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;
533 #if defined TIZEN_EXT
541 apply_p2p_listen_on_iface(wifi, NULL);
543 if (reg_data->callback)
544 reg_data->callback(result, reg_data->user_data);
549 static int peer_register_service(const unsigned char *specification,
550 int specification_length,
551 const unsigned char *query,
552 int query_length, int version,
553 peer_service_registration_cb_t callback,
556 struct peer_service_registration *reg_data;
557 GSupplicantP2PServiceParams *params;
564 if (specification && !version && !query &&
565 is_service_wfd(specification, specification_length)) {
566 return peer_register_wfd_service(specification,
567 specification_length, callback, user_data);
570 reg_data = g_try_malloc0(sizeof(*reg_data));
574 reg_data->callback = callback;
575 reg_data->user_data = user_data;
579 for (list = iface_list; list; list = list->next) {
580 struct wifi_data *wifi = list->data;
581 GSupplicantInterface *iface = wifi->interface;
583 if (!g_supplicant_interface_has_p2p(iface))
586 params = fill_in_peer_service_params(specification,
587 specification_length, query,
588 query_length, version);
595 ret_f = g_supplicant_interface_p2p_add_service(iface,
596 register_peer_service_cb, params, reg_data);
597 if (ret_f == 0 || ret_f == -EINPROGRESS)
601 ret = g_supplicant_interface_p2p_add_service(iface,
602 register_peer_service_cb, params, NULL);
603 if (ret != 0 && ret != -EINPROGRESS)
604 free_peer_service_params(params);
607 if (ret_f != 0 && ret_f != -EINPROGRESS)
613 static int peer_unregister_wfd_service(void)
615 GSupplicantP2PServiceParams *params;
618 if (!wfd_service_registered)
621 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
625 wfd_service_registered = false;
627 g_supplicant_set_widi_ies(params, NULL, NULL);
629 for (list = iface_list; list; list = list->next) {
630 struct wifi_data *wifi = list->data;
632 if (!g_supplicant_interface_has_p2p(wifi->interface))
636 if (!wifi->servicing || wifi->servicing < 0) {
637 g_supplicant_interface_p2p_listen(wifi->interface,
646 static int peer_unregister_service(const unsigned char *specification,
647 int specification_length,
648 const unsigned char *query,
649 int query_length, int version)
651 GSupplicantP2PServiceParams *params;
656 if (specification && !version && !query &&
657 is_service_wfd(specification, specification_length)) {
658 ret = peer_unregister_wfd_service();
659 if (ret != 0 && ret != -EINPROGRESS)
664 for (list = iface_list; list; list = list->next) {
665 struct wifi_data *wifi = list->data;
666 GSupplicantInterface *iface = wifi->interface;
671 if (!g_supplicant_interface_has_p2p(iface))
674 params = fill_in_peer_service_params(specification,
675 specification_length, query,
676 query_length, version);
682 ret = g_supplicant_interface_p2p_del_service(iface, params);
683 if (ret != 0 && ret != -EINPROGRESS)
684 free_peer_service_params(params);
687 if (!wifi->servicing || wifi->servicing < 0) {
688 g_supplicant_interface_p2p_listen(iface, 0, 0);
696 static struct connman_peer_driver peer_driver = {
697 .connect = peer_connect,
698 .disconnect = peer_disconnect,
699 .register_service = peer_register_service,
700 .unregister_service = peer_unregister_service,
703 static void handle_tethering(struct wifi_data *wifi)
705 if (!wifi->tethering)
714 DBG("index %d bridge %s", wifi->index, wifi->bridge);
716 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
719 wifi->bridged = true;
722 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
724 struct connman_device *device = user_data;
725 struct wifi_data *wifi = connman_device_get_data(device);
730 DBG("index %d flags %d change %d", wifi->index, flags, change);
732 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
736 DBG("interface down");
739 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
740 if (flags & IFF_LOWER_UP) {
743 handle_tethering(wifi);
751 static int wifi_probe(struct connman_device *device)
753 struct wifi_data *wifi;
755 DBG("device %p", device);
757 wifi = g_try_new0(struct wifi_data, 1);
761 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
763 connman_device_set_data(device, wifi);
764 wifi->device = connman_device_ref(device);
766 wifi->index = connman_device_get_index(device);
769 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
770 wifi_newlink, device);
771 if (is_p2p_connecting())
772 add_pending_wifi_device(wifi);
774 iface_list = g_list_append(iface_list, wifi);
779 static void remove_networks(struct connman_device *device,
780 struct wifi_data *wifi)
784 for (list = wifi->networks; list; list = list->next) {
785 struct connman_network *network = list->data;
787 connman_device_remove_network(device, network);
788 connman_network_unref(network);
791 g_slist_free(wifi->networks);
792 wifi->networks = NULL;
795 static void reset_autoscan(struct connman_device *device)
797 struct wifi_data *wifi = connman_device_get_data(device);
798 struct autoscan_params *autoscan;
802 if (!wifi || !wifi->autoscan)
805 autoscan = wifi->autoscan;
807 if (autoscan->timeout == 0 && autoscan->interval == 0)
810 g_source_remove(autoscan->timeout);
812 autoscan->timeout = 0;
813 autoscan->interval = 0;
815 connman_device_unref(device);
818 static void stop_autoscan(struct connman_device *device)
820 const struct wifi_data *wifi = connman_device_get_data(device);
822 if (!wifi || !wifi->autoscan)
825 reset_autoscan(device);
827 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
830 static void check_p2p_technology(void)
832 bool p2p_exists = false;
835 for (list = iface_list; list; list = list->next) {
836 struct wifi_data *w = list->data;
839 g_supplicant_interface_has_p2p(w->interface))
844 connman_technology_driver_unregister(&p2p_tech_driver);
845 connman_peer_driver_unregister(&peer_driver);
849 static void wifi_remove(struct connman_device *device)
851 struct wifi_data *wifi = connman_device_get_data(device);
853 DBG("device %p wifi %p", device, wifi);
858 stop_autoscan(device);
860 if (wifi->p2p_device)
861 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
863 iface_list = g_list_remove(iface_list, wifi);
865 check_p2p_technology();
867 remove_pending_wifi_device(wifi);
869 if (wifi->p2p_find_timeout) {
870 g_source_remove(wifi->p2p_find_timeout);
871 connman_device_unref(wifi->device);
874 if (wifi->p2p_connection_timeout)
875 g_source_remove(wifi->p2p_connection_timeout);
877 remove_networks(device, wifi);
879 connman_device_set_powered(device, false);
880 connman_device_set_data(device, NULL);
881 connman_device_unref(wifi->device);
882 connman_rtnl_remove_watch(wifi->watch);
884 g_supplicant_interface_set_data(wifi->interface, NULL);
886 g_supplicant_interface_cancel(wifi->interface);
888 if (wifi->scan_params)
889 g_supplicant_free_scan_params(wifi->scan_params);
891 g_free(wifi->autoscan);
892 g_free(wifi->identifier);
896 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
900 for (iter = list; iter; iter = g_slist_next(iter)) {
901 struct scan_ssid *scan_ssid = iter->data;
903 if (ssid_len == scan_ssid->ssid_len &&
904 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
911 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
912 int freq, GSupplicantScanParams *scan_data,
913 int driver_max_scan_ssids, char *ssid_name)
916 struct scan_ssid *scan_ssid;
918 if ((driver_max_scan_ssids == 0 ||
919 driver_max_scan_ssids > scan_data->num_ssids) &&
920 (hex_ssid || raw_ssid)) {
922 unsigned int j = 0, hex;
925 size_t hex_ssid_len = strlen(hex_ssid);
927 ssid = g_try_malloc0(hex_ssid_len / 2);
931 for (i = 0; i < hex_ssid_len; i += 2) {
932 sscanf(hex_ssid + i, "%02x", &hex);
941 * If we have already added hidden AP to the list,
942 * then do not do it again. This might happen if you have
943 * used or are using multiple wifi cards, so in that case
944 * you might have multiple service files for same AP.
946 if (is_duplicate(scan_data->ssids, ssid, j)) {
952 scan_ssid = g_try_new(struct scan_ssid, 1);
959 memcpy(scan_ssid->ssid, ssid, j);
960 scan_ssid->ssid_len = j;
961 scan_data->ssids = g_slist_prepend(scan_data->ssids,
964 scan_data->num_ssids++;
966 DBG("SSID %s added to scanned list of %d entries", ssid_name,
967 scan_data->num_ssids);
974 scan_data->ssids = g_slist_reverse(scan_data->ssids);
976 if (!scan_data->freqs) {
977 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
978 if (!scan_data->freqs) {
979 g_slist_free_full(scan_data->ssids, g_free);
983 scan_data->num_freqs = 1;
984 scan_data->freqs[0] = freq;
986 bool duplicate = false;
988 /* Don't add duplicate entries */
989 for (i = 0; i < scan_data->num_freqs; i++) {
990 if (scan_data->freqs[i] == freq) {
997 scan_data->num_freqs++;
998 scan_data->freqs = g_try_realloc(scan_data->freqs,
999 sizeof(uint16_t) * scan_data->num_freqs);
1000 if (!scan_data->freqs) {
1001 g_slist_free_full(scan_data->ssids, g_free);
1004 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1011 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1013 struct connman_config_entry **entries;
1019 int num_ssids = 0, add_param_failed = 0;
1021 services = connman_storage_get_services();
1022 for (i = 0; services && services[i]; i++) {
1023 if (strncmp(services[i], "wifi_", 5) != 0)
1026 keyfile = connman_storage_load_service(services[i]);
1030 value = g_key_file_get_boolean(keyfile,
1031 services[i], "Hidden", NULL);
1033 g_key_file_free(keyfile);
1037 value = g_key_file_get_boolean(keyfile,
1038 services[i], "Favorite", NULL);
1040 g_key_file_free(keyfile);
1044 #if defined TIZEN_EXT
1045 value = g_key_file_get_boolean(keyfile,
1046 services[i], "AutoConnect", NULL);
1048 g_key_file_free(keyfile);
1053 ssid = g_key_file_get_string(keyfile,
1054 services[i], "SSID", NULL);
1056 name = g_key_file_get_string(keyfile, services[i], "Name",
1059 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1067 g_key_file_free(keyfile);
1071 * Check if there are any hidden AP that needs to be provisioned.
1073 entries = connman_config_get_entries("wifi");
1074 for (i = 0; entries && entries[i]; i++) {
1077 if (!entries[i]->hidden)
1080 if (!entries[i]->ssid) {
1081 ssid = entries[i]->name;
1084 ssid = entries[i]->ssid;
1085 len = entries[i]->ssid_len;
1091 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1098 connman_config_free_entries(entries);
1100 if (add_param_failed > 0)
1101 DBG("Unable to scan %d out of %d SSIDs",
1102 add_param_failed, num_ssids);
1104 g_strfreev(services);
1109 static int get_hidden_connections_params(struct wifi_data *wifi,
1110 GSupplicantScanParams *scan_params)
1112 int driver_max_ssids, i;
1113 GSupplicantScanParams *orig_params;
1116 * Scan hidden networks so that we can autoconnect to them.
1117 * We will assume 1 as a default number of ssid to scan.
1119 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1121 if (driver_max_ssids == 0)
1122 driver_max_ssids = 1;
1124 DBG("max ssids %d", driver_max_ssids);
1126 if (!wifi->scan_params) {
1127 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1128 if (!wifi->scan_params)
1131 if (get_hidden_connections(wifi->scan_params) == 0) {
1132 g_supplicant_free_scan_params(wifi->scan_params);
1133 wifi->scan_params = NULL;
1139 orig_params = wifi->scan_params;
1141 /* Let's transfer driver_max_ssids params */
1142 for (i = 0; i < driver_max_ssids; i++) {
1143 struct scan_ssid *ssid;
1145 if (!wifi->scan_params->ssids)
1148 ssid = orig_params->ssids->data;
1149 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1150 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1154 scan_params->num_ssids = i;
1155 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1157 scan_params->freqs = g_memdup(orig_params->freqs,
1158 sizeof(uint16_t) * orig_params->num_freqs);
1159 if (!scan_params->freqs)
1162 scan_params->num_freqs = orig_params->num_freqs;
1167 orig_params->num_ssids -= scan_params->num_ssids;
1169 return scan_params->num_ssids;
1172 g_slist_free_full(scan_params->ssids, g_free);
1173 g_supplicant_free_scan_params(wifi->scan_params);
1174 wifi->scan_params = NULL;
1179 static int throw_wifi_scan(struct connman_device *device,
1180 GSupplicantInterfaceCallback callback)
1182 struct wifi_data *wifi = connman_device_get_data(device);
1188 DBG("device %p %p", device, wifi->interface);
1190 if (wifi->tethering)
1192 #if defined TIZEN_EXT
1193 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1195 if (connman_device_get_scanning(device))
1199 connman_device_ref(device);
1201 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1204 connman_device_set_scanning(device,
1205 CONNMAN_SERVICE_TYPE_WIFI, true);
1207 connman_device_unref(device);
1212 static void hidden_free(struct hidden_params *hidden)
1217 if (hidden->scan_params)
1218 g_supplicant_free_scan_params(hidden->scan_params);
1219 g_free(hidden->identity);
1220 g_free(hidden->passphrase);
1221 g_free(hidden->security);
1225 #if defined TIZEN_EXT
1226 static void service_state_changed(struct connman_service *service,
1227 enum connman_service_state state);
1229 static int network_connect(struct connman_network *network);
1231 static struct connman_notifier notifier = {
1233 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1234 .service_state_changed = service_state_changed,
1237 static void service_state_changed(struct connman_service *service,
1238 enum connman_service_state state)
1240 enum connman_service_type type;
1242 type = connman_service_get_type(service);
1243 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1246 DBG("service %p state %d", service, state);
1249 case CONNMAN_SERVICE_STATE_READY:
1250 case CONNMAN_SERVICE_STATE_ONLINE:
1251 case CONNMAN_SERVICE_STATE_FAILURE:
1252 connman_notifier_unregister(¬ifier);
1253 is_wifi_notifier_registered = FALSE;
1255 __connman_device_request_scan(type);
1264 static void scan_callback(int result, GSupplicantInterface *interface,
1267 struct connman_device *device = user_data;
1268 struct wifi_data *wifi = connman_device_get_data(device);
1271 DBG("result %d wifi %p", result, wifi);
1274 if (wifi->hidden && !wifi->postpone_hidden) {
1275 connman_network_clear_hidden(wifi->hidden->user_data);
1276 hidden_free(wifi->hidden);
1277 wifi->hidden = NULL;
1280 if (wifi->scan_params) {
1281 g_supplicant_free_scan_params(wifi->scan_params);
1282 wifi->scan_params = NULL;
1287 connman_device_reset_scanning(device);
1289 /* User is connecting to a hidden AP, let's wait for finished event */
1290 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1291 GSupplicantScanParams *scan_params;
1294 wifi->postpone_hidden = false;
1295 scan_params = wifi->hidden->scan_params;
1296 wifi->hidden->scan_params = NULL;
1298 reset_autoscan(device);
1300 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1301 scan_callback, device);
1305 /* On error, let's recall scan_callback, which will cleanup */
1306 return scan_callback(ret, interface, user_data);
1309 #if defined TIZEN_EXT
1310 if (wifi && wifi->allow_full_scan) {
1312 DBG("Trigger Full Channel Scan");
1313 wifi->allow_full_scan = FALSE;
1315 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1316 scan_callback, device);
1320 /* On error, let's recall scan_callback, which will cleanup */
1321 return scan_callback(ret, interface, user_data);
1325 scanning = connman_device_get_scanning(device);
1327 connman_device_set_scanning(device,
1328 CONNMAN_SERVICE_TYPE_WIFI, false);
1330 if (result != -ENOLINK)
1331 #if defined TIZEN_EXT
1334 start_autoscan(device);
1337 * If we are here then we were scanning; however, if we are
1338 * also mid-flight disabling the interface, then wifi_disable
1339 * has already cleared the device scanning state and
1340 * unreferenced the device, obviating the need to do it here.
1344 connman_device_unref(device);
1346 #if defined TIZEN_EXT
1347 if (wifi && wifi->scan_pending_network && result != -EIO) {
1348 network_connect(wifi->scan_pending_network);
1349 wifi->scan_pending_network = NULL;
1350 connman_network_set_connecting(wifi->network);
1353 if (is_wifi_notifier_registered != true &&
1354 wifi_first_scan == true && found_with_first_scan == true) {
1355 wifi_first_scan = false;
1356 found_with_first_scan = false;
1358 connman_notifier_register(¬ifier);
1359 is_wifi_notifier_registered = true;
1364 static void scan_callback_hidden(int result,
1365 GSupplicantInterface *interface, void *user_data)
1367 struct connman_device *device = user_data;
1368 struct wifi_data *wifi = connman_device_get_data(device);
1369 GSupplicantScanParams *scan_params;
1372 DBG("result %d wifi %p", result, wifi);
1377 /* User is trying to connect to a hidden AP */
1378 if (wifi->hidden && wifi->postpone_hidden)
1381 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1385 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1386 ret = g_supplicant_interface_scan(wifi->interface,
1388 scan_callback_hidden,
1394 g_supplicant_free_scan_params(scan_params);
1397 scan_callback(result, interface, user_data);
1400 static gboolean autoscan_timeout(gpointer data)
1402 struct connman_device *device = data;
1403 struct wifi_data *wifi = connman_device_get_data(device);
1404 struct autoscan_params *autoscan;
1410 autoscan = wifi->autoscan;
1412 if (autoscan->interval <= 0) {
1413 interval = autoscan->base;
1416 interval = autoscan->interval * autoscan->base;
1418 #if defined TIZEN_EXT
1419 if (autoscan->interval >= autoscan->limit)
1421 if (interval > autoscan->limit)
1423 interval = autoscan->limit;
1425 throw_wifi_scan(wifi->device, scan_callback_hidden);
1428 DBG("interval %d", interval);
1430 autoscan->interval = interval;
1432 autoscan->timeout = g_timeout_add_seconds(interval,
1433 autoscan_timeout, device);
1438 static void start_autoscan(struct connman_device *device)
1440 struct wifi_data *wifi = connman_device_get_data(device);
1441 struct autoscan_params *autoscan;
1448 if (wifi->p2p_device)
1451 if (wifi->connected)
1454 autoscan = wifi->autoscan;
1458 if (autoscan->timeout > 0 || autoscan->interval > 0)
1461 connman_device_ref(device);
1463 autoscan_timeout(device);
1466 static struct autoscan_params *parse_autoscan_params(const char *params)
1468 struct autoscan_params *autoscan;
1473 DBG("Emulating autoscan");
1475 list_params = g_strsplit(params, ":", 0);
1476 if (list_params == 0)
1479 if (g_strv_length(list_params) < 3) {
1480 g_strfreev(list_params);
1484 base = atoi(list_params[1]);
1485 limit = atoi(list_params[2]);
1487 g_strfreev(list_params);
1489 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1491 DBG("Could not allocate memory for autoscan");
1495 DBG("base %d - limit %d", base, limit);
1496 autoscan->base = base;
1497 autoscan->limit = limit;
1502 static void setup_autoscan(struct wifi_data *wifi)
1504 if (!wifi->autoscan)
1505 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1507 start_autoscan(wifi->device);
1510 static void finalize_interface_creation(struct wifi_data *wifi)
1512 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1514 if (!wifi->device) {
1515 connman_error("WiFi device not set");
1519 connman_device_set_powered(wifi->device, true);
1521 if (!connman_setting_get_bool("BackgroundScanning"))
1524 if (wifi->p2p_device)
1527 setup_autoscan(wifi);
1530 static void interface_create_callback(int result,
1531 GSupplicantInterface *interface,
1534 struct wifi_data *wifi = user_data;
1536 DBG("result %d ifname %s, wifi %p", result,
1537 g_supplicant_interface_get_ifname(interface),
1540 if (result < 0 || !wifi)
1543 wifi->interface = interface;
1544 g_supplicant_interface_set_data(interface, wifi);
1546 if (g_supplicant_interface_get_ready(interface)) {
1547 wifi->interface_ready = true;
1548 finalize_interface_creation(wifi);
1552 static int wifi_enable(struct connman_device *device)
1554 struct wifi_data *wifi = connman_device_get_data(device);
1557 const char *driver = connman_option_get_string("wifi");
1560 DBG("device %p %p", device, wifi);
1562 index = connman_device_get_index(device);
1563 if (!wifi || index < 0)
1566 if (is_p2p_connecting())
1567 return -EINPROGRESS;
1569 interface = connman_inet_ifname(index);
1570 ret = g_supplicant_interface_create(interface, driver, NULL,
1571 interface_create_callback,
1578 return -EINPROGRESS;
1581 static int wifi_disable(struct connman_device *device)
1583 struct wifi_data *wifi = connman_device_get_data(device);
1586 DBG("device %p wifi %p", device, wifi);
1591 wifi->connected = false;
1592 wifi->disconnecting = false;
1594 if (wifi->pending_network)
1595 wifi->pending_network = NULL;
1597 stop_autoscan(device);
1599 if (wifi->p2p_find_timeout) {
1600 g_source_remove(wifi->p2p_find_timeout);
1601 wifi->p2p_find_timeout = 0;
1602 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1603 connman_device_unref(wifi->device);
1606 /* In case of a user scan, device is still referenced */
1607 if (connman_device_get_scanning(device)) {
1608 connman_device_set_scanning(device,
1609 CONNMAN_SERVICE_TYPE_WIFI, false);
1610 connman_device_unref(wifi->device);
1613 remove_networks(device, wifi);
1615 #if defined TIZEN_EXT
1616 wifi->scan_pending_network = NULL;
1618 if (is_wifi_notifier_registered == true) {
1619 connman_notifier_unregister(¬ifier);
1620 is_wifi_notifier_registered = false;
1624 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1628 return -EINPROGRESS;
1631 struct last_connected {
1637 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1639 GTimeVal *aval = (GTimeVal *)a;
1640 GTimeVal *bval = (GTimeVal *)b;
1642 /* Note that the sort order is descending */
1643 if (aval->tv_sec < bval->tv_sec)
1646 if (aval->tv_sec > bval->tv_sec)
1652 static void free_entry(gpointer data)
1654 struct last_connected *entry = data;
1656 g_free(entry->ssid);
1660 static int get_latest_connections(int max_ssids,
1661 GSupplicantScanParams *scan_data)
1663 GSequenceIter *iter;
1664 GSequence *latest_list;
1665 struct last_connected *entry;
1674 latest_list = g_sequence_new(free_entry);
1678 services = connman_storage_get_services();
1679 for (i = 0; services && services[i]; i++) {
1680 if (strncmp(services[i], "wifi_", 5) != 0)
1683 keyfile = connman_storage_load_service(services[i]);
1687 str = g_key_file_get_string(keyfile,
1688 services[i], "Favorite", NULL);
1689 if (!str || g_strcmp0(str, "true")) {
1691 g_key_file_free(keyfile);
1696 str = g_key_file_get_string(keyfile,
1697 services[i], "AutoConnect", NULL);
1698 if (!str || g_strcmp0(str, "true")) {
1700 g_key_file_free(keyfile);
1705 str = g_key_file_get_string(keyfile,
1706 services[i], "Modified", NULL);
1708 g_key_file_free(keyfile);
1711 g_time_val_from_iso8601(str, &modified);
1714 ssid = g_key_file_get_string(keyfile,
1715 services[i], "SSID", NULL);
1717 freq = g_key_file_get_integer(keyfile, services[i],
1720 entry = g_try_new(struct last_connected, 1);
1722 g_sequence_free(latest_list);
1723 g_key_file_free(keyfile);
1729 entry->modified = modified;
1732 g_sequence_insert_sorted(latest_list, entry,
1738 g_key_file_free(keyfile);
1741 g_strfreev(services);
1743 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1745 iter = g_sequence_get_begin_iter(latest_list);
1747 for (i = 0; i < num_ssids; i++) {
1748 entry = g_sequence_get(iter);
1750 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1751 entry->modified.tv_sec);
1753 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1754 max_ssids, entry->ssid);
1756 iter = g_sequence_iter_next(iter);
1759 g_sequence_free(latest_list);
1763 static int wifi_scan_simple(struct connman_device *device)
1765 reset_autoscan(device);
1767 return throw_wifi_scan(device, scan_callback_hidden);
1770 static gboolean p2p_find_stop(gpointer data)
1772 struct connman_device *device = data;
1773 struct wifi_data *wifi = connman_device_get_data(device);
1777 wifi->p2p_find_timeout = 0;
1779 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1781 g_supplicant_interface_p2p_stop_find(wifi->interface);
1783 connman_device_unref(device);
1784 reset_autoscan(device);
1789 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1792 struct connman_device *device = user_data;
1793 struct wifi_data *wifi = connman_device_get_data(device);
1795 DBG("result %d wifi %p", result, wifi);
1797 if (wifi->p2p_find_timeout) {
1798 g_source_remove(wifi->p2p_find_timeout);
1799 wifi->p2p_find_timeout = 0;
1805 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1806 p2p_find_stop, device);
1807 if (!wifi->p2p_find_timeout)
1812 p2p_find_stop(device);
1815 static int p2p_find(struct connman_device *device)
1817 struct wifi_data *wifi;
1822 if (!p2p_technology)
1825 wifi = connman_device_get_data(device);
1827 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1830 reset_autoscan(device);
1831 connman_device_ref(device);
1833 ret = g_supplicant_interface_p2p_find(wifi->interface,
1834 p2p_find_callback, device);
1836 connman_device_unref(device);
1837 start_autoscan(device);
1839 connman_device_set_scanning(device,
1840 CONNMAN_SERVICE_TYPE_P2P, true);
1846 #if defined TIZEN_EXT
1847 static void specific_scan_callback(int result, GSupplicantInterface *interface,
1850 struct connman_device *device = user_data;
1851 struct wifi_data *wifi = connman_device_get_data(device);
1854 DBG("result %d wifi %p", result, wifi);
1856 if (wifi && wifi->scan_params) {
1857 g_supplicant_free_scan_params(wifi->scan_params);
1858 wifi->scan_params = NULL;
1861 scanning = connman_device_get_scanning(device);
1863 connman_device_set_scanning(device,
1864 CONNMAN_SERVICE_TYPE_WIFI, false);
1865 connman_device_unref(device);
1869 static int wifi_specific_scan(enum connman_service_type type,
1870 struct connman_device *device, int scan_type,
1871 GSList *specific_scan_list, void *user_data)
1873 GSList *list = NULL;
1875 struct wifi_data *wifi = connman_device_get_data(device);
1876 GSupplicantScanParams *scan_params = NULL;
1877 struct scan_ssid *scan_ssid = NULL;
1886 if (wifi->p2p_device)
1889 if (type == CONNMAN_SERVICE_TYPE_P2P)
1890 return p2p_find(device);
1892 if (wifi->tethering)
1895 scanning = connman_device_get_scanning(device);
1899 DBG("scan_type: %d", scan_type);
1900 if (scan_type == 1) { /* ssid based scan */
1901 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1903 DBG("Failed to allocate memory.");
1907 for (list = specific_scan_list; list; list = list->next) {
1908 ssid = (char *)list->data;
1909 int ssid_len = strlen(ssid);
1911 scan_ssid = g_try_new0(struct scan_ssid, 1);
1913 DBG("Failed to allocate memory.");
1914 g_supplicant_free_scan_params(scan_params);
1918 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
1919 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
1920 scan_ssid->ssid_len = ssid_len;
1921 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
1924 scan_params->num_ssids = count;
1926 } else if (scan_type == 2) { /* frequency based scan */
1928 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1930 DBG("Failed to allocate memory.");
1934 guint num_freqs = g_slist_length(specific_scan_list);
1935 DBG("num_freqs: %d", num_freqs);
1937 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
1938 if (!scan_params->freqs) {
1939 DBG("Failed to allocate memory.");
1940 g_free(scan_params);
1945 for (list = specific_scan_list; list; list = list->next) {
1946 freq = (int)list->data;
1948 scan_params->freqs[count] = freq;
1949 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
1952 scan_params->num_freqs = count;
1955 DBG("Invalid scan");
1959 reset_autoscan(device);
1960 connman_device_ref(device);
1962 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1963 specific_scan_callback, device);
1966 connman_device_set_scanning(device,
1967 CONNMAN_SERVICE_TYPE_WIFI, true);
1969 g_supplicant_free_scan_params(scan_params);
1970 connman_device_unref(device);
1978 * Note that the hidden scan is only used when connecting to this specific
1979 * hidden AP first time. It is not used when system autoconnects to hidden AP.
1981 static int wifi_scan(enum connman_service_type type,
1982 struct connman_device *device,
1983 const char *ssid, unsigned int ssid_len,
1984 const char *identity, const char* passphrase,
1985 const char *security, void *user_data)
1987 struct wifi_data *wifi = connman_device_get_data(device);
1988 GSupplicantScanParams *scan_params = NULL;
1989 struct scan_ssid *scan_ssid;
1990 struct hidden_params *hidden;
1992 int driver_max_ssids = 0;
1999 if (wifi->p2p_device)
2002 if (type == CONNMAN_SERVICE_TYPE_P2P)
2003 return p2p_find(device);
2005 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2007 if (wifi->tethering)
2010 scanning = connman_device_get_scanning(device);
2012 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2016 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2018 DBG("max ssids %d", driver_max_ssids);
2019 if (driver_max_ssids == 0)
2020 return wifi_scan_simple(device);
2024 if (scanning && wifi->hidden && wifi->postpone_hidden)
2030 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2035 scan_ssid = g_try_new(struct scan_ssid, 1);
2037 g_free(scan_params);
2041 memcpy(scan_ssid->ssid, ssid, ssid_len);
2042 scan_ssid->ssid_len = ssid_len;
2043 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2045 scan_params->num_ssids = 1;
2047 hidden = g_try_new0(struct hidden_params, 1);
2049 g_supplicant_free_scan_params(scan_params);
2054 hidden_free(wifi->hidden);
2055 wifi->hidden = NULL;
2058 memcpy(hidden->ssid, ssid, ssid_len);
2059 hidden->ssid_len = ssid_len;
2060 hidden->identity = g_strdup(identity);
2061 hidden->passphrase = g_strdup(passphrase);
2062 hidden->security = g_strdup(security);
2063 hidden->user_data = user_data;
2064 wifi->hidden = hidden;
2067 /* Let's keep this active scan for later,
2068 * when current scan will be over. */
2069 wifi->postpone_hidden = TRUE;
2070 hidden->scan_params = scan_params;
2074 } else if (wifi->connected) {
2075 g_supplicant_free_scan_params(scan_params);
2076 return wifi_scan_simple(device);
2078 ret = get_latest_connections(driver_max_ssids, scan_params);
2080 g_supplicant_free_scan_params(scan_params);
2081 return wifi_scan_simple(device);
2085 connman_device_ref(device);
2087 reset_autoscan(device);
2089 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2090 scan_callback, device);
2093 connman_device_set_scanning(device,
2094 CONNMAN_SERVICE_TYPE_WIFI, true);
2095 #if defined TIZEN_EXT
2096 /*To allow the Full Scan after ssid based scan, set the flag here
2097 It is required because Tizen does not use the ConnMan specific
2098 backgroung Scan feature.Tizen has added the BG Scan feature in
2099 net-config. To sync with up ConnMan, we need to issue the Full Scan
2100 after SSID specific scan.*/
2101 wifi->allow_full_scan = TRUE;
2104 g_supplicant_free_scan_params(scan_params);
2105 connman_device_unref(device);
2108 hidden_free(wifi->hidden);
2109 wifi->hidden = NULL;
2116 static void wifi_regdom_callback(int result,
2120 struct connman_device *device = user_data;
2122 connman_device_regdom_notify(device, result, alpha2);
2124 connman_device_unref(device);
2127 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2129 struct wifi_data *wifi = connman_device_get_data(device);
2135 connman_device_ref(device);
2137 ret = g_supplicant_interface_set_country(wifi->interface,
2138 wifi_regdom_callback,
2141 connman_device_unref(device);
2146 static struct connman_device_driver wifi_ng_driver = {
2148 .type = CONNMAN_DEVICE_TYPE_WIFI,
2149 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2150 .probe = wifi_probe,
2151 .remove = wifi_remove,
2152 .enable = wifi_enable,
2153 .disable = wifi_disable,
2155 .set_regdom = wifi_set_regdom,
2156 #if defined TIZEN_EXT
2157 .specific_scan = wifi_specific_scan,
2161 static void system_ready(void)
2165 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2166 connman_error("Failed to register WiFi driver");
2169 static void system_killed(void)
2173 connman_device_driver_unregister(&wifi_ng_driver);
2176 static int network_probe(struct connman_network *network)
2178 DBG("network %p", network);
2183 static void network_remove(struct connman_network *network)
2185 struct connman_device *device = connman_network_get_device(network);
2186 struct wifi_data *wifi;
2188 DBG("network %p", network);
2190 wifi = connman_device_get_data(device);
2194 if (wifi->network != network)
2197 wifi->network = NULL;
2199 #if defined TIZEN_EXT
2200 wifi->disconnecting = false;
2202 if (wifi->pending_network == network)
2203 wifi->pending_network = NULL;
2205 if (wifi->scan_pending_network == network)
2206 wifi->scan_pending_network = NULL;
2210 static void connect_callback(int result, GSupplicantInterface *interface,
2213 #if defined TIZEN_EXT
2215 struct wifi_data *wifi;
2217 struct connman_network *network = user_data;
2219 DBG("network %p result %d", network, result);
2221 #if defined TIZEN_EXT
2222 for (list = iface_list; list; list = list->next) {
2225 if (wifi && wifi->network == network)
2229 /* wifi_data may be invalid because wifi is already disabled */
2234 if (result == -ENOKEY) {
2235 connman_network_set_error(network,
2236 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2237 } else if (result < 0) {
2238 connman_network_set_error(network,
2239 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2242 connman_network_unref(network);
2245 static GSupplicantSecurity network_security(const char *security)
2247 if (g_str_equal(security, "none"))
2248 return G_SUPPLICANT_SECURITY_NONE;
2249 else if (g_str_equal(security, "wep"))
2250 return G_SUPPLICANT_SECURITY_WEP;
2251 else if (g_str_equal(security, "psk"))
2252 return G_SUPPLICANT_SECURITY_PSK;
2253 else if (g_str_equal(security, "wpa"))
2254 return G_SUPPLICANT_SECURITY_PSK;
2255 else if (g_str_equal(security, "rsn"))
2256 return G_SUPPLICANT_SECURITY_PSK;
2257 else if (g_str_equal(security, "ieee8021x"))
2258 return G_SUPPLICANT_SECURITY_IEEE8021X;
2259 #if defined TIZEN_EXT
2260 else if (g_str_equal(security, "ft_psk") == TRUE)
2261 return G_SUPPLICANT_SECURITY_FT_PSK;
2262 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2263 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2266 return G_SUPPLICANT_SECURITY_UNKNOWN;
2269 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2271 const char *security;
2273 memset(ssid, 0, sizeof(*ssid));
2274 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2275 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2277 ssid->scan_ssid = 1;
2278 security = connman_network_get_string(network, "WiFi.Security");
2279 ssid->security = network_security(security);
2280 ssid->passphrase = connman_network_get_string(network,
2283 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2286 * If our private key password is unset,
2287 * we use the supplied passphrase. That is needed
2288 * for PEAP where 2 passphrases (identity and client
2289 * cert may have to be provided.
2291 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2292 connman_network_set_string(network,
2293 "WiFi.PrivateKeyPassphrase",
2295 /* We must have an identity for both PEAP and TLS */
2296 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2298 /* Use agent provided identity as a fallback */
2299 if (!ssid->identity || strlen(ssid->identity) == 0)
2300 ssid->identity = connman_network_get_string(network,
2301 "WiFi.AgentIdentity");
2303 ssid->ca_cert_path = connman_network_get_string(network,
2305 ssid->client_cert_path = connman_network_get_string(network,
2306 "WiFi.ClientCertFile");
2307 ssid->private_key_path = connman_network_get_string(network,
2308 "WiFi.PrivateKeyFile");
2309 ssid->private_key_passphrase = connman_network_get_string(network,
2310 "WiFi.PrivateKeyPassphrase");
2311 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2313 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2314 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2316 #if defined TIZEN_EXT
2317 ssid->bssid = connman_network_get_bssid(network);
2319 #if defined TIZEN_EXT
2320 ssid->freq = connman_network_get_frequency(network);
2323 if (connman_setting_get_bool("BackgroundScanning"))
2324 ssid->bgscan = BGSCAN_DEFAULT;
2327 static int network_connect(struct connman_network *network)
2329 struct connman_device *device = connman_network_get_device(network);
2330 struct wifi_data *wifi;
2331 GSupplicantInterface *interface;
2332 GSupplicantSSID *ssid;
2334 DBG("network %p", network);
2339 wifi = connman_device_get_data(device);
2343 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2347 interface = wifi->interface;
2349 ssid_init(ssid, network);
2351 if (wifi->disconnecting) {
2352 wifi->pending_network = network;
2355 wifi->network = connman_network_ref(network);
2357 #if defined TIZEN_EXT
2358 wifi->scan_pending_network = NULL;
2361 return g_supplicant_interface_connect(interface, ssid,
2362 connect_callback, network);
2365 return -EINPROGRESS;
2368 static void disconnect_callback(int result, GSupplicantInterface *interface,
2371 #if defined TIZEN_EXT
2373 struct wifi_data *wifi;
2374 struct connman_network *network = user_data;
2376 DBG("network %p result %d", network, result);
2378 for (list = iface_list; list; list = list->next) {
2381 if (wifi->network == NULL && wifi->disconnecting == true)
2382 wifi->disconnecting = false;
2384 if (wifi->network == network)
2388 /* wifi_data may be invalid because wifi is already disabled */
2393 struct wifi_data *wifi = user_data;
2396 DBG("result %d supplicant interface %p wifi %p",
2397 result, interface, wifi);
2399 if (result == -ECONNABORTED) {
2400 DBG("wifi interface no longer available");
2404 if (wifi->network) {
2406 * if result < 0 supplican return an error because
2407 * the network is not current.
2408 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2409 * failed, call connman_network_set_connected to report
2410 * disconnect is completed.
2413 connman_network_set_connected(wifi->network, false);
2416 wifi->network = NULL;
2418 wifi->disconnecting = false;
2420 if (wifi->pending_network) {
2421 network_connect(wifi->pending_network);
2422 wifi->pending_network = NULL;
2425 start_autoscan(wifi->device);
2428 static int network_disconnect(struct connman_network *network)
2430 struct connman_device *device = connman_network_get_device(network);
2431 struct wifi_data *wifi;
2433 #if defined TIZEN_EXT
2434 struct connman_service *service;
2437 DBG("network %p", network);
2439 wifi = connman_device_get_data(device);
2440 if (!wifi || !wifi->interface)
2443 #if defined TIZEN_EXT
2444 if (connman_network_get_associating(network) == true) {
2445 connman_network_clear_associating(network);
2446 connman_network_set_bool(network, "WiFi.UseWPS", false);
2448 service = connman_service_lookup_from_network(network);
2450 if (service != NULL &&
2451 (__connman_service_is_connected_state(service,
2452 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2453 __connman_service_is_connected_state(service,
2454 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2455 (connman_service_get_favorite(service) == false))
2456 __connman_service_set_passphrase(service, NULL);
2459 if (wifi->pending_network == network)
2460 wifi->pending_network = NULL;
2462 if (wifi->scan_pending_network == network)
2463 wifi->scan_pending_network = NULL;
2466 connman_network_set_associating(network, false);
2468 if (wifi->disconnecting)
2471 wifi->disconnecting = true;
2473 #if defined TIZEN_EXT
2474 err = g_supplicant_interface_disconnect(wifi->interface,
2475 disconnect_callback, network);
2477 err = g_supplicant_interface_disconnect(wifi->interface,
2478 disconnect_callback, wifi);
2482 wifi->disconnecting = false;
2487 static struct connman_network_driver network_driver = {
2489 .type = CONNMAN_NETWORK_TYPE_WIFI,
2490 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2491 .probe = network_probe,
2492 .remove = network_remove,
2493 .connect = network_connect,
2494 .disconnect = network_disconnect,
2497 static void interface_added(GSupplicantInterface *interface)
2499 const char *ifname = g_supplicant_interface_get_ifname(interface);
2500 const char *driver = g_supplicant_interface_get_driver(interface);
2501 struct wifi_data *wifi;
2503 wifi = g_supplicant_interface_get_data(interface);
2505 wifi = get_pending_wifi_data(ifname);
2509 g_supplicant_interface_set_data(interface, wifi);
2510 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2511 wifi->p2p_device = true;
2514 DBG("ifname %s driver %s wifi %p tethering %d",
2515 ifname, driver, wifi, wifi->tethering);
2517 if (!wifi->device) {
2518 connman_error("WiFi device not set");
2522 connman_device_set_powered(wifi->device, true);
2525 static bool is_idle(struct wifi_data *wifi)
2527 DBG("state %d", wifi->state);
2529 switch (wifi->state) {
2530 case G_SUPPLICANT_STATE_UNKNOWN:
2531 case G_SUPPLICANT_STATE_DISABLED:
2532 case G_SUPPLICANT_STATE_DISCONNECTED:
2533 case G_SUPPLICANT_STATE_INACTIVE:
2534 case G_SUPPLICANT_STATE_SCANNING:
2537 case G_SUPPLICANT_STATE_AUTHENTICATING:
2538 case G_SUPPLICANT_STATE_ASSOCIATING:
2539 case G_SUPPLICANT_STATE_ASSOCIATED:
2540 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2541 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2542 case G_SUPPLICANT_STATE_COMPLETED:
2549 static bool is_idle_wps(GSupplicantInterface *interface,
2550 struct wifi_data *wifi)
2552 /* First, let's check if WPS processing did not went wrong */
2553 if (g_supplicant_interface_get_wps_state(interface) ==
2554 G_SUPPLICANT_WPS_STATE_FAIL)
2557 /* Unlike normal connection, being associated while processing wps
2558 * actually means that we are idling. */
2559 switch (wifi->state) {
2560 case G_SUPPLICANT_STATE_UNKNOWN:
2561 case G_SUPPLICANT_STATE_DISABLED:
2562 case G_SUPPLICANT_STATE_DISCONNECTED:
2563 case G_SUPPLICANT_STATE_INACTIVE:
2564 case G_SUPPLICANT_STATE_SCANNING:
2565 case G_SUPPLICANT_STATE_ASSOCIATED:
2567 case G_SUPPLICANT_STATE_AUTHENTICATING:
2568 case G_SUPPLICANT_STATE_ASSOCIATING:
2569 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2570 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2571 case G_SUPPLICANT_STATE_COMPLETED:
2578 static bool handle_wps_completion(GSupplicantInterface *interface,
2579 struct connman_network *network,
2580 struct connman_device *device,
2581 struct wifi_data *wifi)
2585 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2587 const unsigned char *ssid, *wps_ssid;
2588 unsigned int ssid_len, wps_ssid_len;
2589 const char *wps_key;
2591 /* Checking if we got associated with requested
2593 ssid = connman_network_get_blob(network, "WiFi.SSID",
2596 wps_ssid = g_supplicant_interface_get_wps_ssid(
2597 interface, &wps_ssid_len);
2599 if (!wps_ssid || wps_ssid_len != ssid_len ||
2600 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2601 connman_network_set_associating(network, false);
2602 #if defined TIZEN_EXT
2603 g_supplicant_interface_disconnect(wifi->interface,
2604 disconnect_callback, wifi->network);
2606 connman_network_set_bool(network, "WiFi.UseWPS", false);
2607 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2609 g_supplicant_interface_disconnect(wifi->interface,
2610 disconnect_callback, wifi);
2615 wps_key = g_supplicant_interface_get_wps_key(interface);
2616 connman_network_set_string(network, "WiFi.Passphrase",
2619 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2625 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2626 struct connman_network *network,
2627 struct wifi_data *wifi)
2629 #if defined TIZEN_EXT
2630 const char *security;
2631 struct connman_service *service;
2633 if (wifi->connected)
2636 security = connman_network_get_string(network, "WiFi.Security");
2638 if (security && g_str_equal(security, "ieee8021x") == true &&
2639 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2641 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2646 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2649 struct connman_service *service;
2651 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2654 if (wifi->connected)
2658 service = connman_service_lookup_from_network(network);
2664 if (connman_service_get_favorite(service)) {
2665 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2670 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2675 #if defined TIZEN_EXT
2676 static bool handle_wifi_assoc_retry(struct connman_network *network,
2677 struct wifi_data *wifi)
2679 const char *security;
2681 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2682 connman_network_get_connecting(network) != true) {
2683 wifi->assoc_retry_count = 0;
2687 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2688 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2689 wifi->assoc_retry_count = 0;
2693 security = connman_network_get_string(network, "WiFi.Security");
2694 if (security && g_str_equal(security, "ieee8021x") == true &&
2695 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2696 wifi->assoc_retry_count = 0;
2700 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2701 wifi->assoc_retry_count = 0;
2703 /* Honestly it's not an invalid-key error,
2704 * however QA team recommends that the invalid-key error
2705 * might be better to display for user experience.
2707 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2716 static void interface_state(GSupplicantInterface *interface)
2718 struct connman_network *network;
2719 struct connman_device *device;
2720 struct wifi_data *wifi;
2721 GSupplicantState state = g_supplicant_interface_get_state(interface);
2724 wifi = g_supplicant_interface_get_data(interface);
2726 DBG("wifi %p interface state %d", wifi, state);
2731 device = wifi->device;
2735 if (g_supplicant_interface_get_ready(interface) &&
2736 !wifi->interface_ready) {
2737 wifi->interface_ready = true;
2738 finalize_interface_creation(wifi);
2741 network = wifi->network;
2746 case G_SUPPLICANT_STATE_SCANNING:
2749 case G_SUPPLICANT_STATE_AUTHENTICATING:
2750 case G_SUPPLICANT_STATE_ASSOCIATING:
2751 #if defined TIZEN_EXT
2752 reset_autoscan(device);
2754 stop_autoscan(device);
2757 if (!wifi->connected)
2758 connman_network_set_associating(network, true);
2762 case G_SUPPLICANT_STATE_COMPLETED:
2763 #if defined TIZEN_EXT
2764 /* though it should be already reset: */
2765 reset_autoscan(device);
2767 wifi->assoc_retry_count = 0;
2769 wifi->scan_pending_network = NULL;
2771 /* should be cleared scanning flag */
2772 bool scanning = connman_device_get_scanning(device);
2774 connman_device_set_scanning(device,
2775 CONNMAN_SERVICE_TYPE_WIFI, false);
2776 connman_device_unref(device);
2779 /* though it should be already stopped: */
2780 stop_autoscan(device);
2783 if (!handle_wps_completion(interface, network, device, wifi))
2786 connman_network_set_connected(network, true);
2787 wifi->disconnect_code = 0;
2790 case G_SUPPLICANT_STATE_DISCONNECTED:
2792 * If we're in one of the idle modes, we have
2793 * not started association yet and thus setting
2794 * those ones to FALSE could cancel an association
2797 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2799 if (is_idle_wps(interface, wifi))
2805 /* If previous state was 4way-handshake, then
2806 * it's either: psk was incorrect and thus we retry
2807 * or if we reach the maximum retries we declare the
2809 if (handle_4way_handshake_failure(interface,
2813 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2814 switch (wifi->disconnect_code) {
2815 case 1: /* Unspecified reason */
2816 /* Let's assume it's because we got blocked */
2818 case 6: /* Class 2 frame received from nonauthenticated STA */
2819 connman_network_set_error(network,
2820 CONNMAN_NETWORK_ERROR_BLOCKED);
2828 /* We disable the selected network, if not then
2829 * wpa_supplicant will loop retrying */
2830 if (g_supplicant_interface_enable_selected_network(interface,
2832 DBG("Could not disables selected network");
2834 #if defined TIZEN_EXT
2837 err = g_supplicant_interface_remove_network(wifi->interface);
2839 DBG("Failed to remove network(%d)", err);
2842 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2843 * Retry association until its retry count is expired */
2844 if (handle_wifi_assoc_retry(network, wifi) == true) {
2845 throw_wifi_scan(wifi->device, scan_callback);
2846 wifi->scan_pending_network = wifi->network;
2850 if(wifi->disconnect_code > 0){
2851 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2852 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
2855 /* To avoid unnecessary repeated association in wpa_supplicant,
2856 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2857 if (wps != true && wifi->network && wifi->disconnecting == false) {
2858 wifi->disconnecting = true;
2859 err = g_supplicant_interface_disconnect(wifi->interface,
2860 disconnect_callback, wifi->network);
2862 wifi->disconnecting = false;
2864 connman_network_set_connected(network, false);
2865 connman_network_set_associating(network, false);
2867 start_autoscan(device);
2873 connman_network_set_connected(network, false);
2874 connman_network_set_associating(network, false);
2875 wifi->disconnecting = false;
2877 start_autoscan(device);
2881 case G_SUPPLICANT_STATE_INACTIVE:
2882 #if defined TIZEN_EXT
2883 if (handle_wps_completion(interface, network, device, wifi) == false)
2886 connman_network_set_associating(network, false);
2887 start_autoscan(device);
2891 case G_SUPPLICANT_STATE_UNKNOWN:
2892 case G_SUPPLICANT_STATE_DISABLED:
2893 case G_SUPPLICANT_STATE_ASSOCIATED:
2894 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2895 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2899 wifi->state = state;
2901 /* Saving wpa_s state policy:
2902 * If connected and if the state changes are roaming related:
2903 * --> We stay connected
2905 * --> We are connected
2907 * --> We are not connected
2910 #if defined TIZEN_EXT
2911 case G_SUPPLICANT_STATE_SCANNING:
2914 case G_SUPPLICANT_STATE_AUTHENTICATING:
2915 case G_SUPPLICANT_STATE_ASSOCIATING:
2916 case G_SUPPLICANT_STATE_ASSOCIATED:
2917 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2918 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2919 if (wifi->connected)
2920 connman_warn("Probably roaming right now!"
2921 " Staying connected...");
2923 wifi->connected = false;
2925 case G_SUPPLICANT_STATE_COMPLETED:
2926 wifi->connected = true;
2929 wifi->connected = false;
2936 static void interface_removed(GSupplicantInterface *interface)
2938 const char *ifname = g_supplicant_interface_get_ifname(interface);
2939 struct wifi_data *wifi;
2941 DBG("ifname %s", ifname);
2943 wifi = g_supplicant_interface_get_data(interface);
2946 wifi->interface = NULL;
2948 if (wifi && wifi->tethering)
2951 if (!wifi || !wifi->device) {
2952 DBG("wifi interface already removed");
2956 connman_device_set_powered(wifi->device, false);
2958 check_p2p_technology();
2961 static void set_device_type(const char *type, char dev_type[17])
2963 const char *oui = "0050F204";
2964 const char *category = "0100";
2965 const char *sub_category = "0000";
2967 if (!g_strcmp0(type, "handset")) {
2969 sub_category = "0500";
2970 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2971 sub_category = "0100";
2972 else if (!g_strcmp0(type, "server"))
2973 sub_category = "0200";
2974 else if (!g_strcmp0(type, "laptop"))
2975 sub_category = "0500";
2976 else if (!g_strcmp0(type, "desktop"))
2977 sub_category = "0600";
2978 else if (!g_strcmp0(type, "tablet"))
2979 sub_category = "0900";
2980 else if (!g_strcmp0(type, "watch"))
2983 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2986 static void p2p_support(GSupplicantInterface *interface)
2988 char dev_type[17] = {};
2989 const char *hostname;
2993 if (!g_supplicant_interface_has_p2p(interface))
2996 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2997 DBG("Could not register P2P technology driver");
3001 hostname = connman_utsname_get_hostname();
3003 hostname = "ConnMan";
3005 set_device_type(connman_machine_get_type(), dev_type);
3006 g_supplicant_interface_set_p2p_device_config(interface,
3007 hostname, dev_type);
3008 connman_peer_driver_register(&peer_driver);
3011 static void scan_started(GSupplicantInterface *interface)
3016 static void scan_finished(GSupplicantInterface *interface)
3018 #if defined TIZEN_EXT
3019 struct wifi_data *wifi;
3020 bool is_associating = false;
3021 static bool is_scanning = true;
3026 #if defined TIZEN_EXT
3027 wifi = g_supplicant_interface_get_data(interface);
3028 if (wifi && wifi->scan_pending_network) {
3029 network_connect(wifi->scan_pending_network);
3030 wifi->scan_pending_network = NULL;
3033 //service state - associating
3034 if(!wifi || !wifi->network)
3037 is_associating = connman_network_get_associating(wifi->network);
3038 if(is_associating && is_scanning){
3039 is_scanning = false;
3040 DBG("send scan for connecting");
3041 throw_wifi_scan(wifi->device, scan_callback);
3052 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3054 unsigned char strength;
3056 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3058 #if !defined TIZEN_EXT
3065 static void network_added(GSupplicantNetwork *supplicant_network)
3067 struct connman_network *network;
3068 GSupplicantInterface *interface;
3069 struct wifi_data *wifi;
3070 const char *name, *identifier, *security, *group, *mode;
3071 const unsigned char *ssid;
3072 unsigned int ssid_len;
3076 bool wps_advertizing;
3078 #if defined TIZEN_EXT
3079 const char *wifi_vsie;
3080 unsigned int wifi_vsie_len;
3083 mode = g_supplicant_network_get_mode(supplicant_network);
3084 identifier = g_supplicant_network_get_identifier(supplicant_network);
3086 DBG("%s", identifier);
3088 if (!g_strcmp0(mode, "adhoc"))
3091 interface = g_supplicant_network_get_interface(supplicant_network);
3092 wifi = g_supplicant_interface_get_data(interface);
3093 name = g_supplicant_network_get_name(supplicant_network);
3094 security = g_supplicant_network_get_security(supplicant_network);
3095 group = g_supplicant_network_get_identifier(supplicant_network);
3096 wps = g_supplicant_network_get_wps(supplicant_network);
3097 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3098 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3099 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3100 supplicant_network);
3105 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3107 #if defined TIZEN_EXT
3108 wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len);
3110 network = connman_device_get_network(wifi->device, identifier);
3113 network = connman_network_create(identifier,
3114 CONNMAN_NETWORK_TYPE_WIFI);
3118 connman_network_set_index(network, wifi->index);
3120 if (connman_device_add_network(wifi->device, network) < 0) {
3121 connman_network_unref(network);
3125 wifi->networks = g_slist_prepend(wifi->networks, network);
3128 if (name && name[0] != '\0')
3129 connman_network_set_name(network, name);
3131 connman_network_set_blob(network, "WiFi.SSID",
3133 #if defined TIZEN_EXT
3134 if(wifi_vsie_len > 0 && wifi_vsie)
3135 connman_network_set_blob(network, "WiFi.Vsie",
3136 wifi_vsie, wifi_vsie_len);
3138 connman_network_set_string(network, "WiFi.Security", security);
3139 connman_network_set_strength(network,
3140 calculate_strength(supplicant_network));
3141 connman_network_set_bool(network, "WiFi.WPS", wps);
3144 /* Is AP advertizing for WPS association?
3145 * If so, we decide to use WPS by default */
3146 if (wps_ready && wps_pbc &&
3148 #if !defined TIZEN_EXT
3149 connman_network_set_bool(network, "WiFi.UseWPS", true);
3151 DBG("wps is activating by ap but ignore it.");
3156 connman_network_set_frequency(network,
3157 g_supplicant_network_get_frequency(supplicant_network));
3158 #if defined TIZEN_EXT
3159 connman_network_set_bssid(network,
3160 g_supplicant_network_get_bssid(supplicant_network));
3161 connman_network_set_maxrate(network,
3162 g_supplicant_network_get_maxrate(supplicant_network));
3163 connman_network_set_enc_mode(network,
3164 g_supplicant_network_get_enc_mode(supplicant_network));
3165 connman_network_set_rsn_mode(network,
3166 g_supplicant_network_get_rsn_mode(supplicant_network));
3167 connman_network_set_keymgmt(network,
3168 g_supplicant_network_get_keymgmt(supplicant_network));
3170 connman_network_set_available(network, true);
3171 connman_network_set_string(network, "WiFi.Mode", mode);
3173 #if defined TIZEN_EXT
3178 connman_network_set_group(network, group);
3180 #if defined TIZEN_EXT
3181 if (wifi_first_scan == true)
3182 found_with_first_scan = true;
3185 if (wifi->hidden && ssid) {
3186 #if defined TIZEN_EXT
3187 if (network_security(wifi->hidden->security) ==
3188 network_security(security) &&
3190 if (!g_strcmp0(wifi->hidden->security, security) &&
3192 wifi->hidden->ssid_len == ssid_len &&
3193 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3194 connman_network_connect_hidden(network,
3195 wifi->hidden->identity,
3196 wifi->hidden->passphrase,
3197 wifi->hidden->user_data);
3198 wifi->hidden->user_data = NULL;
3199 hidden_free(wifi->hidden);
3200 wifi->hidden = NULL;
3205 static void network_removed(GSupplicantNetwork *network)
3207 GSupplicantInterface *interface;
3208 struct wifi_data *wifi;
3209 const char *name, *identifier;
3210 struct connman_network *connman_network;
3212 interface = g_supplicant_network_get_interface(network);
3213 wifi = g_supplicant_interface_get_data(interface);
3214 identifier = g_supplicant_network_get_identifier(network);
3215 name = g_supplicant_network_get_name(network);
3217 DBG("name %s", name);
3222 connman_network = connman_device_get_network(wifi->device, identifier);
3223 if (!connman_network)
3226 #if defined TIZEN_EXT
3227 if (connman_network == wifi->scan_pending_network)
3228 wifi->scan_pending_network = NULL;
3230 if (connman_network == wifi->pending_network)
3231 wifi->pending_network = NULL;
3233 if(connman_network_get_connecting(connman_network) == true){
3234 connman_network_set_connected(connman_network, false);
3238 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3240 connman_device_remove_network(wifi->device, connman_network);
3241 connman_network_unref(connman_network);
3244 static void network_changed(GSupplicantNetwork *network, const char *property)
3246 GSupplicantInterface *interface;
3247 struct wifi_data *wifi;
3248 const char *name, *identifier;
3249 struct connman_network *connman_network;
3251 #if defined TIZEN_EXT
3252 const unsigned char *bssid;
3253 unsigned int maxrate;
3258 interface = g_supplicant_network_get_interface(network);
3259 wifi = g_supplicant_interface_get_data(interface);
3260 identifier = g_supplicant_network_get_identifier(network);
3261 name = g_supplicant_network_get_name(network);
3263 DBG("name %s", name);
3268 connman_network = connman_device_get_network(wifi->device, identifier);
3269 if (!connman_network)
3272 if (g_str_equal(property, "Signal")) {
3273 connman_network_set_strength(connman_network,
3274 calculate_strength(network));
3275 connman_network_update(connman_network);
3278 #if defined TIZEN_EXT
3279 bssid = g_supplicant_network_get_bssid(network);
3280 maxrate = g_supplicant_network_get_maxrate(network);
3281 frequency = g_supplicant_network_get_frequency(network);
3282 wps = g_supplicant_network_get_wps(network);
3284 connman_network_set_bssid(connman_network, bssid);
3285 connman_network_set_maxrate(connman_network, maxrate);
3286 connman_network_set_frequency(connman_network, frequency);
3287 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3291 static void apply_peer_services(GSupplicantPeer *peer,
3292 struct connman_peer *connman_peer)
3294 const unsigned char *data;
3299 connman_peer_reset_services(connman_peer);
3301 data = g_supplicant_peer_get_widi_ies(peer, &length);
3303 connman_peer_add_service(connman_peer,
3304 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3308 static void add_station(const char *mac)
3310 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3314 static void remove_station(const char *mac)
3316 connman_technology_tethering_remove_station(mac);
3319 static void peer_found(GSupplicantPeer *peer)
3321 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3322 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3323 struct connman_peer *connman_peer;
3324 const char *identifier, *name;
3326 #if defined TIZEN_EXT
3330 identifier = g_supplicant_peer_get_identifier(peer);
3331 name = g_supplicant_peer_get_name(peer);
3333 DBG("ident: %s", identifier);
3335 connman_peer = connman_peer_get(wifi->device, identifier);
3339 connman_peer = connman_peer_create(identifier);
3340 connman_peer_set_name(connman_peer, name);
3341 connman_peer_set_device(connman_peer, wifi->device);
3342 apply_peer_services(peer, connman_peer);
3344 ret = connman_peer_register(connman_peer);
3345 if (ret < 0 && ret != -EALREADY)
3346 connman_peer_unref(connman_peer);
3349 static void peer_lost(GSupplicantPeer *peer)
3351 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3352 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3353 struct connman_peer *connman_peer;
3354 const char *identifier;
3359 identifier = g_supplicant_peer_get_identifier(peer);
3361 DBG("ident: %s", identifier);
3363 connman_peer = connman_peer_get(wifi->device, identifier);
3365 if (wifi->p2p_connecting &&
3366 wifi->pending_peer == connman_peer) {
3367 peer_connect_timeout(wifi);
3369 connman_peer_unregister(connman_peer);
3370 connman_peer_unref(connman_peer);
3374 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3376 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3377 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3378 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3379 struct connman_peer *connman_peer;
3380 const char *identifier;
3382 #if defined TIZEN_EXT
3387 identifier = g_supplicant_peer_get_identifier(peer);
3389 DBG("ident: %s", identifier);
3391 connman_peer = connman_peer_get(wifi->device, identifier);
3396 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3397 apply_peer_services(peer, connman_peer);
3398 connman_peer_services_changed(connman_peer);
3400 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3401 if (!g_supplicant_peer_is_in_a_group(peer))
3402 p_state = CONNMAN_PEER_STATE_IDLE;
3404 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3406 case G_SUPPLICANT_PEER_GROUP_STARTED:
3408 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3409 p_state = CONNMAN_PEER_STATE_IDLE;
3411 case G_SUPPLICANT_PEER_GROUP_JOINED:
3412 connman_peer_set_iface_address(connman_peer,
3413 g_supplicant_peer_get_iface_address(peer));
3415 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3416 p_state = CONNMAN_PEER_STATE_IDLE;
3418 case G_SUPPLICANT_PEER_GROUP_FAILED:
3419 if (g_supplicant_peer_has_requested_connection(peer))
3420 p_state = CONNMAN_PEER_STATE_IDLE;
3422 p_state = CONNMAN_PEER_STATE_FAILURE;
3426 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3427 p_state == CONNMAN_PEER_STATE_FAILURE) {
3428 if (wifi->p2p_connecting
3429 && connman_peer == wifi->pending_peer)
3430 peer_cancel_timeout(wifi);
3432 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3435 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3438 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3439 GSupplicantInterface *g_iface;
3440 struct wifi_data *g_wifi;
3442 g_iface = g_supplicant_peer_get_group_interface(peer);
3446 g_wifi = g_supplicant_interface_get_data(g_iface);
3450 connman_peer_set_as_master(connman_peer,
3451 !g_supplicant_peer_is_client(peer));
3452 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3455 connman_peer_set_state(connman_peer, p_state);
3458 static void peer_request(GSupplicantPeer *peer)
3460 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3461 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3462 struct connman_peer *connman_peer;
3463 const char *identifier;
3465 #if defined TIZEN_EXT
3470 identifier = g_supplicant_peer_get_identifier(peer);
3472 DBG("ident: %s", identifier);
3474 connman_peer = connman_peer_get(wifi->device, identifier);
3478 connman_peer_request_connection(connman_peer);
3481 #if defined TIZEN_EXT
3482 static void system_power_off(void)
3485 struct wifi_data *wifi;
3486 struct connman_service *service;
3487 struct connman_ipconfig *ipconfig_ipv4;
3489 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3490 for (list = iface_list; list; list = list->next) {
3493 if (wifi->network != NULL) {
3494 service = connman_service_lookup_from_network(wifi->network);
3495 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3496 __connman_dhcp_stop(ipconfig_ipv4);
3502 static void network_merged(GSupplicantNetwork *network)
3504 GSupplicantInterface *interface;
3505 GSupplicantState state;
3506 struct wifi_data *wifi;
3507 const char *identifier;
3508 struct connman_network *connman_network;
3509 unsigned int ishs20AP = 0;
3512 interface = g_supplicant_network_get_interface(network);
3516 state = g_supplicant_interface_get_state(interface);
3517 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3520 wifi = g_supplicant_interface_get_data(interface);
3524 identifier = g_supplicant_network_get_identifier(network);
3526 connman_network = connman_device_get_network(wifi->device, identifier);
3527 if (!connman_network)
3530 DBG("merged identifier %s", identifier);
3532 if (wifi->connected == FALSE) {
3534 case G_SUPPLICANT_STATE_AUTHENTICATING:
3535 case G_SUPPLICANT_STATE_ASSOCIATING:
3536 case G_SUPPLICANT_STATE_ASSOCIATED:
3537 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3538 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3539 connman_network_set_associating(connman_network, TRUE);
3541 case G_SUPPLICANT_STATE_COMPLETED:
3542 connman_network_set_connected(connman_network, TRUE);
3545 DBG("Not handled the state : %d", state);
3550 ishs20AP = g_supplicant_network_is_hs20AP(network);
3551 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3554 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3555 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3556 connman_network_set_string(connman_network, "WiFi.EAP",
3558 connman_network_set_string(connman_network, "WiFi.Identity",
3559 g_supplicant_network_get_identity(network));
3560 connman_network_set_string(connman_network, "WiFi.Phase2",
3561 g_supplicant_network_get_phase2(network));
3566 wifi->network = connman_network;
3570 static void debug(const char *str)
3572 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3573 connman_debug("%s", str);
3576 static void disconnect_reasoncode(GSupplicantInterface *interface,
3579 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3582 wifi->disconnect_code = reasoncode;
3587 static const GSupplicantCallbacks callbacks = {
3588 .system_ready = system_ready,
3589 .system_killed = system_killed,
3590 .interface_added = interface_added,
3591 .interface_state = interface_state,
3592 .interface_removed = interface_removed,
3593 .p2p_support = p2p_support,
3594 .scan_started = scan_started,
3595 .scan_finished = scan_finished,
3596 .network_added = network_added,
3597 .network_removed = network_removed,
3598 .network_changed = network_changed,
3599 .add_station = add_station,
3600 .remove_station = remove_station,
3601 .peer_found = peer_found,
3602 .peer_lost = peer_lost,
3603 .peer_changed = peer_changed,
3604 .peer_request = peer_request,
3605 #if defined TIZEN_EXT
3606 .system_power_off = system_power_off,
3607 .network_merged = network_merged,
3609 .disconnect_reasoncode = disconnect_reasoncode,
3614 static int tech_probe(struct connman_technology *technology)
3616 wifi_technology = technology;
3621 static void tech_remove(struct connman_technology *technology)
3623 wifi_technology = NULL;
3626 struct wifi_tethering_info {
3627 struct wifi_data *wifi;
3628 struct connman_technology *technology;
3630 GSupplicantSSID *ssid;
3633 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3634 const char *passphrase, bool hidden)
3636 GSupplicantSSID *ap;
3638 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3642 ap->mode = G_SUPPLICANT_MODE_MASTER;
3644 ap->ssid_len = strlen(ssid);
3648 if (!passphrase || strlen(passphrase) == 0) {
3649 ap->security = G_SUPPLICANT_SECURITY_NONE;
3650 ap->passphrase = NULL;
3652 ap->security = G_SUPPLICANT_SECURITY_PSK;
3653 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3654 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3655 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3656 ap->passphrase = passphrase;
3660 ap->ignore_broadcast_ssid =
3661 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3663 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3668 static void ap_start_callback(int result, GSupplicantInterface *interface,
3671 struct wifi_tethering_info *info = user_data;
3673 DBG("result %d index %d bridge %s",
3674 result, info->wifi->index, info->wifi->bridge);
3677 connman_inet_remove_from_bridge(info->wifi->index,
3678 info->wifi->bridge);
3679 connman_technology_tethering_notify(info->technology, false);
3682 g_free(info->ifname);
3686 static void ap_create_callback(int result,
3687 GSupplicantInterface *interface,
3690 struct wifi_tethering_info *info = user_data;
3692 DBG("result %d ifname %s", result,
3693 g_supplicant_interface_get_ifname(interface));
3696 connman_inet_remove_from_bridge(info->wifi->index,
3697 info->wifi->bridge);
3698 connman_technology_tethering_notify(info->technology, false);
3700 g_free(info->ifname);
3706 info->wifi->interface = interface;
3707 g_supplicant_interface_set_data(interface, info->wifi);
3709 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3710 connman_error("Failed to set interface ap_scan property");
3712 g_supplicant_interface_connect(interface, info->ssid,
3713 ap_start_callback, info);
3716 static void sta_remove_callback(int result,
3717 GSupplicantInterface *interface,
3720 struct wifi_tethering_info *info = user_data;
3721 const char *driver = connman_option_get_string("wifi");
3723 DBG("ifname %s result %d ", info->ifname, result);
3726 info->wifi->tethering = true;
3728 g_free(info->ifname);
3734 info->wifi->interface = NULL;
3736 connman_technology_tethering_notify(info->technology, true);
3738 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3743 static int tech_set_tethering(struct connman_technology *technology,
3744 const char *identifier, const char *passphrase,
3745 const char *bridge, bool enabled, bool hidden)
3748 GSupplicantInterface *interface;
3749 struct wifi_data *wifi;
3750 struct wifi_tethering_info *info;
3758 for (list = iface_list; list; list = list->next) {
3761 if (wifi->tethering) {
3762 wifi->tethering = false;
3764 connman_inet_remove_from_bridge(wifi->index,
3766 wifi->bridged = false;
3770 connman_technology_tethering_notify(technology, false);
3775 for (list = iface_list; list; list = list->next) {
3778 interface = wifi->interface;
3783 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3785 mode = g_supplicant_interface_get_mode(interface);
3786 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3787 DBG("%s does not support AP mode", ifname);
3791 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3796 info->technology = technology;
3797 info->wifi->bridge = bridge;
3798 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3803 info->ifname = g_strdup(ifname);
3804 if (!info->ifname) {
3810 info->wifi->tethering = true;
3812 err = g_supplicant_interface_remove(interface,
3813 sta_remove_callback,
3822 static void regdom_callback(int result, const char *alpha2, void *user_data)
3826 if (!wifi_technology)
3832 connman_technology_regdom_notify(wifi_technology, alpha2);
3835 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3837 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3840 static struct connman_technology_driver tech_driver = {
3842 .type = CONNMAN_SERVICE_TYPE_WIFI,
3843 .probe = tech_probe,
3844 .remove = tech_remove,
3845 .set_tethering = tech_set_tethering,
3846 .set_regdom = tech_set_regdom,
3849 static int wifi_init(void)
3853 err = connman_network_driver_register(&network_driver);
3857 err = g_supplicant_register(&callbacks);
3859 connman_network_driver_unregister(&network_driver);
3863 err = connman_technology_driver_register(&tech_driver);
3865 g_supplicant_unregister(&callbacks);
3866 connman_network_driver_unregister(&network_driver);
3873 static void wifi_exit(void)
3877 connman_technology_driver_unregister(&tech_driver);
3879 g_supplicant_unregister(&callbacks);
3881 connman_network_driver_unregister(&network_driver);
3884 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3885 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)