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;
140 #if defined TIZEN_EXT
143 #define TIZEN_ASSOC_RETRY_COUNT 4
145 static gboolean wifi_first_scan = false;
146 static gboolean found_with_first_scan = false;
147 static gboolean is_wifi_notifier_registered = false;
151 static GList *iface_list = NULL;
153 static GList *pending_wifi_device = NULL;
154 static GList *p2p_iface_list = NULL;
155 bool wfd_service_registered = false;
157 static void start_autoscan(struct connman_device *device);
159 static int p2p_tech_probe(struct connman_technology *technology)
161 p2p_technology = technology;
166 static void p2p_tech_remove(struct connman_technology *technology)
168 p2p_technology = NULL;
171 static struct connman_technology_driver p2p_tech_driver = {
173 .type = CONNMAN_SERVICE_TYPE_P2P,
174 .probe = p2p_tech_probe,
175 .remove = p2p_tech_remove,
178 static bool is_p2p_connecting(void)
182 for (list = iface_list; list; list = list->next) {
183 struct wifi_data *wifi = list->data;
185 if (wifi->p2p_connecting)
192 static void add_pending_wifi_device(struct wifi_data *wifi)
194 if (g_list_find(pending_wifi_device, wifi))
197 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
200 static struct wifi_data *get_pending_wifi_data(const char *ifname)
204 for (list = pending_wifi_device; list; list = list->next) {
205 struct wifi_data *wifi;
206 const char *dev_name;
209 if (!wifi || !wifi->device)
212 dev_name = connman_device_get_string(wifi->device, "Interface");
213 if (!g_strcmp0(ifname, dev_name)) {
214 pending_wifi_device = g_list_delete_link(
215 pending_wifi_device, list);
223 static void remove_pending_wifi_device(struct wifi_data *wifi)
227 link = g_list_find(pending_wifi_device, wifi);
232 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
235 static void peer_cancel_timeout(struct wifi_data *wifi)
237 if (wifi->p2p_connection_timeout > 0)
238 g_source_remove(wifi->p2p_connection_timeout);
240 wifi->p2p_connection_timeout = 0;
241 wifi->p2p_connecting = false;
243 if (wifi->pending_peer) {
244 connman_peer_unref(wifi->pending_peer);
245 wifi->pending_peer = NULL;
251 static gboolean peer_connect_timeout(gpointer data)
253 struct wifi_data *wifi = data;
257 if (wifi->p2p_connecting) {
258 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
260 if (g_supplicant_peer_has_requested_connection(wifi->peer))
261 state = CONNMAN_PEER_STATE_IDLE;
263 connman_peer_set_state(wifi->pending_peer, state);
266 peer_cancel_timeout(wifi);
271 static void peer_connect_callback(int result, GSupplicantInterface *interface,
274 struct wifi_data *wifi = user_data;
275 struct connman_peer *peer = wifi->pending_peer;
277 DBG("peer %p - %d", peer, result);
283 peer_connect_timeout(wifi);
287 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
289 wifi->p2p_connection_timeout = g_timeout_add_seconds(
290 P2P_CONNECTION_TIMEOUT,
291 peer_connect_timeout, wifi);
294 static int peer_connect(struct connman_peer *peer,
295 enum connman_peer_wps_method wps_method,
298 struct connman_device *device = connman_peer_get_device(peer);
299 GSupplicantPeerParams *peer_params;
300 GSupplicantPeer *gs_peer;
301 struct wifi_data *wifi;
305 DBG("peer %p", peer);
310 wifi = connman_device_get_data(device);
314 if (wifi->p2p_connecting)
319 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
320 connman_peer_get_identifier(peer));
324 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
325 pin = g_supplicant_peer_is_wps_pin(gs_peer);
327 switch (wps_method) {
328 case CONNMAN_PEER_WPS_UNKNOWN:
329 if ((pbc && pin) || pin)
332 case CONNMAN_PEER_WPS_PBC:
337 case CONNMAN_PEER_WPS_PIN:
338 if (!pin || !wps_pin)
343 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
347 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
349 peer_params->wps_pin = g_strdup(wps_pin);
351 peer_params->master = connman_peer_service_is_master();
353 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
354 peer_connect_callback, wifi);
355 if (ret == -EINPROGRESS) {
356 wifi->pending_peer = connman_peer_ref(peer);
357 wifi->peer = gs_peer;
358 wifi->p2p_connecting = true;
365 static int peer_disconnect(struct connman_peer *peer)
367 struct connman_device *device = connman_peer_get_device(peer);
368 GSupplicantPeerParams peer_params = {};
369 GSupplicantPeer *gs_peer;
370 struct wifi_data *wifi;
373 DBG("peer %p", peer);
378 wifi = connman_device_get_data(device);
382 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
383 connman_peer_get_identifier(peer));
387 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
389 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
391 g_free(peer_params.path);
393 if (ret == -EINPROGRESS)
394 peer_cancel_timeout(wifi);
399 struct peer_service_registration {
400 peer_service_registration_cb_t callback;
404 static bool is_service_wfd(const unsigned char *specs, int length)
406 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
412 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
414 struct wifi_data *wifi = data;
416 if (!wifi->interface ||
417 !g_supplicant_interface_has_p2p(wifi->interface))
420 if (!wifi->servicing) {
421 g_supplicant_interface_p2p_listen(wifi->interface,
422 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
428 static void register_wfd_service_cb(int result,
429 GSupplicantInterface *iface, void *user_data)
431 struct peer_service_registration *reg_data = user_data;
436 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
438 if (reg_data && reg_data->callback) {
439 reg_data->callback(result, reg_data->user_data);
444 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
445 const unsigned char *spec,
446 int spec_length, const unsigned char *query,
447 int query_length, int version)
449 GSupplicantP2PServiceParams *params;
451 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
456 params->version = version;
457 params->service = g_memdup(spec, spec_length);
458 } else if (query_length > 0 && spec_length > 0) {
459 params->query = g_memdup(query, query_length);
460 params->query_length = query_length;
462 params->response = g_memdup(spec, spec_length);
463 params->response_length = spec_length;
465 params->wfd_ies = g_memdup(spec, spec_length);
466 params->wfd_ies_length = spec_length;
472 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
477 g_free(params->service);
478 g_free(params->query);
479 g_free(params->response);
480 g_free(params->wfd_ies);
485 static int peer_register_wfd_service(const unsigned char *specification,
486 int specification_length,
487 peer_service_registration_cb_t callback,
490 struct peer_service_registration *reg_data = NULL;
491 static GSupplicantP2PServiceParams *params;
496 if (wfd_service_registered)
499 params = fill_in_peer_service_params(specification,
500 specification_length, NULL, 0, 0);
504 reg_data = g_try_malloc0(sizeof(*reg_data));
510 reg_data->callback = callback;
511 reg_data->user_data = user_data;
513 ret = g_supplicant_set_widi_ies(params,
514 register_wfd_service_cb, reg_data);
515 if (ret < 0 && ret != -EINPROGRESS)
518 wfd_service_registered = true;
522 free_peer_service_params(params);
528 static void register_peer_service_cb(int result,
529 GSupplicantInterface *iface, void *user_data)
531 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
532 struct peer_service_registration *reg_data = user_data;
537 apply_p2p_listen_on_iface(wifi, NULL);
539 if (reg_data->callback)
540 reg_data->callback(result, reg_data->user_data);
545 static int peer_register_service(const unsigned char *specification,
546 int specification_length,
547 const unsigned char *query,
548 int query_length, int version,
549 peer_service_registration_cb_t callback,
552 struct peer_service_registration *reg_data;
553 GSupplicantP2PServiceParams *params;
560 if (specification && !version && !query &&
561 is_service_wfd(specification, specification_length)) {
562 return peer_register_wfd_service(specification,
563 specification_length, callback, user_data);
566 reg_data = g_try_malloc0(sizeof(*reg_data));
570 reg_data->callback = callback;
571 reg_data->user_data = user_data;
575 for (list = iface_list; list; list = list->next) {
576 struct wifi_data *wifi = list->data;
577 GSupplicantInterface *iface = wifi->interface;
579 if (!g_supplicant_interface_has_p2p(iface))
582 params = fill_in_peer_service_params(specification,
583 specification_length, query,
584 query_length, version);
591 ret_f = g_supplicant_interface_p2p_add_service(iface,
592 register_peer_service_cb, params, reg_data);
593 if (ret_f == 0 || ret_f == -EINPROGRESS)
597 ret = g_supplicant_interface_p2p_add_service(iface,
598 register_peer_service_cb, params, NULL);
599 if (ret != 0 && ret != -EINPROGRESS)
600 free_peer_service_params(params);
603 if (ret_f != 0 && ret_f != -EINPROGRESS)
609 static int peer_unregister_wfd_service(void)
611 GSupplicantP2PServiceParams *params;
614 if (!wfd_service_registered)
617 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
621 wfd_service_registered = false;
623 g_supplicant_set_widi_ies(params, NULL, NULL);
625 for (list = iface_list; list; list = list->next) {
626 struct wifi_data *wifi = list->data;
628 if (!g_supplicant_interface_has_p2p(wifi->interface))
632 if (!wifi->servicing || wifi->servicing < 0) {
633 g_supplicant_interface_p2p_listen(wifi->interface,
642 static int peer_unregister_service(const unsigned char *specification,
643 int specification_length,
644 const unsigned char *query,
645 int query_length, int version)
647 GSupplicantP2PServiceParams *params;
652 if (specification && !version && !query &&
653 is_service_wfd(specification, specification_length)) {
654 ret = peer_unregister_wfd_service();
655 if (ret != 0 && ret != -EINPROGRESS)
660 for (list = iface_list; list; list = list->next) {
661 struct wifi_data *wifi = list->data;
662 GSupplicantInterface *iface = wifi->interface;
667 if (!g_supplicant_interface_has_p2p(iface))
670 params = fill_in_peer_service_params(specification,
671 specification_length, query,
672 query_length, version);
678 ret = g_supplicant_interface_p2p_del_service(iface, params);
679 if (ret != 0 && ret != -EINPROGRESS)
680 free_peer_service_params(params);
683 if (!wifi->servicing || wifi->servicing < 0) {
684 g_supplicant_interface_p2p_listen(iface, 0, 0);
692 static struct connman_peer_driver peer_driver = {
693 .connect = peer_connect,
694 .disconnect = peer_disconnect,
695 .register_service = peer_register_service,
696 .unregister_service = peer_unregister_service,
699 static void handle_tethering(struct wifi_data *wifi)
701 if (!wifi->tethering)
710 DBG("index %d bridge %s", wifi->index, wifi->bridge);
712 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
715 wifi->bridged = true;
718 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
720 struct connman_device *device = user_data;
721 struct wifi_data *wifi = connman_device_get_data(device);
726 DBG("index %d flags %d change %d", wifi->index, flags, change);
728 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
732 DBG("interface down");
735 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
736 if (flags & IFF_LOWER_UP) {
739 handle_tethering(wifi);
747 static int wifi_probe(struct connman_device *device)
749 struct wifi_data *wifi;
751 DBG("device %p", device);
753 wifi = g_try_new0(struct wifi_data, 1);
757 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
759 connman_device_set_data(device, wifi);
760 wifi->device = connman_device_ref(device);
762 wifi->index = connman_device_get_index(device);
765 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
766 wifi_newlink, device);
767 if (is_p2p_connecting())
768 add_pending_wifi_device(wifi);
770 iface_list = g_list_append(iface_list, wifi);
775 static void remove_networks(struct connman_device *device,
776 struct wifi_data *wifi)
780 for (list = wifi->networks; list; list = list->next) {
781 struct connman_network *network = list->data;
783 connman_device_remove_network(device, network);
784 connman_network_unref(network);
787 g_slist_free(wifi->networks);
788 wifi->networks = NULL;
791 static void reset_autoscan(struct connman_device *device)
793 struct wifi_data *wifi = connman_device_get_data(device);
794 struct autoscan_params *autoscan;
798 if (!wifi || !wifi->autoscan)
801 autoscan = wifi->autoscan;
803 if (autoscan->timeout == 0 && autoscan->interval == 0)
806 g_source_remove(autoscan->timeout);
808 autoscan->timeout = 0;
809 autoscan->interval = 0;
811 connman_device_unref(device);
814 static void stop_autoscan(struct connman_device *device)
816 const struct wifi_data *wifi = connman_device_get_data(device);
818 if (!wifi || !wifi->autoscan)
821 reset_autoscan(device);
823 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
826 static void check_p2p_technology(void)
828 bool p2p_exists = false;
831 for (list = iface_list; list; list = list->next) {
832 struct wifi_data *w = list->data;
835 g_supplicant_interface_has_p2p(w->interface))
840 connman_technology_driver_unregister(&p2p_tech_driver);
841 connman_peer_driver_unregister(&peer_driver);
845 static void wifi_remove(struct connman_device *device)
847 struct wifi_data *wifi = connman_device_get_data(device);
849 DBG("device %p wifi %p", device, wifi);
854 stop_autoscan(device);
856 if (wifi->p2p_device)
857 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
859 iface_list = g_list_remove(iface_list, wifi);
861 check_p2p_technology();
863 remove_pending_wifi_device(wifi);
865 if (wifi->p2p_find_timeout) {
866 g_source_remove(wifi->p2p_find_timeout);
867 connman_device_unref(wifi->device);
870 if (wifi->p2p_connection_timeout)
871 g_source_remove(wifi->p2p_connection_timeout);
873 remove_networks(device, wifi);
875 connman_device_set_powered(device, false);
876 connman_device_set_data(device, NULL);
877 connman_device_unref(wifi->device);
878 connman_rtnl_remove_watch(wifi->watch);
880 g_supplicant_interface_set_data(wifi->interface, NULL);
882 g_supplicant_interface_cancel(wifi->interface);
884 if (wifi->scan_params)
885 g_supplicant_free_scan_params(wifi->scan_params);
887 g_free(wifi->autoscan);
888 g_free(wifi->identifier);
892 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
896 for (iter = list; iter; iter = g_slist_next(iter)) {
897 struct scan_ssid *scan_ssid = iter->data;
899 if (ssid_len == scan_ssid->ssid_len &&
900 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
907 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
908 int freq, GSupplicantScanParams *scan_data,
909 int driver_max_scan_ssids, char *ssid_name)
912 struct scan_ssid *scan_ssid;
914 if ((driver_max_scan_ssids == 0 ||
915 driver_max_scan_ssids > scan_data->num_ssids) &&
916 (hex_ssid || raw_ssid)) {
918 unsigned int j = 0, hex;
921 size_t hex_ssid_len = strlen(hex_ssid);
923 ssid = g_try_malloc0(hex_ssid_len / 2);
927 for (i = 0; i < hex_ssid_len; i += 2) {
928 sscanf(hex_ssid + i, "%02x", &hex);
937 * If we have already added hidden AP to the list,
938 * then do not do it again. This might happen if you have
939 * used or are using multiple wifi cards, so in that case
940 * you might have multiple service files for same AP.
942 if (is_duplicate(scan_data->ssids, ssid, j)) {
948 scan_ssid = g_try_new(struct scan_ssid, 1);
955 memcpy(scan_ssid->ssid, ssid, j);
956 scan_ssid->ssid_len = j;
957 scan_data->ssids = g_slist_prepend(scan_data->ssids,
960 scan_data->num_ssids++;
962 DBG("SSID %s added to scanned list of %d entries", ssid_name,
963 scan_data->num_ssids);
970 scan_data->ssids = g_slist_reverse(scan_data->ssids);
972 if (!scan_data->freqs) {
973 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
974 if (!scan_data->freqs) {
975 g_slist_free_full(scan_data->ssids, g_free);
979 scan_data->num_freqs = 1;
980 scan_data->freqs[0] = freq;
982 bool duplicate = false;
984 /* Don't add duplicate entries */
985 for (i = 0; i < scan_data->num_freqs; i++) {
986 if (scan_data->freqs[i] == freq) {
993 scan_data->num_freqs++;
994 scan_data->freqs = g_try_realloc(scan_data->freqs,
995 sizeof(uint16_t) * scan_data->num_freqs);
996 if (!scan_data->freqs) {
997 g_slist_free_full(scan_data->ssids, g_free);
1000 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1007 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1009 struct connman_config_entry **entries;
1015 int num_ssids = 0, add_param_failed = 0;
1017 services = connman_storage_get_services();
1018 for (i = 0; services && services[i]; i++) {
1019 if (strncmp(services[i], "wifi_", 5) != 0)
1022 keyfile = connman_storage_load_service(services[i]);
1026 value = g_key_file_get_boolean(keyfile,
1027 services[i], "Hidden", NULL);
1029 g_key_file_free(keyfile);
1033 value = g_key_file_get_boolean(keyfile,
1034 services[i], "Favorite", NULL);
1036 g_key_file_free(keyfile);
1040 #if defined TIZEN_EXT
1041 value = g_key_file_get_boolean(keyfile,
1042 services[i], "AutoConnect", NULL);
1044 g_key_file_free(keyfile);
1049 ssid = g_key_file_get_string(keyfile,
1050 services[i], "SSID", NULL);
1052 name = g_key_file_get_string(keyfile, services[i], "Name",
1055 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1063 g_key_file_free(keyfile);
1067 * Check if there are any hidden AP that needs to be provisioned.
1069 entries = connman_config_get_entries("wifi");
1070 for (i = 0; entries && entries[i]; i++) {
1073 if (!entries[i]->hidden)
1076 if (!entries[i]->ssid) {
1077 ssid = entries[i]->name;
1080 ssid = entries[i]->ssid;
1081 len = entries[i]->ssid_len;
1087 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1094 connman_config_free_entries(entries);
1096 if (add_param_failed > 0)
1097 DBG("Unable to scan %d out of %d SSIDs",
1098 add_param_failed, num_ssids);
1100 g_strfreev(services);
1105 static int get_hidden_connections_params(struct wifi_data *wifi,
1106 GSupplicantScanParams *scan_params)
1108 int driver_max_ssids, i;
1109 GSupplicantScanParams *orig_params;
1112 * Scan hidden networks so that we can autoconnect to them.
1113 * We will assume 1 as a default number of ssid to scan.
1115 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1117 if (driver_max_ssids == 0)
1118 driver_max_ssids = 1;
1120 DBG("max ssids %d", driver_max_ssids);
1122 if (!wifi->scan_params) {
1123 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1124 if (!wifi->scan_params)
1127 if (get_hidden_connections(wifi->scan_params) == 0) {
1128 g_supplicant_free_scan_params(wifi->scan_params);
1129 wifi->scan_params = NULL;
1135 orig_params = wifi->scan_params;
1137 /* Let's transfer driver_max_ssids params */
1138 for (i = 0; i < driver_max_ssids; i++) {
1139 struct scan_ssid *ssid;
1141 if (!wifi->scan_params->ssids)
1144 ssid = orig_params->ssids->data;
1145 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1146 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1150 scan_params->num_ssids = i;
1151 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1153 scan_params->freqs = g_memdup(orig_params->freqs,
1154 sizeof(uint16_t) * orig_params->num_freqs);
1155 if (!scan_params->freqs)
1158 scan_params->num_freqs = orig_params->num_freqs;
1163 orig_params->num_ssids -= scan_params->num_ssids;
1165 return scan_params->num_ssids;
1168 g_slist_free_full(scan_params->ssids, g_free);
1169 g_supplicant_free_scan_params(wifi->scan_params);
1170 wifi->scan_params = NULL;
1175 static int throw_wifi_scan(struct connman_device *device,
1176 GSupplicantInterfaceCallback callback)
1178 struct wifi_data *wifi = connman_device_get_data(device);
1184 DBG("device %p %p", device, wifi->interface);
1186 if (wifi->tethering)
1188 #if defined TIZEN_EXT
1189 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1191 if (connman_device_get_scanning(device))
1195 connman_device_ref(device);
1197 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1200 connman_device_set_scanning(device,
1201 CONNMAN_SERVICE_TYPE_WIFI, true);
1203 connman_device_unref(device);
1208 static void hidden_free(struct hidden_params *hidden)
1213 if (hidden->scan_params)
1214 g_supplicant_free_scan_params(hidden->scan_params);
1215 g_free(hidden->identity);
1216 g_free(hidden->passphrase);
1217 g_free(hidden->security);
1221 #if defined TIZEN_EXT
1222 static void service_state_changed(struct connman_service *service,
1223 enum connman_service_state state);
1225 static int network_connect(struct connman_network *network);
1227 static struct connman_notifier notifier = {
1229 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1230 .service_state_changed = service_state_changed,
1233 static void service_state_changed(struct connman_service *service,
1234 enum connman_service_state state)
1236 enum connman_service_type type;
1238 type = connman_service_get_type(service);
1239 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1242 DBG("service %p state %d", service, state);
1245 case CONNMAN_SERVICE_STATE_READY:
1246 case CONNMAN_SERVICE_STATE_ONLINE:
1247 case CONNMAN_SERVICE_STATE_FAILURE:
1248 connman_notifier_unregister(¬ifier);
1249 is_wifi_notifier_registered = FALSE;
1251 __connman_device_request_scan(type);
1260 static void scan_callback(int result, GSupplicantInterface *interface,
1263 struct connman_device *device = user_data;
1264 struct wifi_data *wifi = connman_device_get_data(device);
1267 DBG("result %d wifi %p", result, wifi);
1270 if (wifi->hidden && !wifi->postpone_hidden) {
1271 connman_network_clear_hidden(wifi->hidden->user_data);
1272 hidden_free(wifi->hidden);
1273 wifi->hidden = NULL;
1276 if (wifi->scan_params) {
1277 g_supplicant_free_scan_params(wifi->scan_params);
1278 wifi->scan_params = NULL;
1283 connman_device_reset_scanning(device);
1285 /* User is connecting to a hidden AP, let's wait for finished event */
1286 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1287 GSupplicantScanParams *scan_params;
1290 wifi->postpone_hidden = false;
1291 scan_params = wifi->hidden->scan_params;
1292 wifi->hidden->scan_params = NULL;
1294 reset_autoscan(device);
1296 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1297 scan_callback, device);
1301 /* On error, let's recall scan_callback, which will cleanup */
1302 return scan_callback(ret, interface, user_data);
1305 scanning = connman_device_get_scanning(device);
1306 #if defined TIZEN_EXT
1307 if (scanning && wifi && !wifi->allow_full_scan)
1311 connman_device_set_scanning(device,
1312 CONNMAN_SERVICE_TYPE_WIFI, false);
1314 if (result != -ENOLINK)
1315 #if defined TIZEN_EXT
1318 start_autoscan(device);
1321 * If we are here then we were scanning; however, if we are
1322 * also mid-flight disabling the interface, then wifi_disable
1323 * has already cleared the device scanning state and
1324 * unreferenced the device, obviating the need to do it here.
1328 connman_device_unref(device);
1330 #if defined TIZEN_EXT
1331 if (wifi && wifi->allow_full_scan) {
1332 DBG("Trigger Full Channel Scan");
1333 throw_wifi_scan(device, scan_callback);
1334 wifi->allow_full_scan = FALSE;
1336 if (wifi && wifi->scan_pending_network && result != -EIO) {
1337 network_connect(wifi->scan_pending_network);
1338 wifi->scan_pending_network = NULL;
1339 connman_network_set_connecting(wifi->network);
1342 if (is_wifi_notifier_registered != true &&
1343 wifi_first_scan == true && found_with_first_scan == true) {
1344 wifi_first_scan = false;
1345 found_with_first_scan = false;
1347 connman_notifier_register(¬ifier);
1348 is_wifi_notifier_registered = true;
1353 static void scan_callback_hidden(int result,
1354 GSupplicantInterface *interface, void *user_data)
1356 struct connman_device *device = user_data;
1357 struct wifi_data *wifi = connman_device_get_data(device);
1358 GSupplicantScanParams *scan_params;
1361 DBG("result %d wifi %p", result, wifi);
1366 /* User is trying to connect to a hidden AP */
1367 if (wifi->hidden && wifi->postpone_hidden)
1370 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1374 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1375 ret = g_supplicant_interface_scan(wifi->interface,
1377 scan_callback_hidden,
1383 g_supplicant_free_scan_params(scan_params);
1386 scan_callback(result, interface, user_data);
1389 static gboolean autoscan_timeout(gpointer data)
1391 struct connman_device *device = data;
1392 struct wifi_data *wifi = connman_device_get_data(device);
1393 struct autoscan_params *autoscan;
1399 autoscan = wifi->autoscan;
1401 if (autoscan->interval <= 0) {
1402 interval = autoscan->base;
1405 interval = autoscan->interval * autoscan->base;
1407 #if defined TIZEN_EXT
1408 if (autoscan->interval >= autoscan->limit)
1410 if (interval > autoscan->limit)
1412 interval = autoscan->limit;
1414 throw_wifi_scan(wifi->device, scan_callback_hidden);
1417 DBG("interval %d", interval);
1419 autoscan->interval = interval;
1421 autoscan->timeout = g_timeout_add_seconds(interval,
1422 autoscan_timeout, device);
1427 static void start_autoscan(struct connman_device *device)
1429 struct wifi_data *wifi = connman_device_get_data(device);
1430 struct autoscan_params *autoscan;
1437 if (wifi->p2p_device)
1440 if (wifi->connected)
1443 autoscan = wifi->autoscan;
1447 if (autoscan->timeout > 0 || autoscan->interval > 0)
1450 connman_device_ref(device);
1452 autoscan_timeout(device);
1455 static struct autoscan_params *parse_autoscan_params(const char *params)
1457 struct autoscan_params *autoscan;
1462 DBG("Emulating autoscan");
1464 list_params = g_strsplit(params, ":", 0);
1465 if (list_params == 0)
1468 if (g_strv_length(list_params) < 3) {
1469 g_strfreev(list_params);
1473 base = atoi(list_params[1]);
1474 limit = atoi(list_params[2]);
1476 g_strfreev(list_params);
1478 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1480 DBG("Could not allocate memory for autoscan");
1484 DBG("base %d - limit %d", base, limit);
1485 autoscan->base = base;
1486 autoscan->limit = limit;
1491 static void setup_autoscan(struct wifi_data *wifi)
1493 if (!wifi->autoscan)
1494 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1496 start_autoscan(wifi->device);
1499 static void finalize_interface_creation(struct wifi_data *wifi)
1501 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1503 if (!wifi->device) {
1504 connman_error("WiFi device not set");
1508 connman_device_set_powered(wifi->device, true);
1510 if (!connman_setting_get_bool("BackgroundScanning"))
1513 if (wifi->p2p_device)
1516 setup_autoscan(wifi);
1519 static void interface_create_callback(int result,
1520 GSupplicantInterface *interface,
1523 struct wifi_data *wifi = user_data;
1525 DBG("result %d ifname %s, wifi %p", result,
1526 g_supplicant_interface_get_ifname(interface),
1529 if (result < 0 || !wifi)
1532 wifi->interface = interface;
1533 g_supplicant_interface_set_data(interface, wifi);
1535 if (g_supplicant_interface_get_ready(interface)) {
1536 wifi->interface_ready = true;
1537 finalize_interface_creation(wifi);
1541 static int wifi_enable(struct connman_device *device)
1543 struct wifi_data *wifi = connman_device_get_data(device);
1546 const char *driver = connman_option_get_string("wifi");
1549 DBG("device %p %p", device, wifi);
1551 index = connman_device_get_index(device);
1552 if (!wifi || index < 0)
1555 if (is_p2p_connecting())
1556 return -EINPROGRESS;
1558 interface = connman_inet_ifname(index);
1559 ret = g_supplicant_interface_create(interface, driver, NULL,
1560 interface_create_callback,
1567 return -EINPROGRESS;
1570 static int wifi_disable(struct connman_device *device)
1572 struct wifi_data *wifi = connman_device_get_data(device);
1575 DBG("device %p wifi %p", device, wifi);
1580 wifi->connected = false;
1581 wifi->disconnecting = false;
1583 if (wifi->pending_network)
1584 wifi->pending_network = NULL;
1586 stop_autoscan(device);
1588 if (wifi->p2p_find_timeout) {
1589 g_source_remove(wifi->p2p_find_timeout);
1590 wifi->p2p_find_timeout = 0;
1591 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1592 connman_device_unref(wifi->device);
1595 /* In case of a user scan, device is still referenced */
1596 if (connman_device_get_scanning(device)) {
1597 connman_device_set_scanning(device,
1598 CONNMAN_SERVICE_TYPE_WIFI, false);
1599 connman_device_unref(wifi->device);
1602 remove_networks(device, wifi);
1604 #if defined TIZEN_EXT
1605 wifi->scan_pending_network = NULL;
1607 if (is_wifi_notifier_registered == true) {
1608 connman_notifier_unregister(¬ifier);
1609 is_wifi_notifier_registered = false;
1613 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1617 return -EINPROGRESS;
1620 struct last_connected {
1626 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1628 GTimeVal *aval = (GTimeVal *)a;
1629 GTimeVal *bval = (GTimeVal *)b;
1631 /* Note that the sort order is descending */
1632 if (aval->tv_sec < bval->tv_sec)
1635 if (aval->tv_sec > bval->tv_sec)
1641 static void free_entry(gpointer data)
1643 struct last_connected *entry = data;
1645 g_free(entry->ssid);
1649 static int get_latest_connections(int max_ssids,
1650 GSupplicantScanParams *scan_data)
1652 GSequenceIter *iter;
1653 GSequence *latest_list;
1654 struct last_connected *entry;
1663 latest_list = g_sequence_new(free_entry);
1667 services = connman_storage_get_services();
1668 for (i = 0; services && services[i]; i++) {
1669 if (strncmp(services[i], "wifi_", 5) != 0)
1672 keyfile = connman_storage_load_service(services[i]);
1676 str = g_key_file_get_string(keyfile,
1677 services[i], "Favorite", NULL);
1678 if (!str || g_strcmp0(str, "true")) {
1680 g_key_file_free(keyfile);
1685 str = g_key_file_get_string(keyfile,
1686 services[i], "AutoConnect", NULL);
1687 if (!str || g_strcmp0(str, "true")) {
1689 g_key_file_free(keyfile);
1694 str = g_key_file_get_string(keyfile,
1695 services[i], "Modified", NULL);
1697 g_key_file_free(keyfile);
1700 g_time_val_from_iso8601(str, &modified);
1703 ssid = g_key_file_get_string(keyfile,
1704 services[i], "SSID", NULL);
1706 freq = g_key_file_get_integer(keyfile, services[i],
1709 entry = g_try_new(struct last_connected, 1);
1711 g_sequence_free(latest_list);
1712 g_key_file_free(keyfile);
1718 entry->modified = modified;
1721 g_sequence_insert_sorted(latest_list, entry,
1727 g_key_file_free(keyfile);
1730 g_strfreev(services);
1732 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1734 iter = g_sequence_get_begin_iter(latest_list);
1736 for (i = 0; i < num_ssids; i++) {
1737 entry = g_sequence_get(iter);
1739 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1740 entry->modified.tv_sec);
1742 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1743 max_ssids, entry->ssid);
1745 iter = g_sequence_iter_next(iter);
1748 g_sequence_free(latest_list);
1752 static int wifi_scan_simple(struct connman_device *device)
1754 reset_autoscan(device);
1756 return throw_wifi_scan(device, scan_callback_hidden);
1759 static gboolean p2p_find_stop(gpointer data)
1761 struct connman_device *device = data;
1762 struct wifi_data *wifi = connman_device_get_data(device);
1766 wifi->p2p_find_timeout = 0;
1768 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1770 g_supplicant_interface_p2p_stop_find(wifi->interface);
1772 connman_device_unref(device);
1773 reset_autoscan(device);
1778 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1781 struct connman_device *device = user_data;
1782 struct wifi_data *wifi = connman_device_get_data(device);
1784 DBG("result %d wifi %p", result, wifi);
1786 if (wifi->p2p_find_timeout) {
1787 g_source_remove(wifi->p2p_find_timeout);
1788 wifi->p2p_find_timeout = 0;
1794 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1795 p2p_find_stop, device);
1796 if (!wifi->p2p_find_timeout)
1801 p2p_find_stop(device);
1804 static int p2p_find(struct connman_device *device)
1806 struct wifi_data *wifi;
1811 if (!p2p_technology)
1814 wifi = connman_device_get_data(device);
1816 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1819 reset_autoscan(device);
1820 connman_device_ref(device);
1822 ret = g_supplicant_interface_p2p_find(wifi->interface,
1823 p2p_find_callback, device);
1825 connman_device_unref(device);
1826 start_autoscan(device);
1828 connman_device_set_scanning(device,
1829 CONNMAN_SERVICE_TYPE_P2P, true);
1836 * Note that the hidden scan is only used when connecting to this specific
1837 * hidden AP first time. It is not used when system autoconnects to hidden AP.
1839 static int wifi_scan(enum connman_service_type type,
1840 struct connman_device *device,
1841 const char *ssid, unsigned int ssid_len,
1842 const char *identity, const char* passphrase,
1843 const char *security, void *user_data)
1845 struct wifi_data *wifi = connman_device_get_data(device);
1846 GSupplicantScanParams *scan_params = NULL;
1847 struct scan_ssid *scan_ssid;
1848 struct hidden_params *hidden;
1850 int driver_max_ssids = 0;
1857 if (wifi->p2p_device)
1860 if (type == CONNMAN_SERVICE_TYPE_P2P)
1861 return p2p_find(device);
1863 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
1865 if (wifi->tethering)
1868 scanning = connman_device_get_scanning(device);
1870 if (!ssid || ssid_len == 0 || ssid_len > 32) {
1874 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1876 DBG("max ssids %d", driver_max_ssids);
1877 if (driver_max_ssids == 0)
1878 return wifi_scan_simple(device);
1882 if (scanning && wifi->hidden && wifi->postpone_hidden)
1888 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1893 scan_ssid = g_try_new(struct scan_ssid, 1);
1895 g_free(scan_params);
1899 memcpy(scan_ssid->ssid, ssid, ssid_len);
1900 scan_ssid->ssid_len = ssid_len;
1901 scan_params->ssids = g_slist_prepend(scan_params->ssids,
1903 scan_params->num_ssids = 1;
1905 hidden = g_try_new0(struct hidden_params, 1);
1907 g_supplicant_free_scan_params(scan_params);
1912 hidden_free(wifi->hidden);
1913 wifi->hidden = NULL;
1916 memcpy(hidden->ssid, ssid, ssid_len);
1917 hidden->ssid_len = ssid_len;
1918 hidden->identity = g_strdup(identity);
1919 hidden->passphrase = g_strdup(passphrase);
1920 hidden->security = g_strdup(security);
1921 hidden->user_data = user_data;
1922 wifi->hidden = hidden;
1925 /* Let's keep this active scan for later,
1926 * when current scan will be over. */
1927 wifi->postpone_hidden = TRUE;
1928 hidden->scan_params = scan_params;
1932 } else if (wifi->connected) {
1933 g_supplicant_free_scan_params(scan_params);
1934 return wifi_scan_simple(device);
1936 ret = get_latest_connections(driver_max_ssids, scan_params);
1938 g_supplicant_free_scan_params(scan_params);
1939 return wifi_scan_simple(device);
1943 connman_device_ref(device);
1945 #if defined TIZEN_EXT
1946 /*To allow the Full Scan after ssid based scan, set the flag here
1947 It is required because Tizen does not use the ConnMan specific
1948 backgroung Scan feature.Tizen has added the BG Scan feature in net-config
1949 To sync with up ConnMan, we need to issue the Full Scan after SSID specific scan.*/
1950 wifi->allow_full_scan = TRUE;
1952 reset_autoscan(device);
1954 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1955 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);
1965 hidden_free(wifi->hidden);
1966 wifi->hidden = NULL;
1973 static void wifi_regdom_callback(int result,
1977 struct connman_device *device = user_data;
1979 connman_device_regdom_notify(device, result, alpha2);
1981 connman_device_unref(device);
1984 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
1986 struct wifi_data *wifi = connman_device_get_data(device);
1992 connman_device_ref(device);
1994 ret = g_supplicant_interface_set_country(wifi->interface,
1995 wifi_regdom_callback,
1998 connman_device_unref(device);
2003 static struct connman_device_driver wifi_ng_driver = {
2005 .type = CONNMAN_DEVICE_TYPE_WIFI,
2006 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2007 .probe = wifi_probe,
2008 .remove = wifi_remove,
2009 .enable = wifi_enable,
2010 .disable = wifi_disable,
2012 .set_regdom = wifi_set_regdom,
2015 static void system_ready(void)
2019 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2020 connman_error("Failed to register WiFi driver");
2023 static void system_killed(void)
2027 connman_device_driver_unregister(&wifi_ng_driver);
2030 static int network_probe(struct connman_network *network)
2032 DBG("network %p", network);
2037 static void network_remove(struct connman_network *network)
2039 struct connman_device *device = connman_network_get_device(network);
2040 struct wifi_data *wifi;
2042 DBG("network %p", network);
2044 wifi = connman_device_get_data(device);
2048 if (wifi->network != network)
2051 wifi->network = NULL;
2053 #if defined TIZEN_EXT
2054 wifi->disconnecting = false;
2056 if (wifi->pending_network == network)
2057 wifi->pending_network = NULL;
2059 if (wifi->scan_pending_network == network)
2060 wifi->scan_pending_network = NULL;
2064 static void connect_callback(int result, GSupplicantInterface *interface,
2067 #if defined TIZEN_EXT
2069 struct wifi_data *wifi;
2071 struct connman_network *network = user_data;
2073 DBG("network %p result %d", network, result);
2075 #if defined TIZEN_EXT
2076 for (list = iface_list; list; list = list->next) {
2079 if (wifi && wifi->network == network)
2083 /* wifi_data may be invalid because wifi is already disabled */
2088 if (result == -ENOKEY) {
2089 connman_network_set_error(network,
2090 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2091 } else if (result < 0) {
2092 connman_network_set_error(network,
2093 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2096 connman_network_unref(network);
2099 static GSupplicantSecurity network_security(const char *security)
2101 if (g_str_equal(security, "none"))
2102 return G_SUPPLICANT_SECURITY_NONE;
2103 else if (g_str_equal(security, "wep"))
2104 return G_SUPPLICANT_SECURITY_WEP;
2105 else if (g_str_equal(security, "psk"))
2106 return G_SUPPLICANT_SECURITY_PSK;
2107 else if (g_str_equal(security, "wpa"))
2108 return G_SUPPLICANT_SECURITY_PSK;
2109 else if (g_str_equal(security, "rsn"))
2110 return G_SUPPLICANT_SECURITY_PSK;
2111 else if (g_str_equal(security, "ieee8021x"))
2112 return G_SUPPLICANT_SECURITY_IEEE8021X;
2113 #if defined TIZEN_EXT
2114 else if (g_str_equal(security, "ft_psk") == TRUE)
2115 return G_SUPPLICANT_SECURITY_FT_PSK;
2116 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2117 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2120 return G_SUPPLICANT_SECURITY_UNKNOWN;
2123 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2125 const char *security;
2127 memset(ssid, 0, sizeof(*ssid));
2128 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2129 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2131 ssid->scan_ssid = 1;
2132 security = connman_network_get_string(network, "WiFi.Security");
2133 ssid->security = network_security(security);
2134 ssid->passphrase = connman_network_get_string(network,
2137 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2140 * If our private key password is unset,
2141 * we use the supplied passphrase. That is needed
2142 * for PEAP where 2 passphrases (identity and client
2143 * cert may have to be provided.
2145 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2146 connman_network_set_string(network,
2147 "WiFi.PrivateKeyPassphrase",
2149 /* We must have an identity for both PEAP and TLS */
2150 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2152 /* Use agent provided identity as a fallback */
2153 if (!ssid->identity || strlen(ssid->identity) == 0)
2154 ssid->identity = connman_network_get_string(network,
2155 "WiFi.AgentIdentity");
2157 ssid->ca_cert_path = connman_network_get_string(network,
2159 ssid->client_cert_path = connman_network_get_string(network,
2160 "WiFi.ClientCertFile");
2161 ssid->private_key_path = connman_network_get_string(network,
2162 "WiFi.PrivateKeyFile");
2163 ssid->private_key_passphrase = connman_network_get_string(network,
2164 "WiFi.PrivateKeyPassphrase");
2165 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2167 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2168 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2170 #if defined TIZEN_EXT
2171 ssid->bssid = connman_network_get_bssid(network);
2174 if (connman_setting_get_bool("BackgroundScanning"))
2175 ssid->bgscan = BGSCAN_DEFAULT;
2178 static int network_connect(struct connman_network *network)
2180 struct connman_device *device = connman_network_get_device(network);
2181 struct wifi_data *wifi;
2182 GSupplicantInterface *interface;
2183 GSupplicantSSID *ssid;
2185 DBG("network %p", network);
2190 wifi = connman_device_get_data(device);
2194 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2198 interface = wifi->interface;
2200 ssid_init(ssid, network);
2202 if (wifi->disconnecting) {
2203 wifi->pending_network = network;
2206 wifi->network = connman_network_ref(network);
2208 #if defined TIZEN_EXT
2209 wifi->scan_pending_network = NULL;
2212 return g_supplicant_interface_connect(interface, ssid,
2213 connect_callback, network);
2216 return -EINPROGRESS;
2219 static void disconnect_callback(int result, GSupplicantInterface *interface,
2222 #if defined TIZEN_EXT
2224 struct wifi_data *wifi;
2225 struct connman_network *network = user_data;
2227 DBG("network %p result %d", network, result);
2229 for (list = iface_list; list; list = list->next) {
2232 if (wifi->network == NULL && wifi->disconnecting == true)
2233 wifi->disconnecting = false;
2235 if (wifi->network == network)
2239 /* wifi_data may be invalid because wifi is already disabled */
2244 struct wifi_data *wifi = user_data;
2247 DBG("result %d supplicant interface %p wifi %p",
2248 result, interface, wifi);
2250 if (result == -ECONNABORTED) {
2251 DBG("wifi interface no longer available");
2255 if (wifi->network) {
2257 * if result < 0 supplican return an error because
2258 * the network is not current.
2259 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2260 * failed, call connman_network_set_connected to report
2261 * disconnect is completed.
2264 connman_network_set_connected(wifi->network, false);
2267 wifi->network = NULL;
2269 wifi->disconnecting = false;
2271 if (wifi->pending_network) {
2272 network_connect(wifi->pending_network);
2273 wifi->pending_network = NULL;
2276 start_autoscan(wifi->device);
2279 static int network_disconnect(struct connman_network *network)
2281 struct connman_device *device = connman_network_get_device(network);
2282 struct wifi_data *wifi;
2284 #if defined TIZEN_EXT
2285 struct connman_service *service;
2288 DBG("network %p", network);
2290 wifi = connman_device_get_data(device);
2291 if (!wifi || !wifi->interface)
2294 #if defined TIZEN_EXT
2295 if (connman_network_get_associating(network) == true) {
2296 connman_network_clear_associating(network);
2297 connman_network_set_bool(network, "WiFi.UseWPS", false);
2299 service = connman_service_lookup_from_network(network);
2301 if (service != NULL &&
2302 (__connman_service_is_connected_state(service,
2303 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2304 __connman_service_is_connected_state(service,
2305 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2306 (connman_service_get_favorite(service) == false))
2307 __connman_service_set_passphrase(service, NULL);
2310 if (wifi->pending_network == network)
2311 wifi->pending_network = NULL;
2313 if (wifi->scan_pending_network == network)
2314 wifi->scan_pending_network = NULL;
2317 connman_network_set_associating(network, false);
2319 if (wifi->disconnecting)
2322 wifi->disconnecting = true;
2324 #if defined TIZEN_EXT
2325 err = g_supplicant_interface_disconnect(wifi->interface,
2326 disconnect_callback, network);
2328 err = g_supplicant_interface_disconnect(wifi->interface,
2329 disconnect_callback, wifi);
2333 wifi->disconnecting = false;
2338 static struct connman_network_driver network_driver = {
2340 .type = CONNMAN_NETWORK_TYPE_WIFI,
2341 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2342 .probe = network_probe,
2343 .remove = network_remove,
2344 .connect = network_connect,
2345 .disconnect = network_disconnect,
2348 static void interface_added(GSupplicantInterface *interface)
2350 const char *ifname = g_supplicant_interface_get_ifname(interface);
2351 const char *driver = g_supplicant_interface_get_driver(interface);
2352 struct wifi_data *wifi;
2354 wifi = g_supplicant_interface_get_data(interface);
2356 wifi = get_pending_wifi_data(ifname);
2360 g_supplicant_interface_set_data(interface, wifi);
2361 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2362 wifi->p2p_device = true;
2365 DBG("ifname %s driver %s wifi %p tethering %d",
2366 ifname, driver, wifi, wifi->tethering);
2368 if (!wifi->device) {
2369 connman_error("WiFi device not set");
2373 connman_device_set_powered(wifi->device, true);
2376 static bool is_idle(struct wifi_data *wifi)
2378 DBG("state %d", wifi->state);
2380 switch (wifi->state) {
2381 case G_SUPPLICANT_STATE_UNKNOWN:
2382 case G_SUPPLICANT_STATE_DISABLED:
2383 case G_SUPPLICANT_STATE_DISCONNECTED:
2384 case G_SUPPLICANT_STATE_INACTIVE:
2385 case G_SUPPLICANT_STATE_SCANNING:
2388 case G_SUPPLICANT_STATE_AUTHENTICATING:
2389 case G_SUPPLICANT_STATE_ASSOCIATING:
2390 case G_SUPPLICANT_STATE_ASSOCIATED:
2391 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2392 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2393 case G_SUPPLICANT_STATE_COMPLETED:
2400 static bool is_idle_wps(GSupplicantInterface *interface,
2401 struct wifi_data *wifi)
2403 /* First, let's check if WPS processing did not went wrong */
2404 if (g_supplicant_interface_get_wps_state(interface) ==
2405 G_SUPPLICANT_WPS_STATE_FAIL)
2408 /* Unlike normal connection, being associated while processing wps
2409 * actually means that we are idling. */
2410 switch (wifi->state) {
2411 case G_SUPPLICANT_STATE_UNKNOWN:
2412 case G_SUPPLICANT_STATE_DISABLED:
2413 case G_SUPPLICANT_STATE_DISCONNECTED:
2414 case G_SUPPLICANT_STATE_INACTIVE:
2415 case G_SUPPLICANT_STATE_SCANNING:
2416 case G_SUPPLICANT_STATE_ASSOCIATED:
2418 case G_SUPPLICANT_STATE_AUTHENTICATING:
2419 case G_SUPPLICANT_STATE_ASSOCIATING:
2420 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2421 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2422 case G_SUPPLICANT_STATE_COMPLETED:
2429 static bool handle_wps_completion(GSupplicantInterface *interface,
2430 struct connman_network *network,
2431 struct connman_device *device,
2432 struct wifi_data *wifi)
2436 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2438 const unsigned char *ssid, *wps_ssid;
2439 unsigned int ssid_len, wps_ssid_len;
2440 const char *wps_key;
2442 /* Checking if we got associated with requested
2444 ssid = connman_network_get_blob(network, "WiFi.SSID",
2447 wps_ssid = g_supplicant_interface_get_wps_ssid(
2448 interface, &wps_ssid_len);
2450 if (!wps_ssid || wps_ssid_len != ssid_len ||
2451 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2452 connman_network_set_associating(network, false);
2453 #if defined TIZEN_EXT
2454 g_supplicant_interface_disconnect(wifi->interface,
2455 disconnect_callback, wifi->network);
2457 connman_network_set_bool(network, "WiFi.UseWPS", false);
2458 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2460 g_supplicant_interface_disconnect(wifi->interface,
2461 disconnect_callback, wifi);
2466 wps_key = g_supplicant_interface_get_wps_key(interface);
2467 connman_network_set_string(network, "WiFi.Passphrase",
2470 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2476 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2477 struct connman_network *network,
2478 struct wifi_data *wifi)
2480 #if defined TIZEN_EXT
2481 const char *security;
2482 struct connman_service *service;
2484 if (wifi->connected)
2487 security = connman_network_get_string(network, "WiFi.Security");
2489 if (g_str_equal(security, "ieee8021x") == true &&
2490 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2492 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2497 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2500 struct connman_service *service;
2502 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2505 if (wifi->connected)
2509 service = connman_service_lookup_from_network(network);
2515 if (connman_service_get_favorite(service)) {
2516 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2521 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2526 #if defined TIZEN_EXT
2527 static bool handle_wifi_assoc_retry(struct connman_network *network,
2528 struct wifi_data *wifi)
2530 const char *security;
2532 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2533 connman_network_get_connecting(network) != true) {
2534 wifi->assoc_retry_count = 0;
2538 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2539 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2540 wifi->assoc_retry_count = 0;
2544 security = connman_network_get_string(network, "WiFi.Security");
2545 if (g_str_equal(security, "ieee8021x") == true &&
2546 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2547 wifi->assoc_retry_count = 0;
2551 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2552 wifi->assoc_retry_count = 0;
2554 /* Honestly it's not an invalid-key error,
2555 * however QA team recommends that the invalid-key error
2556 * might be better to display for user experience.
2558 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2567 static void interface_state(GSupplicantInterface *interface)
2569 struct connman_network *network;
2570 struct connman_device *device;
2571 struct wifi_data *wifi;
2572 GSupplicantState state = g_supplicant_interface_get_state(interface);
2575 wifi = g_supplicant_interface_get_data(interface);
2577 DBG("wifi %p interface state %d", wifi, state);
2582 device = wifi->device;
2586 if (g_supplicant_interface_get_ready(interface) &&
2587 !wifi->interface_ready) {
2588 wifi->interface_ready = true;
2589 finalize_interface_creation(wifi);
2592 network = wifi->network;
2597 case G_SUPPLICANT_STATE_SCANNING:
2600 case G_SUPPLICANT_STATE_AUTHENTICATING:
2601 case G_SUPPLICANT_STATE_ASSOCIATING:
2602 #if defined TIZEN_EXT
2603 reset_autoscan(device);
2605 stop_autoscan(device);
2608 if (!wifi->connected)
2609 connman_network_set_associating(network, true);
2613 case G_SUPPLICANT_STATE_COMPLETED:
2614 #if defined TIZEN_EXT
2615 /* though it should be already reset: */
2616 reset_autoscan(device);
2618 wifi->assoc_retry_count = 0;
2620 wifi->scan_pending_network = NULL;
2622 /* should be cleared scanning flag */
2623 bool scanning = connman_device_get_scanning(device);
2625 connman_device_set_scanning(device,
2626 CONNMAN_SERVICE_TYPE_WIFI, false);
2627 connman_device_unref(device);
2630 /* though it should be already stopped: */
2631 stop_autoscan(device);
2634 if (!handle_wps_completion(interface, network, device, wifi))
2637 connman_network_set_connected(network, true);
2640 case G_SUPPLICANT_STATE_DISCONNECTED:
2642 * If we're in one of the idle modes, we have
2643 * not started association yet and thus setting
2644 * those ones to FALSE could cancel an association
2647 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2649 if (is_idle_wps(interface, wifi))
2655 /* If previous state was 4way-handshake, then
2656 * it's either: psk was incorrect and thus we retry
2657 * or if we reach the maximum retries we declare the
2659 if (handle_4way_handshake_failure(interface,
2663 #if defined TIZEN_EXT
2664 wifi->disconnect_code = g_supplicant_interface_get_disconnect_reason(wifi->interface);
2665 DBG("Disconnect Reason code %d", wifi->disconnect_code);
2667 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2668 switch (wifi->disconnect_code) {
2669 case 1: /* Unspecified reason */
2670 /* Let's assume it's because we got blocked */
2672 case 6: /* Class 2 frame received from nonauthenticated STA */
2673 connman_network_set_error(network,
2674 CONNMAN_NETWORK_ERROR_BLOCKED);
2682 /* We disable the selected network, if not then
2683 * wpa_supplicant will loop retrying */
2684 if (g_supplicant_interface_enable_selected_network(interface,
2686 DBG("Could not disables selected network");
2688 #if defined TIZEN_EXT
2691 err = g_supplicant_interface_remove_network(wifi->interface);
2693 DBG("Failed to remove network(%d)", err);
2696 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2697 * Retry association until its retry count is expired */
2698 if (handle_wifi_assoc_retry(network, wifi) == true) {
2699 throw_wifi_scan(wifi->device, scan_callback);
2700 wifi->scan_pending_network = wifi->network;
2704 if(wifi->disconnect_code > 0){
2705 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2706 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
2709 /* To avoid unnecessary repeated association in wpa_supplicant,
2710 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2711 if (wps != true && wifi->network && wifi->disconnecting == false) {
2712 wifi->disconnecting = true;
2713 err = g_supplicant_interface_disconnect(wifi->interface,
2714 disconnect_callback, wifi->network);
2716 wifi->disconnecting = false;
2718 connman_network_set_connected(network, false);
2719 connman_network_set_associating(network, false);
2721 start_autoscan(device);
2727 connman_network_set_connected(network, false);
2728 connman_network_set_associating(network, false);
2729 wifi->disconnecting = false;
2731 start_autoscan(device);
2735 case G_SUPPLICANT_STATE_INACTIVE:
2736 #if defined TIZEN_EXT
2737 if (handle_wps_completion(interface, network, device, wifi) == false)
2740 connman_network_set_associating(network, false);
2741 start_autoscan(device);
2745 case G_SUPPLICANT_STATE_UNKNOWN:
2746 case G_SUPPLICANT_STATE_DISABLED:
2747 case G_SUPPLICANT_STATE_ASSOCIATED:
2748 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2749 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2753 wifi->state = state;
2755 /* Saving wpa_s state policy:
2756 * If connected and if the state changes are roaming related:
2757 * --> We stay connected
2759 * --> We are connected
2761 * --> We are not connected
2764 #if defined TIZEN_EXT
2765 case G_SUPPLICANT_STATE_SCANNING:
2768 case G_SUPPLICANT_STATE_AUTHENTICATING:
2769 case G_SUPPLICANT_STATE_ASSOCIATING:
2770 case G_SUPPLICANT_STATE_ASSOCIATED:
2771 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2772 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2773 if (wifi->connected)
2774 connman_warn("Probably roaming right now!"
2775 " Staying connected...");
2777 wifi->connected = false;
2779 case G_SUPPLICANT_STATE_COMPLETED:
2780 wifi->connected = true;
2783 wifi->connected = false;
2790 static void interface_removed(GSupplicantInterface *interface)
2792 const char *ifname = g_supplicant_interface_get_ifname(interface);
2793 struct wifi_data *wifi;
2795 DBG("ifname %s", ifname);
2797 wifi = g_supplicant_interface_get_data(interface);
2800 wifi->interface = NULL;
2802 if (wifi && wifi->tethering)
2805 if (!wifi || !wifi->device) {
2806 DBG("wifi interface already removed");
2810 connman_device_set_powered(wifi->device, false);
2812 check_p2p_technology();
2815 static void set_device_type(const char *type, char dev_type[17])
2817 const char *oui = "0050F204";
2818 const char *category = "0100";
2819 const char *sub_category = "0000";
2821 if (!g_strcmp0(type, "handset")) {
2823 sub_category = "0500";
2824 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2825 sub_category = "0100";
2826 else if (!g_strcmp0(type, "server"))
2827 sub_category = "0200";
2828 else if (!g_strcmp0(type, "laptop"))
2829 sub_category = "0500";
2830 else if (!g_strcmp0(type, "desktop"))
2831 sub_category = "0600";
2832 else if (!g_strcmp0(type, "tablet"))
2833 sub_category = "0900";
2834 else if (!g_strcmp0(type, "watch"))
2837 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2840 static void p2p_support(GSupplicantInterface *interface)
2842 char dev_type[17] = {};
2843 const char *hostname;
2847 if (!g_supplicant_interface_has_p2p(interface))
2850 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2851 DBG("Could not register P2P technology driver");
2855 hostname = connman_utsname_get_hostname();
2857 hostname = "ConnMan";
2859 set_device_type(connman_machine_get_type(), dev_type);
2860 g_supplicant_interface_set_p2p_device_config(interface,
2861 hostname, dev_type);
2862 connman_peer_driver_register(&peer_driver);
2865 static void scan_started(GSupplicantInterface *interface)
2870 static void scan_finished(GSupplicantInterface *interface)
2872 #if defined TIZEN_EXT
2873 struct wifi_data *wifi;
2874 bool is_associating = false;
2875 static bool is_scanning = true;
2880 #if defined TIZEN_EXT
2881 wifi = g_supplicant_interface_get_data(interface);
2882 if (wifi && wifi->scan_pending_network) {
2883 network_connect(wifi->scan_pending_network);
2884 wifi->scan_pending_network = NULL;
2887 //service state - associating
2888 if(!wifi || !wifi->network)
2891 is_associating = connman_network_get_associating(wifi->network);
2892 if(is_associating && is_scanning){
2893 is_scanning = false;
2894 DBG("send scan for connecting");
2895 throw_wifi_scan(wifi->device, scan_callback);
2906 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
2908 unsigned char strength;
2910 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
2917 static void network_added(GSupplicantNetwork *supplicant_network)
2919 struct connman_network *network;
2920 GSupplicantInterface *interface;
2921 struct wifi_data *wifi;
2922 const char *name, *identifier, *security, *group, *mode;
2923 const unsigned char *ssid;
2924 unsigned int ssid_len;
2928 bool wps_advertizing;
2930 mode = g_supplicant_network_get_mode(supplicant_network);
2931 identifier = g_supplicant_network_get_identifier(supplicant_network);
2933 DBG("%s", identifier);
2935 if (!g_strcmp0(mode, "adhoc"))
2938 interface = g_supplicant_network_get_interface(supplicant_network);
2939 wifi = g_supplicant_interface_get_data(interface);
2940 name = g_supplicant_network_get_name(supplicant_network);
2941 security = g_supplicant_network_get_security(supplicant_network);
2942 group = g_supplicant_network_get_identifier(supplicant_network);
2943 wps = g_supplicant_network_get_wps(supplicant_network);
2944 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
2945 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
2946 wps_advertizing = g_supplicant_network_is_wps_advertizing(
2947 supplicant_network);
2952 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
2954 network = connman_device_get_network(wifi->device, identifier);
2957 network = connman_network_create(identifier,
2958 CONNMAN_NETWORK_TYPE_WIFI);
2962 connman_network_set_index(network, wifi->index);
2964 if (connman_device_add_network(wifi->device, network) < 0) {
2965 connman_network_unref(network);
2969 wifi->networks = g_slist_prepend(wifi->networks, network);
2972 if (name && name[0] != '\0')
2973 connman_network_set_name(network, name);
2975 connman_network_set_blob(network, "WiFi.SSID",
2977 connman_network_set_string(network, "WiFi.Security", security);
2978 connman_network_set_strength(network,
2979 calculate_strength(supplicant_network));
2980 connman_network_set_bool(network, "WiFi.WPS", wps);
2983 /* Is AP advertizing for WPS association?
2984 * If so, we decide to use WPS by default */
2985 if (wps_ready && wps_pbc &&
2987 #if !defined TIZEN_EXT
2988 connman_network_set_bool(network, "WiFi.UseWPS", true);
2990 DBG("wps is activating by ap but ignore it.");
2995 connman_network_set_frequency(network,
2996 g_supplicant_network_get_frequency(supplicant_network));
2997 #if defined TIZEN_EXT
2998 connman_network_set_bssid(network,
2999 g_supplicant_network_get_bssid(supplicant_network));
3000 connman_network_set_maxrate(network,
3001 g_supplicant_network_get_maxrate(supplicant_network));
3002 connman_network_set_enc_mode(network,
3003 g_supplicant_network_get_enc_mode(supplicant_network));
3004 connman_network_set_rsn_mode(network,
3005 g_supplicant_network_get_rsn_mode(supplicant_network));
3006 connman_network_set_keymgmt(network,
3007 g_supplicant_network_get_keymgmt(supplicant_network));
3009 connman_network_set_available(network, true);
3010 connman_network_set_string(network, "WiFi.Mode", mode);
3012 #if defined TIZEN_EXT
3017 connman_network_set_group(network, group);
3019 #if defined TIZEN_EXT
3020 if (wifi_first_scan == true)
3021 found_with_first_scan = true;
3024 if (wifi->hidden && ssid) {
3025 #if defined TIZEN_EXT
3026 if (network_security(wifi->hidden->security) ==
3027 network_security(security) &&
3029 if (!g_strcmp0(wifi->hidden->security, security) &&
3031 wifi->hidden->ssid_len == ssid_len &&
3032 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3033 connman_network_connect_hidden(network,
3034 wifi->hidden->identity,
3035 wifi->hidden->passphrase,
3036 wifi->hidden->user_data);
3037 wifi->hidden->user_data = NULL;
3038 hidden_free(wifi->hidden);
3039 wifi->hidden = NULL;
3044 static void network_removed(GSupplicantNetwork *network)
3046 GSupplicantInterface *interface;
3047 struct wifi_data *wifi;
3048 const char *name, *identifier;
3049 struct connman_network *connman_network;
3051 interface = g_supplicant_network_get_interface(network);
3052 wifi = g_supplicant_interface_get_data(interface);
3053 identifier = g_supplicant_network_get_identifier(network);
3054 name = g_supplicant_network_get_name(network);
3056 DBG("name %s", name);
3061 connman_network = connman_device_get_network(wifi->device, identifier);
3062 if (!connman_network)
3065 #if defined TIZEN_EXT
3066 if (connman_network == wifi->scan_pending_network)
3067 wifi->scan_pending_network = NULL;
3069 if (connman_network == wifi->pending_network)
3070 wifi->pending_network = NULL;
3072 if(connman_network_get_connecting(connman_network) == true){
3073 connman_network_set_connected(connman_network, false);
3077 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3079 connman_device_remove_network(wifi->device, connman_network);
3080 connman_network_unref(connman_network);
3083 static void network_changed(GSupplicantNetwork *network, const char *property)
3085 GSupplicantInterface *interface;
3086 struct wifi_data *wifi;
3087 const char *name, *identifier;
3088 struct connman_network *connman_network;
3090 #if defined TIZEN_EXT
3091 const unsigned char *bssid;
3092 unsigned int maxrate;
3097 interface = g_supplicant_network_get_interface(network);
3098 wifi = g_supplicant_interface_get_data(interface);
3099 identifier = g_supplicant_network_get_identifier(network);
3100 name = g_supplicant_network_get_name(network);
3102 DBG("name %s", name);
3107 connman_network = connman_device_get_network(wifi->device, identifier);
3108 if (!connman_network)
3111 if (g_str_equal(property, "Signal")) {
3112 connman_network_set_strength(connman_network,
3113 calculate_strength(network));
3114 connman_network_update(connman_network);
3117 #if defined TIZEN_EXT
3118 bssid = g_supplicant_network_get_bssid(network);
3119 maxrate = g_supplicant_network_get_maxrate(network);
3120 frequency = g_supplicant_network_get_frequency(network);
3121 wps = g_supplicant_network_get_wps(network);
3123 connman_network_set_bssid(connman_network, bssid);
3124 connman_network_set_maxrate(connman_network, maxrate);
3125 connman_network_set_frequency(connman_network, frequency);
3126 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3130 static void apply_peer_services(GSupplicantPeer *peer,
3131 struct connman_peer *connman_peer)
3133 const unsigned char *data;
3138 connman_peer_reset_services(connman_peer);
3140 data = g_supplicant_peer_get_widi_ies(peer, &length);
3142 connman_peer_add_service(connman_peer,
3143 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3147 static void add_station(const char *mac)
3149 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3153 static void remove_station(const char *mac)
3155 connman_technology_tethering_remove_station(mac);
3158 static void peer_found(GSupplicantPeer *peer)
3160 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3161 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3162 struct connman_peer *connman_peer;
3163 const char *identifier, *name;
3166 identifier = g_supplicant_peer_get_identifier(peer);
3167 name = g_supplicant_peer_get_name(peer);
3169 DBG("ident: %s", identifier);
3171 connman_peer = connman_peer_get(wifi->device, identifier);
3175 connman_peer = connman_peer_create(identifier);
3176 connman_peer_set_name(connman_peer, name);
3177 connman_peer_set_device(connman_peer, wifi->device);
3178 apply_peer_services(peer, connman_peer);
3180 ret = connman_peer_register(connman_peer);
3181 if (ret < 0 && ret != -EALREADY)
3182 connman_peer_unref(connman_peer);
3185 static void peer_lost(GSupplicantPeer *peer)
3187 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3188 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3189 struct connman_peer *connman_peer;
3190 const char *identifier;
3195 identifier = g_supplicant_peer_get_identifier(peer);
3197 DBG("ident: %s", identifier);
3199 connman_peer = connman_peer_get(wifi->device, identifier);
3201 if (wifi->p2p_connecting &&
3202 wifi->pending_peer == connman_peer) {
3203 peer_connect_timeout(wifi);
3205 connman_peer_unregister(connman_peer);
3206 connman_peer_unref(connman_peer);
3210 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3212 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3213 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3214 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3215 struct connman_peer *connman_peer;
3216 const char *identifier;
3218 identifier = g_supplicant_peer_get_identifier(peer);
3220 DBG("ident: %s", identifier);
3222 connman_peer = connman_peer_get(wifi->device, identifier);
3227 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3228 apply_peer_services(peer, connman_peer);
3229 connman_peer_services_changed(connman_peer);
3231 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3232 if (!g_supplicant_peer_is_in_a_group(peer))
3233 p_state = CONNMAN_PEER_STATE_IDLE;
3235 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3237 case G_SUPPLICANT_PEER_GROUP_STARTED:
3239 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3240 p_state = CONNMAN_PEER_STATE_IDLE;
3242 case G_SUPPLICANT_PEER_GROUP_JOINED:
3243 connman_peer_set_iface_address(connman_peer,
3244 g_supplicant_peer_get_iface_address(peer));
3246 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3247 p_state = CONNMAN_PEER_STATE_IDLE;
3249 case G_SUPPLICANT_PEER_GROUP_FAILED:
3250 if (g_supplicant_peer_has_requested_connection(peer))
3251 p_state = CONNMAN_PEER_STATE_IDLE;
3253 p_state = CONNMAN_PEER_STATE_FAILURE;
3257 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3258 p_state == CONNMAN_PEER_STATE_FAILURE) {
3259 if (wifi->p2p_connecting
3260 && connman_peer == wifi->pending_peer)
3261 peer_cancel_timeout(wifi);
3263 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3266 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3269 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3270 GSupplicantInterface *g_iface;
3271 struct wifi_data *g_wifi;
3273 g_iface = g_supplicant_peer_get_group_interface(peer);
3277 g_wifi = g_supplicant_interface_get_data(g_iface);
3281 connman_peer_set_as_master(connman_peer,
3282 !g_supplicant_peer_is_client(peer));
3283 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3286 connman_peer_set_state(connman_peer, p_state);
3289 static void peer_request(GSupplicantPeer *peer)
3291 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3292 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3293 struct connman_peer *connman_peer;
3294 const char *identifier;
3296 identifier = g_supplicant_peer_get_identifier(peer);
3298 DBG("ident: %s", identifier);
3300 connman_peer = connman_peer_get(wifi->device, identifier);
3304 connman_peer_request_connection(connman_peer);
3307 #if defined TIZEN_EXT
3308 static void system_power_off(void)
3311 struct wifi_data *wifi;
3312 struct connman_service *service;
3313 struct connman_ipconfig *ipconfig_ipv4;
3315 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3316 for (list = iface_list; list; list = list->next) {
3319 if (wifi->network != NULL) {
3320 service = connman_service_lookup_from_network(wifi->network);
3321 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3322 __connman_dhcp_stop(ipconfig_ipv4);
3328 static void network_merged(GSupplicantNetwork *network)
3330 GSupplicantInterface *interface;
3331 GSupplicantState state;
3332 struct wifi_data *wifi;
3333 const char *identifier;
3334 struct connman_network *connman_network;
3335 unsigned int ishs20AP = 0;
3338 interface = g_supplicant_network_get_interface(network);
3342 state = g_supplicant_interface_get_state(interface);
3343 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3346 wifi = g_supplicant_interface_get_data(interface);
3350 identifier = g_supplicant_network_get_identifier(network);
3352 connman_network = connman_device_get_network(wifi->device, identifier);
3353 if (!connman_network)
3356 DBG("merged identifier %s", identifier);
3358 if (wifi->connected == FALSE) {
3360 case G_SUPPLICANT_STATE_AUTHENTICATING:
3361 case G_SUPPLICANT_STATE_ASSOCIATING:
3362 case G_SUPPLICANT_STATE_ASSOCIATED:
3363 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3364 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3365 connman_network_set_associating(connman_network, TRUE);
3367 case G_SUPPLICANT_STATE_COMPLETED:
3368 connman_network_set_connected(connman_network, TRUE);
3371 DBG("Not handled the state : %d", state);
3376 ishs20AP = g_supplicant_network_is_hs20AP(network);
3377 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3380 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3381 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3382 connman_network_set_string(connman_network, "WiFi.EAP",
3384 connman_network_set_string(connman_network, "WiFi.Identity",
3385 g_supplicant_network_get_identity(network));
3386 connman_network_set_string(connman_network, "WiFi.Phase2",
3387 g_supplicant_network_get_phase2(network));
3392 wifi->network = connman_network;
3396 static void debug(const char *str)
3398 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3399 connman_debug("%s", str);
3402 static const GSupplicantCallbacks callbacks = {
3403 .system_ready = system_ready,
3404 .system_killed = system_killed,
3405 .interface_added = interface_added,
3406 .interface_state = interface_state,
3407 .interface_removed = interface_removed,
3408 .p2p_support = p2p_support,
3409 .scan_started = scan_started,
3410 .scan_finished = scan_finished,
3411 .network_added = network_added,
3412 .network_removed = network_removed,
3413 .network_changed = network_changed,
3414 .add_station = add_station,
3415 .remove_station = remove_station,
3416 .peer_found = peer_found,
3417 .peer_lost = peer_lost,
3418 .peer_changed = peer_changed,
3419 .peer_request = peer_request,
3420 #if defined TIZEN_EXT
3421 .system_power_off = system_power_off,
3422 .network_merged = network_merged,
3428 static int tech_probe(struct connman_technology *technology)
3430 wifi_technology = technology;
3435 static void tech_remove(struct connman_technology *technology)
3437 wifi_technology = NULL;
3440 struct wifi_tethering_info {
3441 struct wifi_data *wifi;
3442 struct connman_technology *technology;
3444 GSupplicantSSID *ssid;
3447 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3448 const char *passphrase, bool hidden)
3450 GSupplicantSSID *ap;
3452 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3456 ap->mode = G_SUPPLICANT_MODE_MASTER;
3458 ap->ssid_len = strlen(ssid);
3462 if (!passphrase || strlen(passphrase) == 0) {
3463 ap->security = G_SUPPLICANT_SECURITY_NONE;
3464 ap->passphrase = NULL;
3466 ap->security = G_SUPPLICANT_SECURITY_PSK;
3467 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3468 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3469 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3470 ap->passphrase = passphrase;
3474 ap->ignore_broadcast_ssid =
3475 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3477 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3482 static void ap_start_callback(int result, GSupplicantInterface *interface,
3485 struct wifi_tethering_info *info = user_data;
3487 DBG("result %d index %d bridge %s",
3488 result, info->wifi->index, info->wifi->bridge);
3491 connman_inet_remove_from_bridge(info->wifi->index,
3492 info->wifi->bridge);
3493 connman_technology_tethering_notify(info->technology, false);
3496 g_free(info->ifname);
3500 static void ap_create_callback(int result,
3501 GSupplicantInterface *interface,
3504 struct wifi_tethering_info *info = user_data;
3506 DBG("result %d ifname %s", result,
3507 g_supplicant_interface_get_ifname(interface));
3510 connman_inet_remove_from_bridge(info->wifi->index,
3511 info->wifi->bridge);
3512 connman_technology_tethering_notify(info->technology, false);
3514 g_free(info->ifname);
3520 info->wifi->interface = interface;
3521 g_supplicant_interface_set_data(interface, info->wifi);
3523 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3524 connman_error("Failed to set interface ap_scan property");
3526 g_supplicant_interface_connect(interface, info->ssid,
3527 ap_start_callback, info);
3530 static void sta_remove_callback(int result,
3531 GSupplicantInterface *interface,
3534 struct wifi_tethering_info *info = user_data;
3535 const char *driver = connman_option_get_string("wifi");
3537 DBG("ifname %s result %d ", info->ifname, result);
3540 info->wifi->tethering = true;
3542 g_free(info->ifname);
3548 info->wifi->interface = NULL;
3550 connman_technology_tethering_notify(info->technology, true);
3552 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3557 static int tech_set_tethering(struct connman_technology *technology,
3558 const char *identifier, const char *passphrase,
3559 const char *bridge, bool enabled, bool hidden)
3562 GSupplicantInterface *interface;
3563 struct wifi_data *wifi;
3564 struct wifi_tethering_info *info;
3572 for (list = iface_list; list; list = list->next) {
3575 if (wifi->tethering) {
3576 wifi->tethering = false;
3578 connman_inet_remove_from_bridge(wifi->index,
3580 wifi->bridged = false;
3584 connman_technology_tethering_notify(technology, false);
3589 for (list = iface_list; list; list = list->next) {
3592 interface = wifi->interface;
3597 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3599 mode = g_supplicant_interface_get_mode(interface);
3600 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3601 DBG("%s does not support AP mode", ifname);
3605 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3610 info->technology = technology;
3611 info->wifi->bridge = bridge;
3612 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3617 info->ifname = g_strdup(ifname);
3618 if (!info->ifname) {
3624 info->wifi->tethering = true;
3626 err = g_supplicant_interface_remove(interface,
3627 sta_remove_callback,
3636 static void regdom_callback(int result, const char *alpha2, void *user_data)
3640 if (!wifi_technology)
3646 connman_technology_regdom_notify(wifi_technology, alpha2);
3649 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3651 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3654 static struct connman_technology_driver tech_driver = {
3656 .type = CONNMAN_SERVICE_TYPE_WIFI,
3657 .probe = tech_probe,
3658 .remove = tech_remove,
3659 .set_tethering = tech_set_tethering,
3660 .set_regdom = tech_set_regdom,
3663 static int wifi_init(void)
3667 err = connman_network_driver_register(&network_driver);
3671 err = g_supplicant_register(&callbacks);
3673 connman_network_driver_unregister(&network_driver);
3677 err = connman_technology_driver_register(&tech_driver);
3679 g_supplicant_unregister(&callbacks);
3680 connman_network_driver_unregister(&network_driver);
3687 static void wifi_exit(void)
3691 connman_technology_driver_unregister(&tech_driver);
3693 g_supplicant_unregister(&callbacks);
3695 connman_network_driver_unregister(&network_driver);
3698 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3699 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)