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);
2173 #if defined TIZEN_EXT
2174 ssid->freq = connman_network_get_frequency(network);
2177 if (connman_setting_get_bool("BackgroundScanning"))
2178 ssid->bgscan = BGSCAN_DEFAULT;
2181 static int network_connect(struct connman_network *network)
2183 struct connman_device *device = connman_network_get_device(network);
2184 struct wifi_data *wifi;
2185 GSupplicantInterface *interface;
2186 GSupplicantSSID *ssid;
2188 DBG("network %p", network);
2193 wifi = connman_device_get_data(device);
2197 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2201 interface = wifi->interface;
2203 ssid_init(ssid, network);
2205 if (wifi->disconnecting) {
2206 wifi->pending_network = network;
2209 wifi->network = connman_network_ref(network);
2211 #if defined TIZEN_EXT
2212 wifi->scan_pending_network = NULL;
2215 return g_supplicant_interface_connect(interface, ssid,
2216 connect_callback, network);
2219 return -EINPROGRESS;
2222 static void disconnect_callback(int result, GSupplicantInterface *interface,
2225 #if defined TIZEN_EXT
2227 struct wifi_data *wifi;
2228 struct connman_network *network = user_data;
2230 DBG("network %p result %d", network, result);
2232 for (list = iface_list; list; list = list->next) {
2235 if (wifi->network == NULL && wifi->disconnecting == true)
2236 wifi->disconnecting = false;
2238 if (wifi->network == network)
2242 /* wifi_data may be invalid because wifi is already disabled */
2247 struct wifi_data *wifi = user_data;
2250 DBG("result %d supplicant interface %p wifi %p",
2251 result, interface, wifi);
2253 if (result == -ECONNABORTED) {
2254 DBG("wifi interface no longer available");
2258 if (wifi->network) {
2260 * if result < 0 supplican return an error because
2261 * the network is not current.
2262 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2263 * failed, call connman_network_set_connected to report
2264 * disconnect is completed.
2267 connman_network_set_connected(wifi->network, false);
2270 wifi->network = NULL;
2272 wifi->disconnecting = false;
2274 if (wifi->pending_network) {
2275 network_connect(wifi->pending_network);
2276 wifi->pending_network = NULL;
2279 start_autoscan(wifi->device);
2282 static int network_disconnect(struct connman_network *network)
2284 struct connman_device *device = connman_network_get_device(network);
2285 struct wifi_data *wifi;
2287 #if defined TIZEN_EXT
2288 struct connman_service *service;
2291 DBG("network %p", network);
2293 wifi = connman_device_get_data(device);
2294 if (!wifi || !wifi->interface)
2297 #if defined TIZEN_EXT
2298 if (connman_network_get_associating(network) == true) {
2299 connman_network_clear_associating(network);
2300 connman_network_set_bool(network, "WiFi.UseWPS", false);
2302 service = connman_service_lookup_from_network(network);
2304 if (service != NULL &&
2305 (__connman_service_is_connected_state(service,
2306 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2307 __connman_service_is_connected_state(service,
2308 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2309 (connman_service_get_favorite(service) == false))
2310 __connman_service_set_passphrase(service, NULL);
2313 if (wifi->pending_network == network)
2314 wifi->pending_network = NULL;
2316 if (wifi->scan_pending_network == network)
2317 wifi->scan_pending_network = NULL;
2320 connman_network_set_associating(network, false);
2322 if (wifi->disconnecting)
2325 wifi->disconnecting = true;
2327 #if defined TIZEN_EXT
2328 err = g_supplicant_interface_disconnect(wifi->interface,
2329 disconnect_callback, network);
2331 err = g_supplicant_interface_disconnect(wifi->interface,
2332 disconnect_callback, wifi);
2336 wifi->disconnecting = false;
2341 static struct connman_network_driver network_driver = {
2343 .type = CONNMAN_NETWORK_TYPE_WIFI,
2344 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2345 .probe = network_probe,
2346 .remove = network_remove,
2347 .connect = network_connect,
2348 .disconnect = network_disconnect,
2351 static void interface_added(GSupplicantInterface *interface)
2353 const char *ifname = g_supplicant_interface_get_ifname(interface);
2354 const char *driver = g_supplicant_interface_get_driver(interface);
2355 struct wifi_data *wifi;
2357 wifi = g_supplicant_interface_get_data(interface);
2359 wifi = get_pending_wifi_data(ifname);
2363 g_supplicant_interface_set_data(interface, wifi);
2364 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2365 wifi->p2p_device = true;
2368 DBG("ifname %s driver %s wifi %p tethering %d",
2369 ifname, driver, wifi, wifi->tethering);
2371 if (!wifi->device) {
2372 connman_error("WiFi device not set");
2376 connman_device_set_powered(wifi->device, true);
2379 static bool is_idle(struct wifi_data *wifi)
2381 DBG("state %d", wifi->state);
2383 switch (wifi->state) {
2384 case G_SUPPLICANT_STATE_UNKNOWN:
2385 case G_SUPPLICANT_STATE_DISABLED:
2386 case G_SUPPLICANT_STATE_DISCONNECTED:
2387 case G_SUPPLICANT_STATE_INACTIVE:
2388 case G_SUPPLICANT_STATE_SCANNING:
2391 case G_SUPPLICANT_STATE_AUTHENTICATING:
2392 case G_SUPPLICANT_STATE_ASSOCIATING:
2393 case G_SUPPLICANT_STATE_ASSOCIATED:
2394 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2395 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2396 case G_SUPPLICANT_STATE_COMPLETED:
2403 static bool is_idle_wps(GSupplicantInterface *interface,
2404 struct wifi_data *wifi)
2406 /* First, let's check if WPS processing did not went wrong */
2407 if (g_supplicant_interface_get_wps_state(interface) ==
2408 G_SUPPLICANT_WPS_STATE_FAIL)
2411 /* Unlike normal connection, being associated while processing wps
2412 * actually means that we are idling. */
2413 switch (wifi->state) {
2414 case G_SUPPLICANT_STATE_UNKNOWN:
2415 case G_SUPPLICANT_STATE_DISABLED:
2416 case G_SUPPLICANT_STATE_DISCONNECTED:
2417 case G_SUPPLICANT_STATE_INACTIVE:
2418 case G_SUPPLICANT_STATE_SCANNING:
2419 case G_SUPPLICANT_STATE_ASSOCIATED:
2421 case G_SUPPLICANT_STATE_AUTHENTICATING:
2422 case G_SUPPLICANT_STATE_ASSOCIATING:
2423 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2424 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2425 case G_SUPPLICANT_STATE_COMPLETED:
2432 static bool handle_wps_completion(GSupplicantInterface *interface,
2433 struct connman_network *network,
2434 struct connman_device *device,
2435 struct wifi_data *wifi)
2439 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2441 const unsigned char *ssid, *wps_ssid;
2442 unsigned int ssid_len, wps_ssid_len;
2443 const char *wps_key;
2445 /* Checking if we got associated with requested
2447 ssid = connman_network_get_blob(network, "WiFi.SSID",
2450 wps_ssid = g_supplicant_interface_get_wps_ssid(
2451 interface, &wps_ssid_len);
2453 if (!wps_ssid || wps_ssid_len != ssid_len ||
2454 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2455 connman_network_set_associating(network, false);
2456 #if defined TIZEN_EXT
2457 g_supplicant_interface_disconnect(wifi->interface,
2458 disconnect_callback, wifi->network);
2460 connman_network_set_bool(network, "WiFi.UseWPS", false);
2461 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2463 g_supplicant_interface_disconnect(wifi->interface,
2464 disconnect_callback, wifi);
2469 wps_key = g_supplicant_interface_get_wps_key(interface);
2470 connman_network_set_string(network, "WiFi.Passphrase",
2473 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2479 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2480 struct connman_network *network,
2481 struct wifi_data *wifi)
2483 #if defined TIZEN_EXT
2484 const char *security;
2485 struct connman_service *service;
2487 if (wifi->connected)
2490 security = connman_network_get_string(network, "WiFi.Security");
2492 if (g_str_equal(security, "ieee8021x") == true &&
2493 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2495 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2500 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2503 struct connman_service *service;
2505 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2508 if (wifi->connected)
2512 service = connman_service_lookup_from_network(network);
2518 if (connman_service_get_favorite(service)) {
2519 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2524 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2529 #if defined TIZEN_EXT
2530 static bool handle_wifi_assoc_retry(struct connman_network *network,
2531 struct wifi_data *wifi)
2533 const char *security;
2535 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2536 connman_network_get_connecting(network) != true) {
2537 wifi->assoc_retry_count = 0;
2541 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2542 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2543 wifi->assoc_retry_count = 0;
2547 security = connman_network_get_string(network, "WiFi.Security");
2548 if (g_str_equal(security, "ieee8021x") == true &&
2549 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2550 wifi->assoc_retry_count = 0;
2554 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2555 wifi->assoc_retry_count = 0;
2557 /* Honestly it's not an invalid-key error,
2558 * however QA team recommends that the invalid-key error
2559 * might be better to display for user experience.
2561 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2570 static void interface_state(GSupplicantInterface *interface)
2572 struct connman_network *network;
2573 struct connman_device *device;
2574 struct wifi_data *wifi;
2575 GSupplicantState state = g_supplicant_interface_get_state(interface);
2578 wifi = g_supplicant_interface_get_data(interface);
2580 DBG("wifi %p interface state %d", wifi, state);
2585 device = wifi->device;
2589 if (g_supplicant_interface_get_ready(interface) &&
2590 !wifi->interface_ready) {
2591 wifi->interface_ready = true;
2592 finalize_interface_creation(wifi);
2595 network = wifi->network;
2600 case G_SUPPLICANT_STATE_SCANNING:
2603 case G_SUPPLICANT_STATE_AUTHENTICATING:
2604 case G_SUPPLICANT_STATE_ASSOCIATING:
2605 #if defined TIZEN_EXT
2606 reset_autoscan(device);
2608 stop_autoscan(device);
2611 if (!wifi->connected)
2612 connman_network_set_associating(network, true);
2616 case G_SUPPLICANT_STATE_COMPLETED:
2617 #if defined TIZEN_EXT
2618 /* though it should be already reset: */
2619 reset_autoscan(device);
2621 wifi->assoc_retry_count = 0;
2623 wifi->scan_pending_network = NULL;
2625 /* should be cleared scanning flag */
2626 bool scanning = connman_device_get_scanning(device);
2628 connman_device_set_scanning(device,
2629 CONNMAN_SERVICE_TYPE_WIFI, false);
2630 connman_device_unref(device);
2633 /* though it should be already stopped: */
2634 stop_autoscan(device);
2637 if (!handle_wps_completion(interface, network, device, wifi))
2640 connman_network_set_connected(network, true);
2643 case G_SUPPLICANT_STATE_DISCONNECTED:
2645 * If we're in one of the idle modes, we have
2646 * not started association yet and thus setting
2647 * those ones to FALSE could cancel an association
2650 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2652 if (is_idle_wps(interface, wifi))
2658 /* If previous state was 4way-handshake, then
2659 * it's either: psk was incorrect and thus we retry
2660 * or if we reach the maximum retries we declare the
2662 if (handle_4way_handshake_failure(interface,
2666 #if defined TIZEN_EXT
2667 wifi->disconnect_code = g_supplicant_interface_get_disconnect_reason(wifi->interface);
2668 DBG("Disconnect Reason code %d", wifi->disconnect_code);
2670 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2671 switch (wifi->disconnect_code) {
2672 case 1: /* Unspecified reason */
2673 /* Let's assume it's because we got blocked */
2675 case 6: /* Class 2 frame received from nonauthenticated STA */
2676 connman_network_set_error(network,
2677 CONNMAN_NETWORK_ERROR_BLOCKED);
2685 /* We disable the selected network, if not then
2686 * wpa_supplicant will loop retrying */
2687 if (g_supplicant_interface_enable_selected_network(interface,
2689 DBG("Could not disables selected network");
2691 #if defined TIZEN_EXT
2694 err = g_supplicant_interface_remove_network(wifi->interface);
2696 DBG("Failed to remove network(%d)", err);
2699 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2700 * Retry association until its retry count is expired */
2701 if (handle_wifi_assoc_retry(network, wifi) == true) {
2702 throw_wifi_scan(wifi->device, scan_callback);
2703 wifi->scan_pending_network = wifi->network;
2707 if(wifi->disconnect_code > 0){
2708 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2709 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
2712 /* To avoid unnecessary repeated association in wpa_supplicant,
2713 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2714 if (wps != true && wifi->network && wifi->disconnecting == false) {
2715 wifi->disconnecting = true;
2716 err = g_supplicant_interface_disconnect(wifi->interface,
2717 disconnect_callback, wifi->network);
2719 wifi->disconnecting = false;
2721 connman_network_set_connected(network, false);
2722 connman_network_set_associating(network, false);
2724 start_autoscan(device);
2730 connman_network_set_connected(network, false);
2731 connman_network_set_associating(network, false);
2732 wifi->disconnecting = false;
2734 start_autoscan(device);
2738 case G_SUPPLICANT_STATE_INACTIVE:
2739 #if defined TIZEN_EXT
2740 if (handle_wps_completion(interface, network, device, wifi) == false)
2743 connman_network_set_associating(network, false);
2744 start_autoscan(device);
2748 case G_SUPPLICANT_STATE_UNKNOWN:
2749 case G_SUPPLICANT_STATE_DISABLED:
2750 case G_SUPPLICANT_STATE_ASSOCIATED:
2751 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2752 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2756 wifi->state = state;
2758 /* Saving wpa_s state policy:
2759 * If connected and if the state changes are roaming related:
2760 * --> We stay connected
2762 * --> We are connected
2764 * --> We are not connected
2767 #if defined TIZEN_EXT
2768 case G_SUPPLICANT_STATE_SCANNING:
2771 case G_SUPPLICANT_STATE_AUTHENTICATING:
2772 case G_SUPPLICANT_STATE_ASSOCIATING:
2773 case G_SUPPLICANT_STATE_ASSOCIATED:
2774 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2775 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2776 if (wifi->connected)
2777 connman_warn("Probably roaming right now!"
2778 " Staying connected...");
2780 wifi->connected = false;
2782 case G_SUPPLICANT_STATE_COMPLETED:
2783 wifi->connected = true;
2786 wifi->connected = false;
2793 static void interface_removed(GSupplicantInterface *interface)
2795 const char *ifname = g_supplicant_interface_get_ifname(interface);
2796 struct wifi_data *wifi;
2798 DBG("ifname %s", ifname);
2800 wifi = g_supplicant_interface_get_data(interface);
2803 wifi->interface = NULL;
2805 if (wifi && wifi->tethering)
2808 if (!wifi || !wifi->device) {
2809 DBG("wifi interface already removed");
2813 connman_device_set_powered(wifi->device, false);
2815 check_p2p_technology();
2818 static void set_device_type(const char *type, char dev_type[17])
2820 const char *oui = "0050F204";
2821 const char *category = "0100";
2822 const char *sub_category = "0000";
2824 if (!g_strcmp0(type, "handset")) {
2826 sub_category = "0500";
2827 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2828 sub_category = "0100";
2829 else if (!g_strcmp0(type, "server"))
2830 sub_category = "0200";
2831 else if (!g_strcmp0(type, "laptop"))
2832 sub_category = "0500";
2833 else if (!g_strcmp0(type, "desktop"))
2834 sub_category = "0600";
2835 else if (!g_strcmp0(type, "tablet"))
2836 sub_category = "0900";
2837 else if (!g_strcmp0(type, "watch"))
2840 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2843 static void p2p_support(GSupplicantInterface *interface)
2845 char dev_type[17] = {};
2846 const char *hostname;
2850 if (!g_supplicant_interface_has_p2p(interface))
2853 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2854 DBG("Could not register P2P technology driver");
2858 hostname = connman_utsname_get_hostname();
2860 hostname = "ConnMan";
2862 set_device_type(connman_machine_get_type(), dev_type);
2863 g_supplicant_interface_set_p2p_device_config(interface,
2864 hostname, dev_type);
2865 connman_peer_driver_register(&peer_driver);
2868 static void scan_started(GSupplicantInterface *interface)
2873 static void scan_finished(GSupplicantInterface *interface)
2875 #if defined TIZEN_EXT
2876 struct wifi_data *wifi;
2877 bool is_associating = false;
2878 static bool is_scanning = true;
2883 #if defined TIZEN_EXT
2884 wifi = g_supplicant_interface_get_data(interface);
2885 if (wifi && wifi->scan_pending_network) {
2886 network_connect(wifi->scan_pending_network);
2887 wifi->scan_pending_network = NULL;
2890 //service state - associating
2891 if(!wifi || !wifi->network)
2894 is_associating = connman_network_get_associating(wifi->network);
2895 if(is_associating && is_scanning){
2896 is_scanning = false;
2897 DBG("send scan for connecting");
2898 throw_wifi_scan(wifi->device, scan_callback);
2909 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
2911 unsigned char strength;
2913 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
2920 static void network_added(GSupplicantNetwork *supplicant_network)
2922 struct connman_network *network;
2923 GSupplicantInterface *interface;
2924 struct wifi_data *wifi;
2925 const char *name, *identifier, *security, *group, *mode;
2926 const unsigned char *ssid;
2927 unsigned int ssid_len;
2931 bool wps_advertizing;
2933 mode = g_supplicant_network_get_mode(supplicant_network);
2934 identifier = g_supplicant_network_get_identifier(supplicant_network);
2936 DBG("%s", identifier);
2938 if (!g_strcmp0(mode, "adhoc"))
2941 interface = g_supplicant_network_get_interface(supplicant_network);
2942 wifi = g_supplicant_interface_get_data(interface);
2943 name = g_supplicant_network_get_name(supplicant_network);
2944 security = g_supplicant_network_get_security(supplicant_network);
2945 group = g_supplicant_network_get_identifier(supplicant_network);
2946 wps = g_supplicant_network_get_wps(supplicant_network);
2947 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
2948 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
2949 wps_advertizing = g_supplicant_network_is_wps_advertizing(
2950 supplicant_network);
2955 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
2957 network = connman_device_get_network(wifi->device, identifier);
2960 network = connman_network_create(identifier,
2961 CONNMAN_NETWORK_TYPE_WIFI);
2965 connman_network_set_index(network, wifi->index);
2967 if (connman_device_add_network(wifi->device, network) < 0) {
2968 connman_network_unref(network);
2972 wifi->networks = g_slist_prepend(wifi->networks, network);
2975 if (name && name[0] != '\0')
2976 connman_network_set_name(network, name);
2978 connman_network_set_blob(network, "WiFi.SSID",
2980 connman_network_set_string(network, "WiFi.Security", security);
2981 connman_network_set_strength(network,
2982 calculate_strength(supplicant_network));
2983 connman_network_set_bool(network, "WiFi.WPS", wps);
2986 /* Is AP advertizing for WPS association?
2987 * If so, we decide to use WPS by default */
2988 if (wps_ready && wps_pbc &&
2990 #if !defined TIZEN_EXT
2991 connman_network_set_bool(network, "WiFi.UseWPS", true);
2993 DBG("wps is activating by ap but ignore it.");
2998 connman_network_set_frequency(network,
2999 g_supplicant_network_get_frequency(supplicant_network));
3000 #if defined TIZEN_EXT
3001 connman_network_set_bssid(network,
3002 g_supplicant_network_get_bssid(supplicant_network));
3003 connman_network_set_maxrate(network,
3004 g_supplicant_network_get_maxrate(supplicant_network));
3005 connman_network_set_enc_mode(network,
3006 g_supplicant_network_get_enc_mode(supplicant_network));
3007 connman_network_set_rsn_mode(network,
3008 g_supplicant_network_get_rsn_mode(supplicant_network));
3009 connman_network_set_keymgmt(network,
3010 g_supplicant_network_get_keymgmt(supplicant_network));
3012 connman_network_set_available(network, true);
3013 connman_network_set_string(network, "WiFi.Mode", mode);
3015 #if defined TIZEN_EXT
3020 connman_network_set_group(network, group);
3022 #if defined TIZEN_EXT
3023 if (wifi_first_scan == true)
3024 found_with_first_scan = true;
3027 if (wifi->hidden && ssid) {
3028 #if defined TIZEN_EXT
3029 if (network_security(wifi->hidden->security) ==
3030 network_security(security) &&
3032 if (!g_strcmp0(wifi->hidden->security, security) &&
3034 wifi->hidden->ssid_len == ssid_len &&
3035 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3036 connman_network_connect_hidden(network,
3037 wifi->hidden->identity,
3038 wifi->hidden->passphrase,
3039 wifi->hidden->user_data);
3040 wifi->hidden->user_data = NULL;
3041 hidden_free(wifi->hidden);
3042 wifi->hidden = NULL;
3047 static void network_removed(GSupplicantNetwork *network)
3049 GSupplicantInterface *interface;
3050 struct wifi_data *wifi;
3051 const char *name, *identifier;
3052 struct connman_network *connman_network;
3054 interface = g_supplicant_network_get_interface(network);
3055 wifi = g_supplicant_interface_get_data(interface);
3056 identifier = g_supplicant_network_get_identifier(network);
3057 name = g_supplicant_network_get_name(network);
3059 DBG("name %s", name);
3064 connman_network = connman_device_get_network(wifi->device, identifier);
3065 if (!connman_network)
3068 #if defined TIZEN_EXT
3069 if (connman_network == wifi->scan_pending_network)
3070 wifi->scan_pending_network = NULL;
3072 if (connman_network == wifi->pending_network)
3073 wifi->pending_network = NULL;
3075 if(connman_network_get_connecting(connman_network) == true){
3076 connman_network_set_connected(connman_network, false);
3080 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3082 connman_device_remove_network(wifi->device, connman_network);
3083 connman_network_unref(connman_network);
3086 static void network_changed(GSupplicantNetwork *network, const char *property)
3088 GSupplicantInterface *interface;
3089 struct wifi_data *wifi;
3090 const char *name, *identifier;
3091 struct connman_network *connman_network;
3093 #if defined TIZEN_EXT
3094 const unsigned char *bssid;
3095 unsigned int maxrate;
3100 interface = g_supplicant_network_get_interface(network);
3101 wifi = g_supplicant_interface_get_data(interface);
3102 identifier = g_supplicant_network_get_identifier(network);
3103 name = g_supplicant_network_get_name(network);
3105 DBG("name %s", name);
3110 connman_network = connman_device_get_network(wifi->device, identifier);
3111 if (!connman_network)
3114 if (g_str_equal(property, "Signal")) {
3115 connman_network_set_strength(connman_network,
3116 calculate_strength(network));
3117 connman_network_update(connman_network);
3120 #if defined TIZEN_EXT
3121 bssid = g_supplicant_network_get_bssid(network);
3122 maxrate = g_supplicant_network_get_maxrate(network);
3123 frequency = g_supplicant_network_get_frequency(network);
3124 wps = g_supplicant_network_get_wps(network);
3126 connman_network_set_bssid(connman_network, bssid);
3127 connman_network_set_maxrate(connman_network, maxrate);
3128 connman_network_set_frequency(connman_network, frequency);
3129 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3133 static void apply_peer_services(GSupplicantPeer *peer,
3134 struct connman_peer *connman_peer)
3136 const unsigned char *data;
3141 connman_peer_reset_services(connman_peer);
3143 data = g_supplicant_peer_get_widi_ies(peer, &length);
3145 connman_peer_add_service(connman_peer,
3146 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3150 static void add_station(const char *mac)
3152 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3156 static void remove_station(const char *mac)
3158 connman_technology_tethering_remove_station(mac);
3161 static void peer_found(GSupplicantPeer *peer)
3163 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3164 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3165 struct connman_peer *connman_peer;
3166 const char *identifier, *name;
3169 identifier = g_supplicant_peer_get_identifier(peer);
3170 name = g_supplicant_peer_get_name(peer);
3172 DBG("ident: %s", identifier);
3174 connman_peer = connman_peer_get(wifi->device, identifier);
3178 connman_peer = connman_peer_create(identifier);
3179 connman_peer_set_name(connman_peer, name);
3180 connman_peer_set_device(connman_peer, wifi->device);
3181 apply_peer_services(peer, connman_peer);
3183 ret = connman_peer_register(connman_peer);
3184 if (ret < 0 && ret != -EALREADY)
3185 connman_peer_unref(connman_peer);
3188 static void peer_lost(GSupplicantPeer *peer)
3190 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3191 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3192 struct connman_peer *connman_peer;
3193 const char *identifier;
3198 identifier = g_supplicant_peer_get_identifier(peer);
3200 DBG("ident: %s", identifier);
3202 connman_peer = connman_peer_get(wifi->device, identifier);
3204 if (wifi->p2p_connecting &&
3205 wifi->pending_peer == connman_peer) {
3206 peer_connect_timeout(wifi);
3208 connman_peer_unregister(connman_peer);
3209 connman_peer_unref(connman_peer);
3213 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3215 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3216 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3217 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3218 struct connman_peer *connman_peer;
3219 const char *identifier;
3221 identifier = g_supplicant_peer_get_identifier(peer);
3223 DBG("ident: %s", identifier);
3225 connman_peer = connman_peer_get(wifi->device, identifier);
3230 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3231 apply_peer_services(peer, connman_peer);
3232 connman_peer_services_changed(connman_peer);
3234 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3235 if (!g_supplicant_peer_is_in_a_group(peer))
3236 p_state = CONNMAN_PEER_STATE_IDLE;
3238 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3240 case G_SUPPLICANT_PEER_GROUP_STARTED:
3242 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3243 p_state = CONNMAN_PEER_STATE_IDLE;
3245 case G_SUPPLICANT_PEER_GROUP_JOINED:
3246 connman_peer_set_iface_address(connman_peer,
3247 g_supplicant_peer_get_iface_address(peer));
3249 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3250 p_state = CONNMAN_PEER_STATE_IDLE;
3252 case G_SUPPLICANT_PEER_GROUP_FAILED:
3253 if (g_supplicant_peer_has_requested_connection(peer))
3254 p_state = CONNMAN_PEER_STATE_IDLE;
3256 p_state = CONNMAN_PEER_STATE_FAILURE;
3260 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3261 p_state == CONNMAN_PEER_STATE_FAILURE) {
3262 if (wifi->p2p_connecting
3263 && connman_peer == wifi->pending_peer)
3264 peer_cancel_timeout(wifi);
3266 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3269 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3272 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3273 GSupplicantInterface *g_iface;
3274 struct wifi_data *g_wifi;
3276 g_iface = g_supplicant_peer_get_group_interface(peer);
3280 g_wifi = g_supplicant_interface_get_data(g_iface);
3284 connman_peer_set_as_master(connman_peer,
3285 !g_supplicant_peer_is_client(peer));
3286 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3289 connman_peer_set_state(connman_peer, p_state);
3292 static void peer_request(GSupplicantPeer *peer)
3294 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3295 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3296 struct connman_peer *connman_peer;
3297 const char *identifier;
3299 identifier = g_supplicant_peer_get_identifier(peer);
3301 DBG("ident: %s", identifier);
3303 connman_peer = connman_peer_get(wifi->device, identifier);
3307 connman_peer_request_connection(connman_peer);
3310 #if defined TIZEN_EXT
3311 static void system_power_off(void)
3314 struct wifi_data *wifi;
3315 struct connman_service *service;
3316 struct connman_ipconfig *ipconfig_ipv4;
3318 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3319 for (list = iface_list; list; list = list->next) {
3322 if (wifi->network != NULL) {
3323 service = connman_service_lookup_from_network(wifi->network);
3324 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3325 __connman_dhcp_stop(ipconfig_ipv4);
3331 static void network_merged(GSupplicantNetwork *network)
3333 GSupplicantInterface *interface;
3334 GSupplicantState state;
3335 struct wifi_data *wifi;
3336 const char *identifier;
3337 struct connman_network *connman_network;
3338 unsigned int ishs20AP = 0;
3341 interface = g_supplicant_network_get_interface(network);
3345 state = g_supplicant_interface_get_state(interface);
3346 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3349 wifi = g_supplicant_interface_get_data(interface);
3353 identifier = g_supplicant_network_get_identifier(network);
3355 connman_network = connman_device_get_network(wifi->device, identifier);
3356 if (!connman_network)
3359 DBG("merged identifier %s", identifier);
3361 if (wifi->connected == FALSE) {
3363 case G_SUPPLICANT_STATE_AUTHENTICATING:
3364 case G_SUPPLICANT_STATE_ASSOCIATING:
3365 case G_SUPPLICANT_STATE_ASSOCIATED:
3366 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3367 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3368 connman_network_set_associating(connman_network, TRUE);
3370 case G_SUPPLICANT_STATE_COMPLETED:
3371 connman_network_set_connected(connman_network, TRUE);
3374 DBG("Not handled the state : %d", state);
3379 ishs20AP = g_supplicant_network_is_hs20AP(network);
3380 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3383 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3384 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3385 connman_network_set_string(connman_network, "WiFi.EAP",
3387 connman_network_set_string(connman_network, "WiFi.Identity",
3388 g_supplicant_network_get_identity(network));
3389 connman_network_set_string(connman_network, "WiFi.Phase2",
3390 g_supplicant_network_get_phase2(network));
3395 wifi->network = connman_network;
3399 static void debug(const char *str)
3401 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3402 connman_debug("%s", str);
3405 static const GSupplicantCallbacks callbacks = {
3406 .system_ready = system_ready,
3407 .system_killed = system_killed,
3408 .interface_added = interface_added,
3409 .interface_state = interface_state,
3410 .interface_removed = interface_removed,
3411 .p2p_support = p2p_support,
3412 .scan_started = scan_started,
3413 .scan_finished = scan_finished,
3414 .network_added = network_added,
3415 .network_removed = network_removed,
3416 .network_changed = network_changed,
3417 .add_station = add_station,
3418 .remove_station = remove_station,
3419 .peer_found = peer_found,
3420 .peer_lost = peer_lost,
3421 .peer_changed = peer_changed,
3422 .peer_request = peer_request,
3423 #if defined TIZEN_EXT
3424 .system_power_off = system_power_off,
3425 .network_merged = network_merged,
3431 static int tech_probe(struct connman_technology *technology)
3433 wifi_technology = technology;
3438 static void tech_remove(struct connman_technology *technology)
3440 wifi_technology = NULL;
3443 struct wifi_tethering_info {
3444 struct wifi_data *wifi;
3445 struct connman_technology *technology;
3447 GSupplicantSSID *ssid;
3450 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3451 const char *passphrase, bool hidden)
3453 GSupplicantSSID *ap;
3455 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3459 ap->mode = G_SUPPLICANT_MODE_MASTER;
3461 ap->ssid_len = strlen(ssid);
3465 if (!passphrase || strlen(passphrase) == 0) {
3466 ap->security = G_SUPPLICANT_SECURITY_NONE;
3467 ap->passphrase = NULL;
3469 ap->security = G_SUPPLICANT_SECURITY_PSK;
3470 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3471 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3472 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3473 ap->passphrase = passphrase;
3477 ap->ignore_broadcast_ssid =
3478 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3480 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3485 static void ap_start_callback(int result, GSupplicantInterface *interface,
3488 struct wifi_tethering_info *info = user_data;
3490 DBG("result %d index %d bridge %s",
3491 result, info->wifi->index, info->wifi->bridge);
3494 connman_inet_remove_from_bridge(info->wifi->index,
3495 info->wifi->bridge);
3496 connman_technology_tethering_notify(info->technology, false);
3499 g_free(info->ifname);
3503 static void ap_create_callback(int result,
3504 GSupplicantInterface *interface,
3507 struct wifi_tethering_info *info = user_data;
3509 DBG("result %d ifname %s", result,
3510 g_supplicant_interface_get_ifname(interface));
3513 connman_inet_remove_from_bridge(info->wifi->index,
3514 info->wifi->bridge);
3515 connman_technology_tethering_notify(info->technology, false);
3517 g_free(info->ifname);
3523 info->wifi->interface = interface;
3524 g_supplicant_interface_set_data(interface, info->wifi);
3526 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3527 connman_error("Failed to set interface ap_scan property");
3529 g_supplicant_interface_connect(interface, info->ssid,
3530 ap_start_callback, info);
3533 static void sta_remove_callback(int result,
3534 GSupplicantInterface *interface,
3537 struct wifi_tethering_info *info = user_data;
3538 const char *driver = connman_option_get_string("wifi");
3540 DBG("ifname %s result %d ", info->ifname, result);
3543 info->wifi->tethering = true;
3545 g_free(info->ifname);
3551 info->wifi->interface = NULL;
3553 connman_technology_tethering_notify(info->technology, true);
3555 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3560 static int tech_set_tethering(struct connman_technology *technology,
3561 const char *identifier, const char *passphrase,
3562 const char *bridge, bool enabled, bool hidden)
3565 GSupplicantInterface *interface;
3566 struct wifi_data *wifi;
3567 struct wifi_tethering_info *info;
3575 for (list = iface_list; list; list = list->next) {
3578 if (wifi->tethering) {
3579 wifi->tethering = false;
3581 connman_inet_remove_from_bridge(wifi->index,
3583 wifi->bridged = false;
3587 connman_technology_tethering_notify(technology, false);
3592 for (list = iface_list; list; list = list->next) {
3595 interface = wifi->interface;
3600 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3602 mode = g_supplicant_interface_get_mode(interface);
3603 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3604 DBG("%s does not support AP mode", ifname);
3608 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3613 info->technology = technology;
3614 info->wifi->bridge = bridge;
3615 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3620 info->ifname = g_strdup(ifname);
3621 if (!info->ifname) {
3627 info->wifi->tethering = true;
3629 err = g_supplicant_interface_remove(interface,
3630 sta_remove_callback,
3639 static void regdom_callback(int result, const char *alpha2, void *user_data)
3643 if (!wifi_technology)
3649 connman_technology_regdom_notify(wifi_technology, alpha2);
3652 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3654 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3657 static struct connman_technology_driver tech_driver = {
3659 .type = CONNMAN_SERVICE_TYPE_WIFI,
3660 .probe = tech_probe,
3661 .remove = tech_remove,
3662 .set_tethering = tech_set_tethering,
3663 .set_regdom = tech_set_regdom,
3666 static int wifi_init(void)
3670 err = connman_network_driver_register(&network_driver);
3674 err = g_supplicant_register(&callbacks);
3676 connman_network_driver_unregister(&network_driver);
3680 err = connman_technology_driver_register(&tech_driver);
3682 g_supplicant_unregister(&callbacks);
3683 connman_network_driver_unregister(&network_driver);
3690 static void wifi_exit(void)
3694 connman_technology_driver_unregister(&tech_driver);
3696 g_supplicant_unregister(&callbacks);
3698 connman_network_driver_unregister(&network_driver);
3701 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3702 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)