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;
138 #if defined TIZEN_EXT
141 #define TIZEN_ASSOC_RETRY_COUNT 4
143 static gboolean wifi_first_scan = false;
144 static gboolean found_with_first_scan = false;
145 static gboolean is_wifi_notifier_registered = false;
149 static GList *iface_list = NULL;
151 static GList *pending_wifi_device = NULL;
152 static GList *p2p_iface_list = NULL;
153 bool wfd_service_registered = false;
155 static void start_autoscan(struct connman_device *device);
157 static int p2p_tech_probe(struct connman_technology *technology)
159 p2p_technology = technology;
164 static void p2p_tech_remove(struct connman_technology *technology)
166 p2p_technology = NULL;
169 static struct connman_technology_driver p2p_tech_driver = {
171 .type = CONNMAN_SERVICE_TYPE_P2P,
172 .probe = p2p_tech_probe,
173 .remove = p2p_tech_remove,
176 static bool is_p2p_connecting(void)
180 for (list = iface_list; list; list = list->next) {
181 struct wifi_data *wifi = list->data;
183 if (wifi->p2p_connecting)
190 static void add_pending_wifi_device(struct wifi_data *wifi)
192 if (g_list_find(pending_wifi_device, wifi))
195 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
198 static struct wifi_data *get_pending_wifi_data(const char *ifname)
202 for (list = pending_wifi_device; list; list = list->next) {
203 struct wifi_data *wifi;
204 const char *dev_name;
207 if (!wifi || !wifi->device)
210 dev_name = connman_device_get_string(wifi->device, "Interface");
211 if (!g_strcmp0(ifname, dev_name)) {
212 pending_wifi_device = g_list_delete_link(
213 pending_wifi_device, list);
221 static void remove_pending_wifi_device(struct wifi_data *wifi)
225 link = g_list_find(pending_wifi_device, wifi);
230 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
233 static void peer_cancel_timeout(struct wifi_data *wifi)
235 if (wifi->p2p_connection_timeout > 0)
236 g_source_remove(wifi->p2p_connection_timeout);
238 wifi->p2p_connection_timeout = 0;
239 wifi->p2p_connecting = false;
241 if (wifi->pending_peer) {
242 connman_peer_unref(wifi->pending_peer);
243 wifi->pending_peer = NULL;
249 static gboolean peer_connect_timeout(gpointer data)
251 struct wifi_data *wifi = data;
255 if (wifi->p2p_connecting) {
256 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
258 if (g_supplicant_peer_has_requested_connection(wifi->peer))
259 state = CONNMAN_PEER_STATE_IDLE;
261 connman_peer_set_state(wifi->pending_peer, state);
264 peer_cancel_timeout(wifi);
269 static void peer_connect_callback(int result, GSupplicantInterface *interface,
272 struct wifi_data *wifi = user_data;
273 struct connman_peer *peer = wifi->pending_peer;
275 DBG("peer %p - %d", peer, result);
281 peer_connect_timeout(wifi);
285 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
287 wifi->p2p_connection_timeout = g_timeout_add_seconds(
288 P2P_CONNECTION_TIMEOUT,
289 peer_connect_timeout, wifi);
292 static int peer_connect(struct connman_peer *peer,
293 enum connman_peer_wps_method wps_method,
296 struct connman_device *device = connman_peer_get_device(peer);
297 GSupplicantPeerParams *peer_params;
298 GSupplicantPeer *gs_peer;
299 struct wifi_data *wifi;
303 DBG("peer %p", peer);
308 wifi = connman_device_get_data(device);
312 if (wifi->p2p_connecting)
317 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
318 connman_peer_get_identifier(peer));
322 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
323 pin = g_supplicant_peer_is_wps_pin(gs_peer);
325 switch (wps_method) {
326 case CONNMAN_PEER_WPS_UNKNOWN:
327 if ((pbc && pin) || pin)
330 case CONNMAN_PEER_WPS_PBC:
335 case CONNMAN_PEER_WPS_PIN:
336 if (!pin || !wps_pin)
341 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
345 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
347 peer_params->wps_pin = g_strdup(wps_pin);
349 peer_params->master = connman_peer_service_is_master();
351 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
352 peer_connect_callback, wifi);
353 if (ret == -EINPROGRESS) {
354 wifi->pending_peer = connman_peer_ref(peer);
355 wifi->peer = gs_peer;
356 wifi->p2p_connecting = true;
363 static int peer_disconnect(struct connman_peer *peer)
365 struct connman_device *device = connman_peer_get_device(peer);
366 GSupplicantPeerParams peer_params = {};
367 GSupplicantPeer *gs_peer;
368 struct wifi_data *wifi;
371 DBG("peer %p", peer);
376 wifi = connman_device_get_data(device);
380 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
381 connman_peer_get_identifier(peer));
385 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
387 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
389 g_free(peer_params.path);
391 if (ret == -EINPROGRESS)
392 peer_cancel_timeout(wifi);
397 struct peer_service_registration {
398 peer_service_registration_cb_t callback;
402 static bool is_service_wfd(const unsigned char *specs, int length)
404 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
410 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
412 struct wifi_data *wifi = data;
414 if (!wifi->interface ||
415 !g_supplicant_interface_has_p2p(wifi->interface))
418 if (!wifi->servicing) {
419 g_supplicant_interface_p2p_listen(wifi->interface,
420 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
426 static void register_wfd_service_cb(int result,
427 GSupplicantInterface *iface, void *user_data)
429 struct peer_service_registration *reg_data = user_data;
434 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
436 if (reg_data && reg_data->callback) {
437 reg_data->callback(result, reg_data->user_data);
442 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
443 const unsigned char *spec,
444 int spec_length, const unsigned char *query,
445 int query_length, int version)
447 GSupplicantP2PServiceParams *params;
449 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
454 params->version = version;
455 params->service = g_memdup(spec, spec_length);
456 } else if (query_length > 0 && spec_length > 0) {
457 params->query = g_memdup(query, query_length);
458 params->query_length = query_length;
460 params->response = g_memdup(spec, spec_length);
461 params->response_length = spec_length;
463 params->wfd_ies = g_memdup(spec, spec_length);
464 params->wfd_ies_length = spec_length;
470 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
475 g_free(params->service);
476 g_free(params->query);
477 g_free(params->response);
478 g_free(params->wfd_ies);
483 static int peer_register_wfd_service(const unsigned char *specification,
484 int specification_length,
485 peer_service_registration_cb_t callback,
488 struct peer_service_registration *reg_data = NULL;
489 static GSupplicantP2PServiceParams *params;
494 if (wfd_service_registered)
497 params = fill_in_peer_service_params(specification,
498 specification_length, NULL, 0, 0);
502 reg_data = g_try_malloc0(sizeof(*reg_data));
508 reg_data->callback = callback;
509 reg_data->user_data = user_data;
511 ret = g_supplicant_set_widi_ies(params,
512 register_wfd_service_cb, reg_data);
513 if (ret < 0 && ret != -EINPROGRESS)
516 wfd_service_registered = true;
520 free_peer_service_params(params);
526 static void register_peer_service_cb(int result,
527 GSupplicantInterface *iface, void *user_data)
529 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
530 struct peer_service_registration *reg_data = user_data;
535 apply_p2p_listen_on_iface(wifi, NULL);
537 if (reg_data->callback)
538 reg_data->callback(result, reg_data->user_data);
543 static int peer_register_service(const unsigned char *specification,
544 int specification_length,
545 const unsigned char *query,
546 int query_length, int version,
547 peer_service_registration_cb_t callback,
550 struct peer_service_registration *reg_data;
551 GSupplicantP2PServiceParams *params;
558 if (specification && !version && !query &&
559 is_service_wfd(specification, specification_length)) {
560 return peer_register_wfd_service(specification,
561 specification_length, callback, user_data);
564 reg_data = g_try_malloc0(sizeof(*reg_data));
568 reg_data->callback = callback;
569 reg_data->user_data = user_data;
573 for (list = iface_list; list; list = list->next) {
574 struct wifi_data *wifi = list->data;
575 GSupplicantInterface *iface = wifi->interface;
577 if (!g_supplicant_interface_has_p2p(iface))
580 params = fill_in_peer_service_params(specification,
581 specification_length, query,
582 query_length, version);
589 ret_f = g_supplicant_interface_p2p_add_service(iface,
590 register_peer_service_cb, params, reg_data);
591 if (ret_f == 0 || ret_f == -EINPROGRESS)
595 ret = g_supplicant_interface_p2p_add_service(iface,
596 register_peer_service_cb, params, NULL);
597 if (ret != 0 && ret != -EINPROGRESS)
598 free_peer_service_params(params);
601 if (ret_f != 0 && ret_f != -EINPROGRESS)
607 static int peer_unregister_wfd_service(void)
609 GSupplicantP2PServiceParams *params;
612 if (!wfd_service_registered)
615 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
619 wfd_service_registered = false;
621 g_supplicant_set_widi_ies(params, NULL, NULL);
623 for (list = iface_list; list; list = list->next) {
624 struct wifi_data *wifi = list->data;
626 if (!g_supplicant_interface_has_p2p(wifi->interface))
630 if (!wifi->servicing || wifi->servicing < 0) {
631 g_supplicant_interface_p2p_listen(wifi->interface,
640 static int peer_unregister_service(const unsigned char *specification,
641 int specification_length,
642 const unsigned char *query,
643 int query_length, int version)
645 GSupplicantP2PServiceParams *params;
650 if (specification && !version && !query &&
651 is_service_wfd(specification, specification_length)) {
652 ret = peer_unregister_wfd_service();
653 if (ret != 0 && ret != -EINPROGRESS)
658 for (list = iface_list; list; list = list->next) {
659 struct wifi_data *wifi = list->data;
660 GSupplicantInterface *iface = wifi->interface;
665 if (!g_supplicant_interface_has_p2p(iface))
668 params = fill_in_peer_service_params(specification,
669 specification_length, query,
670 query_length, version);
676 ret = g_supplicant_interface_p2p_del_service(iface, params);
677 if (ret != 0 && ret != -EINPROGRESS)
678 free_peer_service_params(params);
681 if (!wifi->servicing || wifi->servicing < 0) {
682 g_supplicant_interface_p2p_listen(iface, 0, 0);
690 static struct connman_peer_driver peer_driver = {
691 .connect = peer_connect,
692 .disconnect = peer_disconnect,
693 .register_service = peer_register_service,
694 .unregister_service = peer_unregister_service,
697 static void handle_tethering(struct wifi_data *wifi)
699 if (!wifi->tethering)
708 DBG("index %d bridge %s", wifi->index, wifi->bridge);
710 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
713 wifi->bridged = true;
716 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
718 struct connman_device *device = user_data;
719 struct wifi_data *wifi = connman_device_get_data(device);
724 DBG("index %d flags %d change %d", wifi->index, flags, change);
726 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
730 DBG("interface down");
733 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
734 if (flags & IFF_LOWER_UP) {
737 handle_tethering(wifi);
745 static int wifi_probe(struct connman_device *device)
747 struct wifi_data *wifi;
749 DBG("device %p", device);
751 wifi = g_try_new0(struct wifi_data, 1);
755 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
757 connman_device_set_data(device, wifi);
758 wifi->device = connman_device_ref(device);
760 wifi->index = connman_device_get_index(device);
763 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
764 wifi_newlink, device);
765 if (is_p2p_connecting())
766 add_pending_wifi_device(wifi);
768 iface_list = g_list_append(iface_list, wifi);
773 static void remove_networks(struct connman_device *device,
774 struct wifi_data *wifi)
778 for (list = wifi->networks; list; list = list->next) {
779 struct connman_network *network = list->data;
781 connman_device_remove_network(device, network);
782 connman_network_unref(network);
785 g_slist_free(wifi->networks);
786 wifi->networks = NULL;
789 static void reset_autoscan(struct connman_device *device)
791 struct wifi_data *wifi = connman_device_get_data(device);
792 struct autoscan_params *autoscan;
796 if (!wifi || !wifi->autoscan)
799 autoscan = wifi->autoscan;
801 if (autoscan->timeout == 0 && autoscan->interval == 0)
804 g_source_remove(autoscan->timeout);
806 autoscan->timeout = 0;
807 autoscan->interval = 0;
809 connman_device_unref(device);
812 static void stop_autoscan(struct connman_device *device)
814 const struct wifi_data *wifi = connman_device_get_data(device);
816 if (!wifi || !wifi->autoscan)
819 reset_autoscan(device);
821 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
824 static void check_p2p_technology(void)
826 bool p2p_exists = false;
829 for (list = iface_list; list; list = list->next) {
830 struct wifi_data *w = list->data;
833 g_supplicant_interface_has_p2p(w->interface))
838 connman_technology_driver_unregister(&p2p_tech_driver);
839 connman_peer_driver_unregister(&peer_driver);
843 static void wifi_remove(struct connman_device *device)
845 struct wifi_data *wifi = connman_device_get_data(device);
847 DBG("device %p wifi %p", device, wifi);
852 stop_autoscan(device);
854 if (wifi->p2p_device)
855 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
857 iface_list = g_list_remove(iface_list, wifi);
859 check_p2p_technology();
861 remove_pending_wifi_device(wifi);
863 if (wifi->p2p_find_timeout) {
864 g_source_remove(wifi->p2p_find_timeout);
865 connman_device_unref(wifi->device);
868 if (wifi->p2p_connection_timeout)
869 g_source_remove(wifi->p2p_connection_timeout);
871 remove_networks(device, wifi);
873 connman_device_set_powered(device, false);
874 connman_device_set_data(device, NULL);
875 connman_device_unref(wifi->device);
876 connman_rtnl_remove_watch(wifi->watch);
878 g_supplicant_interface_set_data(wifi->interface, NULL);
880 g_supplicant_interface_cancel(wifi->interface);
882 if (wifi->scan_params)
883 g_supplicant_free_scan_params(wifi->scan_params);
885 g_free(wifi->autoscan);
886 g_free(wifi->identifier);
890 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
894 for (iter = list; iter; iter = g_slist_next(iter)) {
895 struct scan_ssid *scan_ssid = iter->data;
897 if (ssid_len == scan_ssid->ssid_len &&
898 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
905 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
906 int freq, GSupplicantScanParams *scan_data,
907 int driver_max_scan_ssids, char *ssid_name)
910 struct scan_ssid *scan_ssid;
912 if ((driver_max_scan_ssids == 0 ||
913 driver_max_scan_ssids > scan_data->num_ssids) &&
914 (hex_ssid || raw_ssid)) {
916 unsigned int j = 0, hex;
919 size_t hex_ssid_len = strlen(hex_ssid);
921 ssid = g_try_malloc0(hex_ssid_len / 2);
925 for (i = 0; i < hex_ssid_len; i += 2) {
926 sscanf(hex_ssid + i, "%02x", &hex);
935 * If we have already added hidden AP to the list,
936 * then do not do it again. This might happen if you have
937 * used or are using multiple wifi cards, so in that case
938 * you might have multiple service files for same AP.
940 if (is_duplicate(scan_data->ssids, ssid, j)) {
946 scan_ssid = g_try_new(struct scan_ssid, 1);
953 memcpy(scan_ssid->ssid, ssid, j);
954 scan_ssid->ssid_len = j;
955 scan_data->ssids = g_slist_prepend(scan_data->ssids,
958 scan_data->num_ssids++;
960 DBG("SSID %s added to scanned list of %d entries", ssid_name,
961 scan_data->num_ssids);
968 scan_data->ssids = g_slist_reverse(scan_data->ssids);
970 if (!scan_data->freqs) {
971 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
972 if (!scan_data->freqs) {
973 g_slist_free_full(scan_data->ssids, g_free);
977 scan_data->num_freqs = 1;
978 scan_data->freqs[0] = freq;
980 bool duplicate = false;
982 /* Don't add duplicate entries */
983 for (i = 0; i < scan_data->num_freqs; i++) {
984 if (scan_data->freqs[i] == freq) {
991 scan_data->num_freqs++;
992 scan_data->freqs = g_try_realloc(scan_data->freqs,
993 sizeof(uint16_t) * scan_data->num_freqs);
994 if (!scan_data->freqs) {
995 g_slist_free_full(scan_data->ssids, g_free);
998 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1005 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1007 struct connman_config_entry **entries;
1013 int num_ssids = 0, add_param_failed = 0;
1015 services = connman_storage_get_services();
1016 for (i = 0; services && services[i]; i++) {
1017 if (strncmp(services[i], "wifi_", 5) != 0)
1020 keyfile = connman_storage_load_service(services[i]);
1024 value = g_key_file_get_boolean(keyfile,
1025 services[i], "Hidden", NULL);
1027 g_key_file_free(keyfile);
1031 value = g_key_file_get_boolean(keyfile,
1032 services[i], "Favorite", NULL);
1034 g_key_file_free(keyfile);
1038 #if defined TIZEN_EXT
1039 value = g_key_file_get_boolean(keyfile,
1040 services[i], "AutoConnect", NULL);
1042 g_key_file_free(keyfile);
1047 ssid = g_key_file_get_string(keyfile,
1048 services[i], "SSID", NULL);
1050 name = g_key_file_get_string(keyfile, services[i], "Name",
1053 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1061 g_key_file_free(keyfile);
1065 * Check if there are any hidden AP that needs to be provisioned.
1067 entries = connman_config_get_entries("wifi");
1068 for (i = 0; entries && entries[i]; i++) {
1071 if (!entries[i]->hidden)
1074 if (!entries[i]->ssid) {
1075 ssid = entries[i]->name;
1078 ssid = entries[i]->ssid;
1079 len = entries[i]->ssid_len;
1085 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1092 connman_config_free_entries(entries);
1094 if (add_param_failed > 0)
1095 DBG("Unable to scan %d out of %d SSIDs",
1096 add_param_failed, num_ssids);
1098 g_strfreev(services);
1103 static int get_hidden_connections_params(struct wifi_data *wifi,
1104 GSupplicantScanParams *scan_params)
1106 int driver_max_ssids, i;
1107 GSupplicantScanParams *orig_params;
1110 * Scan hidden networks so that we can autoconnect to them.
1111 * We will assume 1 as a default number of ssid to scan.
1113 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1115 if (driver_max_ssids == 0)
1116 driver_max_ssids = 1;
1118 DBG("max ssids %d", driver_max_ssids);
1120 if (!wifi->scan_params) {
1121 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1122 if (!wifi->scan_params)
1125 if (get_hidden_connections(wifi->scan_params) == 0) {
1126 g_supplicant_free_scan_params(wifi->scan_params);
1127 wifi->scan_params = NULL;
1133 orig_params = wifi->scan_params;
1135 /* Let's transfer driver_max_ssids params */
1136 for (i = 0; i < driver_max_ssids; i++) {
1137 struct scan_ssid *ssid;
1139 if (!wifi->scan_params->ssids)
1142 ssid = orig_params->ssids->data;
1143 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1144 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1148 scan_params->num_ssids = i;
1149 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1151 scan_params->freqs = g_memdup(orig_params->freqs,
1152 sizeof(uint16_t) * orig_params->num_freqs);
1153 if (!scan_params->freqs)
1156 scan_params->num_freqs = orig_params->num_freqs;
1161 orig_params->num_ssids -= scan_params->num_ssids;
1163 return scan_params->num_ssids;
1166 g_slist_free_full(scan_params->ssids, g_free);
1167 g_supplicant_free_scan_params(wifi->scan_params);
1168 wifi->scan_params = NULL;
1173 static int throw_wifi_scan(struct connman_device *device,
1174 GSupplicantInterfaceCallback callback)
1176 struct wifi_data *wifi = connman_device_get_data(device);
1182 DBG("device %p %p", device, wifi->interface);
1184 if (wifi->tethering)
1187 if (connman_device_get_scanning(device))
1190 connman_device_ref(device);
1192 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1195 connman_device_set_scanning(device,
1196 CONNMAN_SERVICE_TYPE_WIFI, true);
1198 connman_device_unref(device);
1203 static void hidden_free(struct hidden_params *hidden)
1208 if (hidden->scan_params)
1209 g_supplicant_free_scan_params(hidden->scan_params);
1210 g_free(hidden->identity);
1211 g_free(hidden->passphrase);
1212 g_free(hidden->security);
1216 #if defined TIZEN_EXT
1217 static void service_state_changed(struct connman_service *service,
1218 enum connman_service_state state);
1220 static int network_connect(struct connman_network *network);
1222 static struct connman_notifier notifier = {
1224 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1225 .service_state_changed = service_state_changed,
1228 static void service_state_changed(struct connman_service *service,
1229 enum connman_service_state state)
1231 enum connman_service_type type;
1233 type = connman_service_get_type(service);
1234 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1237 DBG("service %p state %d", service, state);
1240 case CONNMAN_SERVICE_STATE_READY:
1241 case CONNMAN_SERVICE_STATE_ONLINE:
1242 case CONNMAN_SERVICE_STATE_FAILURE:
1243 connman_notifier_unregister(¬ifier);
1244 is_wifi_notifier_registered = FALSE;
1246 __connman_device_request_scan(type);
1255 static void scan_callback(int result, GSupplicantInterface *interface,
1258 struct connman_device *device = user_data;
1259 struct wifi_data *wifi = connman_device_get_data(device);
1262 DBG("result %d wifi %p", result, wifi);
1265 if (wifi->hidden && !wifi->postpone_hidden) {
1266 connman_network_clear_hidden(wifi->hidden->user_data);
1267 hidden_free(wifi->hidden);
1268 wifi->hidden = NULL;
1271 if (wifi->scan_params) {
1272 g_supplicant_free_scan_params(wifi->scan_params);
1273 wifi->scan_params = NULL;
1278 connman_device_reset_scanning(device);
1280 /* User is connecting to a hidden AP, let's wait for finished event */
1281 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1282 GSupplicantScanParams *scan_params;
1285 wifi->postpone_hidden = false;
1286 scan_params = wifi->hidden->scan_params;
1287 wifi->hidden->scan_params = NULL;
1289 reset_autoscan(device);
1291 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1292 scan_callback, device);
1296 /* On error, let's recall scan_callback, which will cleanup */
1297 return scan_callback(ret, interface, user_data);
1300 scanning = connman_device_get_scanning(device);
1303 connman_device_set_scanning(device,
1304 CONNMAN_SERVICE_TYPE_WIFI, false);
1307 if (result != -ENOLINK)
1308 #if defined TIZEN_EXT
1311 start_autoscan(device);
1314 * If we are here then we were scanning; however, if we are
1315 * also mid-flight disabling the interface, then wifi_disable
1316 * has already cleared the device scanning state and
1317 * unreferenced the device, obviating the need to do it here.
1321 connman_device_unref(device);
1323 #if defined TIZEN_EXT
1324 if (wifi && wifi->allow_full_scan) {
1325 DBG("Trigger Full Channel Scan");
1326 throw_wifi_scan(device, scan_callback);
1327 wifi->allow_full_scan = FALSE;
1329 if (wifi && wifi->scan_pending_network && result != -EIO) {
1330 network_connect(wifi->scan_pending_network);
1331 wifi->scan_pending_network = NULL;
1332 connman_network_set_connecting(wifi->network);
1335 if (is_wifi_notifier_registered != true &&
1336 wifi_first_scan == true && found_with_first_scan == true) {
1337 wifi_first_scan = false;
1338 found_with_first_scan = false;
1340 connman_notifier_register(¬ifier);
1341 is_wifi_notifier_registered = true;
1346 static void scan_callback_hidden(int result,
1347 GSupplicantInterface *interface, void *user_data)
1349 struct connman_device *device = user_data;
1350 struct wifi_data *wifi = connman_device_get_data(device);
1351 GSupplicantScanParams *scan_params;
1354 DBG("result %d wifi %p", result, wifi);
1359 /* User is trying to connect to a hidden AP */
1360 if (wifi->hidden && wifi->postpone_hidden)
1363 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1367 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1368 ret = g_supplicant_interface_scan(wifi->interface,
1370 scan_callback_hidden,
1376 g_supplicant_free_scan_params(scan_params);
1379 scan_callback(result, interface, user_data);
1382 static gboolean autoscan_timeout(gpointer data)
1384 struct connman_device *device = data;
1385 struct wifi_data *wifi = connman_device_get_data(device);
1386 struct autoscan_params *autoscan;
1392 autoscan = wifi->autoscan;
1394 if (autoscan->interval <= 0) {
1395 interval = autoscan->base;
1398 interval = autoscan->interval * autoscan->base;
1400 #if defined TIZEN_EXT
1401 if (autoscan->interval >= autoscan->limit)
1403 if (interval > autoscan->limit)
1405 interval = autoscan->limit;
1407 throw_wifi_scan(wifi->device, scan_callback_hidden);
1410 DBG("interval %d", interval);
1412 autoscan->interval = interval;
1414 autoscan->timeout = g_timeout_add_seconds(interval,
1415 autoscan_timeout, device);
1420 static void start_autoscan(struct connman_device *device)
1422 struct wifi_data *wifi = connman_device_get_data(device);
1423 struct autoscan_params *autoscan;
1430 if (wifi->p2p_device)
1433 if (wifi->connected)
1436 autoscan = wifi->autoscan;
1440 if (autoscan->timeout > 0 || autoscan->interval > 0)
1443 connman_device_ref(device);
1445 autoscan_timeout(device);
1448 static struct autoscan_params *parse_autoscan_params(const char *params)
1450 struct autoscan_params *autoscan;
1455 DBG("Emulating autoscan");
1457 list_params = g_strsplit(params, ":", 0);
1458 if (list_params == 0)
1461 if (g_strv_length(list_params) < 3) {
1462 g_strfreev(list_params);
1466 base = atoi(list_params[1]);
1467 limit = atoi(list_params[2]);
1469 g_strfreev(list_params);
1471 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1473 DBG("Could not allocate memory for autoscan");
1477 DBG("base %d - limit %d", base, limit);
1478 autoscan->base = base;
1479 autoscan->limit = limit;
1484 static void setup_autoscan(struct wifi_data *wifi)
1486 if (!wifi->autoscan)
1487 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1489 start_autoscan(wifi->device);
1492 static void finalize_interface_creation(struct wifi_data *wifi)
1494 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1496 if (!wifi->device) {
1497 connman_error("WiFi device not set");
1501 connman_device_set_powered(wifi->device, true);
1503 if (!connman_setting_get_bool("BackgroundScanning"))
1506 if (wifi->p2p_device)
1509 setup_autoscan(wifi);
1512 static void interface_create_callback(int result,
1513 GSupplicantInterface *interface,
1516 struct wifi_data *wifi = user_data;
1518 DBG("result %d ifname %s, wifi %p", result,
1519 g_supplicant_interface_get_ifname(interface),
1522 if (result < 0 || !wifi)
1525 wifi->interface = interface;
1526 g_supplicant_interface_set_data(interface, wifi);
1528 if (g_supplicant_interface_get_ready(interface)) {
1529 wifi->interface_ready = true;
1530 finalize_interface_creation(wifi);
1534 static int wifi_enable(struct connman_device *device)
1536 struct wifi_data *wifi = connman_device_get_data(device);
1539 const char *driver = connman_option_get_string("wifi");
1542 DBG("device %p %p", device, wifi);
1544 index = connman_device_get_index(device);
1545 if (!wifi || index < 0)
1548 if (is_p2p_connecting())
1549 return -EINPROGRESS;
1551 interface = connman_inet_ifname(index);
1552 ret = g_supplicant_interface_create(interface, driver, NULL,
1553 interface_create_callback,
1560 return -EINPROGRESS;
1563 static int wifi_disable(struct connman_device *device)
1565 struct wifi_data *wifi = connman_device_get_data(device);
1568 DBG("device %p wifi %p", device, wifi);
1573 wifi->connected = false;
1574 wifi->disconnecting = false;
1576 if (wifi->pending_network)
1577 wifi->pending_network = NULL;
1579 stop_autoscan(device);
1581 if (wifi->p2p_find_timeout) {
1582 g_source_remove(wifi->p2p_find_timeout);
1583 wifi->p2p_find_timeout = 0;
1584 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1585 connman_device_unref(wifi->device);
1588 /* In case of a user scan, device is still referenced */
1589 if (connman_device_get_scanning(device)) {
1590 connman_device_set_scanning(device,
1591 CONNMAN_SERVICE_TYPE_WIFI, false);
1592 connman_device_unref(wifi->device);
1595 remove_networks(device, wifi);
1597 #if defined TIZEN_EXT
1598 wifi->scan_pending_network = NULL;
1600 if (is_wifi_notifier_registered == true) {
1601 connman_notifier_unregister(¬ifier);
1602 is_wifi_notifier_registered = false;
1606 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1610 return -EINPROGRESS;
1613 struct last_connected {
1619 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1621 GTimeVal *aval = (GTimeVal *)a;
1622 GTimeVal *bval = (GTimeVal *)b;
1624 /* Note that the sort order is descending */
1625 if (aval->tv_sec < bval->tv_sec)
1628 if (aval->tv_sec > bval->tv_sec)
1634 static void free_entry(gpointer data)
1636 struct last_connected *entry = data;
1638 g_free(entry->ssid);
1642 static int get_latest_connections(int max_ssids,
1643 GSupplicantScanParams *scan_data)
1645 GSequenceIter *iter;
1646 GSequence *latest_list;
1647 struct last_connected *entry;
1656 latest_list = g_sequence_new(free_entry);
1660 services = connman_storage_get_services();
1661 for (i = 0; services && services[i]; i++) {
1662 if (strncmp(services[i], "wifi_", 5) != 0)
1665 keyfile = connman_storage_load_service(services[i]);
1669 str = g_key_file_get_string(keyfile,
1670 services[i], "Favorite", NULL);
1671 if (!str || g_strcmp0(str, "true")) {
1673 g_key_file_free(keyfile);
1678 str = g_key_file_get_string(keyfile,
1679 services[i], "AutoConnect", NULL);
1680 if (!str || g_strcmp0(str, "true")) {
1682 g_key_file_free(keyfile);
1687 str = g_key_file_get_string(keyfile,
1688 services[i], "Modified", NULL);
1690 g_key_file_free(keyfile);
1693 g_time_val_from_iso8601(str, &modified);
1696 ssid = g_key_file_get_string(keyfile,
1697 services[i], "SSID", NULL);
1699 freq = g_key_file_get_integer(keyfile, services[i],
1702 entry = g_try_new(struct last_connected, 1);
1704 g_sequence_free(latest_list);
1705 g_key_file_free(keyfile);
1711 entry->modified = modified;
1714 g_sequence_insert_sorted(latest_list, entry,
1720 g_key_file_free(keyfile);
1723 g_strfreev(services);
1725 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1727 iter = g_sequence_get_begin_iter(latest_list);
1729 for (i = 0; i < num_ssids; i++) {
1730 entry = g_sequence_get(iter);
1732 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1733 entry->modified.tv_sec);
1735 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1736 max_ssids, entry->ssid);
1738 iter = g_sequence_iter_next(iter);
1741 g_sequence_free(latest_list);
1745 static int wifi_scan_simple(struct connman_device *device)
1747 reset_autoscan(device);
1749 return throw_wifi_scan(device, scan_callback_hidden);
1752 static gboolean p2p_find_stop(gpointer data)
1754 struct connman_device *device = data;
1755 struct wifi_data *wifi = connman_device_get_data(device);
1759 wifi->p2p_find_timeout = 0;
1761 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1763 g_supplicant_interface_p2p_stop_find(wifi->interface);
1765 connman_device_unref(device);
1766 reset_autoscan(device);
1771 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1774 struct connman_device *device = user_data;
1775 struct wifi_data *wifi = connman_device_get_data(device);
1777 DBG("result %d wifi %p", result, wifi);
1779 if (wifi->p2p_find_timeout) {
1780 g_source_remove(wifi->p2p_find_timeout);
1781 wifi->p2p_find_timeout = 0;
1787 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1788 p2p_find_stop, device);
1789 if (!wifi->p2p_find_timeout)
1794 p2p_find_stop(device);
1797 static int p2p_find(struct connman_device *device)
1799 struct wifi_data *wifi;
1804 if (!p2p_technology)
1807 wifi = connman_device_get_data(device);
1809 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1812 reset_autoscan(device);
1813 connman_device_ref(device);
1815 ret = g_supplicant_interface_p2p_find(wifi->interface,
1816 p2p_find_callback, device);
1818 connman_device_unref(device);
1819 start_autoscan(device);
1821 connman_device_set_scanning(device,
1822 CONNMAN_SERVICE_TYPE_P2P, true);
1829 * Note that the hidden scan is only used when connecting to this specific
1830 * hidden AP first time. It is not used when system autoconnects to hidden AP.
1832 static int wifi_scan(enum connman_service_type type,
1833 struct connman_device *device,
1834 const char *ssid, unsigned int ssid_len,
1835 const char *identity, const char* passphrase,
1836 const char *security, void *user_data)
1838 struct wifi_data *wifi = connman_device_get_data(device);
1839 GSupplicantScanParams *scan_params = NULL;
1840 struct scan_ssid *scan_ssid;
1841 struct hidden_params *hidden;
1843 int driver_max_ssids = 0;
1850 if (wifi->p2p_device)
1853 if (type == CONNMAN_SERVICE_TYPE_P2P)
1854 return p2p_find(device);
1856 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
1858 if (wifi->tethering)
1861 scanning = connman_device_get_scanning(device);
1863 if (!ssid || ssid_len == 0 || ssid_len > 32) {
1867 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1869 DBG("max ssids %d", driver_max_ssids);
1870 if (driver_max_ssids == 0)
1871 return wifi_scan_simple(device);
1875 if (scanning && wifi->hidden && wifi->postpone_hidden)
1881 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1886 scan_ssid = g_try_new(struct scan_ssid, 1);
1888 g_free(scan_params);
1892 memcpy(scan_ssid->ssid, ssid, ssid_len);
1893 scan_ssid->ssid_len = ssid_len;
1894 scan_params->ssids = g_slist_prepend(scan_params->ssids,
1896 scan_params->num_ssids = 1;
1898 hidden = g_try_new0(struct hidden_params, 1);
1900 g_supplicant_free_scan_params(scan_params);
1905 hidden_free(wifi->hidden);
1906 wifi->hidden = NULL;
1909 memcpy(hidden->ssid, ssid, ssid_len);
1910 hidden->ssid_len = ssid_len;
1911 hidden->identity = g_strdup(identity);
1912 hidden->passphrase = g_strdup(passphrase);
1913 hidden->security = g_strdup(security);
1914 hidden->user_data = user_data;
1915 wifi->hidden = hidden;
1918 /* Let's keep this active scan for later,
1919 * when current scan will be over. */
1920 wifi->postpone_hidden = TRUE;
1921 hidden->scan_params = scan_params;
1925 } else if (wifi->connected) {
1926 g_supplicant_free_scan_params(scan_params);
1927 return wifi_scan_simple(device);
1929 ret = get_latest_connections(driver_max_ssids, scan_params);
1931 g_supplicant_free_scan_params(scan_params);
1932 return wifi_scan_simple(device);
1936 connman_device_ref(device);
1938 #if defined TIZEN_EXT
1939 /*To allow the Full Scan after ssid based scan, set the flag here
1940 It is required because Tizen does not use the ConnMan specific
1941 backgroung Scan feature.Tizen has added the BG Scan feature in net-config
1942 To sync with up ConnMan, we need to issue the Full Scan after SSID specific scan.*/
1943 wifi->allow_full_scan = TRUE;
1945 reset_autoscan(device);
1947 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1948 scan_callback, device);
1951 connman_device_set_scanning(device,
1952 CONNMAN_SERVICE_TYPE_WIFI, true);
1954 g_supplicant_free_scan_params(scan_params);
1955 connman_device_unref(device);
1958 hidden_free(wifi->hidden);
1959 wifi->hidden = NULL;
1966 static void wifi_regdom_callback(int result,
1970 struct connman_device *device = user_data;
1972 connman_device_regdom_notify(device, result, alpha2);
1974 connman_device_unref(device);
1977 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
1979 struct wifi_data *wifi = connman_device_get_data(device);
1985 connman_device_ref(device);
1987 ret = g_supplicant_interface_set_country(wifi->interface,
1988 wifi_regdom_callback,
1991 connman_device_unref(device);
1996 static struct connman_device_driver wifi_ng_driver = {
1998 .type = CONNMAN_DEVICE_TYPE_WIFI,
1999 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2000 .probe = wifi_probe,
2001 .remove = wifi_remove,
2002 .enable = wifi_enable,
2003 .disable = wifi_disable,
2005 .set_regdom = wifi_set_regdom,
2008 static void system_ready(void)
2012 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2013 connman_error("Failed to register WiFi driver");
2016 static void system_killed(void)
2020 connman_device_driver_unregister(&wifi_ng_driver);
2023 static int network_probe(struct connman_network *network)
2025 DBG("network %p", network);
2030 static void network_remove(struct connman_network *network)
2032 struct connman_device *device = connman_network_get_device(network);
2033 struct wifi_data *wifi;
2035 DBG("network %p", network);
2037 wifi = connman_device_get_data(device);
2041 if (wifi->network != network)
2044 wifi->network = NULL;
2046 #if defined TIZEN_EXT
2047 wifi->disconnecting = false;
2049 if (wifi->pending_network == network)
2050 wifi->pending_network = NULL;
2052 if (wifi->scan_pending_network == network)
2053 wifi->scan_pending_network = NULL;
2057 static void connect_callback(int result, GSupplicantInterface *interface,
2060 #if defined TIZEN_EXT
2062 struct wifi_data *wifi;
2064 struct connman_network *network = user_data;
2066 DBG("network %p result %d", network, result);
2068 #if defined TIZEN_EXT
2069 for (list = iface_list; list; list = list->next) {
2072 if (wifi && wifi->network == network)
2076 /* wifi_data may be invalid because wifi is already disabled */
2081 if (result == -ENOKEY) {
2082 connman_network_set_error(network,
2083 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2084 } else if (result < 0) {
2085 connman_network_set_error(network,
2086 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2089 connman_network_unref(network);
2092 static GSupplicantSecurity network_security(const char *security)
2094 if (g_str_equal(security, "none"))
2095 return G_SUPPLICANT_SECURITY_NONE;
2096 else if (g_str_equal(security, "wep"))
2097 return G_SUPPLICANT_SECURITY_WEP;
2098 else if (g_str_equal(security, "psk"))
2099 return G_SUPPLICANT_SECURITY_PSK;
2100 else if (g_str_equal(security, "wpa"))
2101 return G_SUPPLICANT_SECURITY_PSK;
2102 else if (g_str_equal(security, "rsn"))
2103 return G_SUPPLICANT_SECURITY_PSK;
2104 else if (g_str_equal(security, "ieee8021x"))
2105 return G_SUPPLICANT_SECURITY_IEEE8021X;
2106 #if defined TIZEN_EXT
2107 else if (g_str_equal(security, "ft_psk") == TRUE)
2108 return G_SUPPLICANT_SECURITY_FT_PSK;
2109 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2110 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2113 return G_SUPPLICANT_SECURITY_UNKNOWN;
2116 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2118 const char *security;
2120 memset(ssid, 0, sizeof(*ssid));
2121 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2122 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2124 ssid->scan_ssid = 1;
2125 security = connman_network_get_string(network, "WiFi.Security");
2126 ssid->security = network_security(security);
2127 ssid->passphrase = connman_network_get_string(network,
2130 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2133 * If our private key password is unset,
2134 * we use the supplied passphrase. That is needed
2135 * for PEAP where 2 passphrases (identity and client
2136 * cert may have to be provided.
2138 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2139 connman_network_set_string(network,
2140 "WiFi.PrivateKeyPassphrase",
2142 /* We must have an identity for both PEAP and TLS */
2143 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2145 /* Use agent provided identity as a fallback */
2146 if (!ssid->identity || strlen(ssid->identity) == 0)
2147 ssid->identity = connman_network_get_string(network,
2148 "WiFi.AgentIdentity");
2150 ssid->ca_cert_path = connman_network_get_string(network,
2152 ssid->client_cert_path = connman_network_get_string(network,
2153 "WiFi.ClientCertFile");
2154 ssid->private_key_path = connman_network_get_string(network,
2155 "WiFi.PrivateKeyFile");
2156 ssid->private_key_passphrase = connman_network_get_string(network,
2157 "WiFi.PrivateKeyPassphrase");
2158 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2160 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2161 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2163 #if defined TIZEN_EXT
2164 ssid->bssid = connman_network_get_bssid(network);
2167 if (connman_setting_get_bool("BackgroundScanning"))
2168 ssid->bgscan = BGSCAN_DEFAULT;
2171 static int network_connect(struct connman_network *network)
2173 struct connman_device *device = connman_network_get_device(network);
2174 struct wifi_data *wifi;
2175 GSupplicantInterface *interface;
2176 GSupplicantSSID *ssid;
2178 DBG("network %p", network);
2183 wifi = connman_device_get_data(device);
2187 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2191 interface = wifi->interface;
2193 ssid_init(ssid, network);
2195 if (wifi->disconnecting) {
2196 wifi->pending_network = network;
2199 wifi->network = connman_network_ref(network);
2201 #if defined TIZEN_EXT
2202 wifi->scan_pending_network = NULL;
2205 return g_supplicant_interface_connect(interface, ssid,
2206 connect_callback, network);
2209 return -EINPROGRESS;
2212 static void disconnect_callback(int result, GSupplicantInterface *interface,
2215 #if defined TIZEN_EXT
2217 struct wifi_data *wifi;
2218 struct connman_network *network = user_data;
2220 DBG("network %p result %d", network, result);
2222 for (list = iface_list; list; list = list->next) {
2225 if (wifi->network == NULL && wifi->disconnecting == true)
2226 wifi->disconnecting = false;
2228 if (wifi->network == network)
2232 /* wifi_data may be invalid because wifi is already disabled */
2237 struct wifi_data *wifi = user_data;
2240 DBG("result %d supplicant interface %p wifi %p",
2241 result, interface, wifi);
2243 if (result == -ECONNABORTED) {
2244 DBG("wifi interface no longer available");
2248 if (wifi->network) {
2250 * if result < 0 supplican return an error because
2251 * the network is not current.
2252 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2253 * failed, call connman_network_set_connected to report
2254 * disconnect is completed.
2257 connman_network_set_connected(wifi->network, false);
2260 wifi->network = NULL;
2262 wifi->disconnecting = false;
2264 if (wifi->pending_network) {
2265 network_connect(wifi->pending_network);
2266 wifi->pending_network = NULL;
2269 start_autoscan(wifi->device);
2272 static int network_disconnect(struct connman_network *network)
2274 struct connman_device *device = connman_network_get_device(network);
2275 struct wifi_data *wifi;
2277 #if defined TIZEN_EXT
2278 struct connman_service *service;
2281 DBG("network %p", network);
2283 wifi = connman_device_get_data(device);
2284 if (!wifi || !wifi->interface)
2287 #if defined TIZEN_EXT
2288 if (connman_network_get_associating(network) == true) {
2289 connman_network_clear_associating(network);
2290 connman_network_set_bool(network, "WiFi.UseWPS", false);
2292 service = connman_service_lookup_from_network(network);
2294 if (service != NULL &&
2295 (__connman_service_is_connected_state(service,
2296 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2297 __connman_service_is_connected_state(service,
2298 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2299 (connman_service_get_favorite(service) == false))
2300 __connman_service_set_passphrase(service, NULL);
2303 if (wifi->pending_network == network)
2304 wifi->pending_network = NULL;
2306 if (wifi->scan_pending_network == network)
2307 wifi->scan_pending_network = NULL;
2310 connman_network_set_associating(network, false);
2312 if (wifi->disconnecting)
2315 wifi->disconnecting = true;
2317 #if defined TIZEN_EXT
2318 err = g_supplicant_interface_disconnect(wifi->interface,
2319 disconnect_callback, network);
2321 err = g_supplicant_interface_disconnect(wifi->interface,
2322 disconnect_callback, wifi);
2326 wifi->disconnecting = false;
2331 static struct connman_network_driver network_driver = {
2333 .type = CONNMAN_NETWORK_TYPE_WIFI,
2334 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2335 .probe = network_probe,
2336 .remove = network_remove,
2337 .connect = network_connect,
2338 .disconnect = network_disconnect,
2341 static void interface_added(GSupplicantInterface *interface)
2343 const char *ifname = g_supplicant_interface_get_ifname(interface);
2344 const char *driver = g_supplicant_interface_get_driver(interface);
2345 struct wifi_data *wifi;
2347 wifi = g_supplicant_interface_get_data(interface);
2349 wifi = get_pending_wifi_data(ifname);
2353 g_supplicant_interface_set_data(interface, wifi);
2354 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2355 wifi->p2p_device = true;
2358 DBG("ifname %s driver %s wifi %p tethering %d",
2359 ifname, driver, wifi, wifi->tethering);
2361 if (!wifi->device) {
2362 connman_error("WiFi device not set");
2366 connman_device_set_powered(wifi->device, true);
2369 static bool is_idle(struct wifi_data *wifi)
2371 DBG("state %d", wifi->state);
2373 switch (wifi->state) {
2374 case G_SUPPLICANT_STATE_UNKNOWN:
2375 case G_SUPPLICANT_STATE_DISABLED:
2376 case G_SUPPLICANT_STATE_DISCONNECTED:
2377 case G_SUPPLICANT_STATE_INACTIVE:
2378 case G_SUPPLICANT_STATE_SCANNING:
2381 case G_SUPPLICANT_STATE_AUTHENTICATING:
2382 case G_SUPPLICANT_STATE_ASSOCIATING:
2383 case G_SUPPLICANT_STATE_ASSOCIATED:
2384 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2385 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2386 case G_SUPPLICANT_STATE_COMPLETED:
2393 static bool is_idle_wps(GSupplicantInterface *interface,
2394 struct wifi_data *wifi)
2396 /* First, let's check if WPS processing did not went wrong */
2397 if (g_supplicant_interface_get_wps_state(interface) ==
2398 G_SUPPLICANT_WPS_STATE_FAIL)
2401 /* Unlike normal connection, being associated while processing wps
2402 * actually means that we are idling. */
2403 switch (wifi->state) {
2404 case G_SUPPLICANT_STATE_UNKNOWN:
2405 case G_SUPPLICANT_STATE_DISABLED:
2406 case G_SUPPLICANT_STATE_DISCONNECTED:
2407 case G_SUPPLICANT_STATE_INACTIVE:
2408 case G_SUPPLICANT_STATE_SCANNING:
2409 case G_SUPPLICANT_STATE_ASSOCIATED:
2411 case G_SUPPLICANT_STATE_AUTHENTICATING:
2412 case G_SUPPLICANT_STATE_ASSOCIATING:
2413 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2414 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2415 case G_SUPPLICANT_STATE_COMPLETED:
2422 static bool handle_wps_completion(GSupplicantInterface *interface,
2423 struct connman_network *network,
2424 struct connman_device *device,
2425 struct wifi_data *wifi)
2429 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2431 const unsigned char *ssid, *wps_ssid;
2432 unsigned int ssid_len, wps_ssid_len;
2433 const char *wps_key;
2435 /* Checking if we got associated with requested
2437 ssid = connman_network_get_blob(network, "WiFi.SSID",
2440 wps_ssid = g_supplicant_interface_get_wps_ssid(
2441 interface, &wps_ssid_len);
2443 if (!wps_ssid || wps_ssid_len != ssid_len ||
2444 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2445 connman_network_set_associating(network, false);
2446 #if defined TIZEN_EXT
2447 g_supplicant_interface_disconnect(wifi->interface,
2448 disconnect_callback, wifi->network);
2450 connman_network_set_bool(network, "WiFi.UseWPS", false);
2451 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2453 g_supplicant_interface_disconnect(wifi->interface,
2454 disconnect_callback, wifi);
2459 wps_key = g_supplicant_interface_get_wps_key(interface);
2460 connman_network_set_string(network, "WiFi.Passphrase",
2463 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2469 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2470 struct connman_network *network,
2471 struct wifi_data *wifi)
2473 #if defined TIZEN_EXT
2474 const char *security;
2475 struct connman_service *service;
2477 if (wifi->connected)
2480 security = connman_network_get_string(network, "WiFi.Security");
2482 if (g_str_equal(security, "ieee8021x") == true &&
2483 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2485 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2490 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2493 struct connman_service *service;
2495 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2498 if (wifi->connected)
2502 service = connman_service_lookup_from_network(network);
2508 if (connman_service_get_favorite(service)) {
2509 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2514 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2519 #if defined TIZEN_EXT
2520 static bool handle_wifi_assoc_retry(struct connman_network *network,
2521 struct wifi_data *wifi)
2523 const char *security;
2525 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2526 connman_network_get_connecting(network) != true) {
2527 wifi->assoc_retry_count = 0;
2531 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2532 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2533 wifi->assoc_retry_count = 0;
2537 security = connman_network_get_string(network, "WiFi.Security");
2538 if (g_str_equal(security, "ieee8021x") == true &&
2539 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2540 wifi->assoc_retry_count = 0;
2544 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2545 wifi->assoc_retry_count = 0;
2547 /* Honestly it's not an invalid-key error,
2548 * however QA team recommends that the invalid-key error
2549 * might be better to display for user experience.
2551 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2560 static void interface_state(GSupplicantInterface *interface)
2562 struct connman_network *network;
2563 struct connman_device *device;
2564 struct wifi_data *wifi;
2565 GSupplicantState state = g_supplicant_interface_get_state(interface);
2568 wifi = g_supplicant_interface_get_data(interface);
2570 DBG("wifi %p interface state %d", wifi, state);
2575 device = wifi->device;
2579 if (g_supplicant_interface_get_ready(interface) &&
2580 !wifi->interface_ready) {
2581 wifi->interface_ready = true;
2582 finalize_interface_creation(wifi);
2585 network = wifi->network;
2590 case G_SUPPLICANT_STATE_SCANNING:
2593 case G_SUPPLICANT_STATE_AUTHENTICATING:
2594 case G_SUPPLICANT_STATE_ASSOCIATING:
2595 #if defined TIZEN_EXT
2596 reset_autoscan(device);
2598 stop_autoscan(device);
2601 if (!wifi->connected)
2602 connman_network_set_associating(network, true);
2606 case G_SUPPLICANT_STATE_COMPLETED:
2607 #if defined TIZEN_EXT
2608 /* though it should be already reset: */
2609 reset_autoscan(device);
2611 wifi->assoc_retry_count = 0;
2613 wifi->scan_pending_network = NULL;
2615 /* though it should be already stopped: */
2616 stop_autoscan(device);
2619 if (!handle_wps_completion(interface, network, device, wifi))
2622 connman_network_set_connected(network, true);
2625 case G_SUPPLICANT_STATE_DISCONNECTED:
2627 * If we're in one of the idle modes, we have
2628 * not started association yet and thus setting
2629 * those ones to FALSE could cancel an association
2632 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2634 if (is_idle_wps(interface, wifi))
2640 /* If previous state was 4way-handshake, then
2641 * it's either: psk was incorrect and thus we retry
2642 * or if we reach the maximum retries we declare the
2644 if (handle_4way_handshake_failure(interface,
2648 /* We disable the selected network, if not then
2649 * wpa_supplicant will loop retrying */
2650 if (g_supplicant_interface_enable_selected_network(interface,
2652 DBG("Could not disables selected network");
2654 #if defined TIZEN_EXT
2656 int reason_code = 0;
2658 err = g_supplicant_interface_remove_network(wifi->interface);
2660 DBG("Failed to remove network(%d)", err);
2662 reason_code = g_supplicant_interface_get_disconnect_reason(wifi->interface);
2664 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2665 * Retry association until its retry count is expired */
2666 if (handle_wifi_assoc_retry(network, wifi) == true) {
2667 throw_wifi_scan(wifi->device, scan_callback);
2668 wifi->scan_pending_network = wifi->network;
2672 if(reason_code > 0){
2673 DBG("Set disconnect reason code(%d)", reason_code);
2674 connman_network_set_disconnect_reason(network, reason_code);
2677 /* To avoid unnecessary repeated association in wpa_supplicant,
2678 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2679 if (wps != true && wifi->network && wifi->disconnecting == false) {
2680 wifi->disconnecting = true;
2681 err = g_supplicant_interface_disconnect(wifi->interface,
2682 disconnect_callback, wifi->network);
2684 wifi->disconnecting = false;
2686 connman_network_set_connected(network, false);
2687 connman_network_set_associating(network, false);
2689 start_autoscan(device);
2695 connman_network_set_connected(network, false);
2696 connman_network_set_associating(network, false);
2697 wifi->disconnecting = false;
2699 start_autoscan(device);
2703 case G_SUPPLICANT_STATE_INACTIVE:
2704 #if defined TIZEN_EXT
2705 if (handle_wps_completion(interface, network, device, wifi) == false)
2708 connman_network_set_associating(network, false);
2709 start_autoscan(device);
2713 case G_SUPPLICANT_STATE_UNKNOWN:
2714 case G_SUPPLICANT_STATE_DISABLED:
2715 case G_SUPPLICANT_STATE_ASSOCIATED:
2716 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2717 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2721 wifi->state = state;
2723 /* Saving wpa_s state policy:
2724 * If connected and if the state changes are roaming related:
2725 * --> We stay connected
2727 * --> We are connected
2729 * --> We are not connected
2732 #if defined TIZEN_EXT
2733 case G_SUPPLICANT_STATE_SCANNING:
2736 case G_SUPPLICANT_STATE_AUTHENTICATING:
2737 case G_SUPPLICANT_STATE_ASSOCIATING:
2738 case G_SUPPLICANT_STATE_ASSOCIATED:
2739 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2740 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2741 if (wifi->connected)
2742 connman_warn("Probably roaming right now!"
2743 " Staying connected...");
2745 wifi->connected = false;
2747 case G_SUPPLICANT_STATE_COMPLETED:
2748 wifi->connected = true;
2751 wifi->connected = false;
2758 static void interface_removed(GSupplicantInterface *interface)
2760 const char *ifname = g_supplicant_interface_get_ifname(interface);
2761 struct wifi_data *wifi;
2763 DBG("ifname %s", ifname);
2765 wifi = g_supplicant_interface_get_data(interface);
2768 wifi->interface = NULL;
2770 if (wifi && wifi->tethering)
2773 if (!wifi || !wifi->device) {
2774 DBG("wifi interface already removed");
2778 connman_device_set_powered(wifi->device, false);
2780 check_p2p_technology();
2783 static void set_device_type(const char *type, char dev_type[17])
2785 const char *oui = "0050F204";
2786 const char *category = "0100";
2787 const char *sub_category = "0000";
2789 if (!g_strcmp0(type, "handset")) {
2791 sub_category = "0500";
2792 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2793 sub_category = "0100";
2794 else if (!g_strcmp0(type, "server"))
2795 sub_category = "0200";
2796 else if (!g_strcmp0(type, "laptop"))
2797 sub_category = "0500";
2798 else if (!g_strcmp0(type, "desktop"))
2799 sub_category = "0600";
2800 else if (!g_strcmp0(type, "tablet"))
2801 sub_category = "0900";
2802 else if (!g_strcmp0(type, "watch"))
2805 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2808 static void p2p_support(GSupplicantInterface *interface)
2810 char dev_type[17] = {};
2811 const char *hostname;
2815 if (!g_supplicant_interface_has_p2p(interface))
2818 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2819 DBG("Could not register P2P technology driver");
2823 hostname = connman_utsname_get_hostname();
2825 hostname = "ConnMan";
2827 set_device_type(connman_machine_get_type(), dev_type);
2828 g_supplicant_interface_set_p2p_device_config(interface,
2829 hostname, dev_type);
2830 connman_peer_driver_register(&peer_driver);
2833 static void scan_started(GSupplicantInterface *interface)
2838 static void scan_finished(GSupplicantInterface *interface)
2840 #if defined TIZEN_EXT
2841 struct wifi_data *wifi;
2842 bool is_associating = false;
2843 static bool is_scanning = true;
2848 #if defined TIZEN_EXT
2849 wifi = g_supplicant_interface_get_data(interface);
2850 if (wifi && wifi->scan_pending_network) {
2851 network_connect(wifi->scan_pending_network);
2852 wifi->scan_pending_network = NULL;
2855 //service state - associating
2856 if(!wifi || !wifi->network)
2859 is_associating = connman_network_get_associating(wifi->network);
2860 if(is_associating && is_scanning){
2861 is_scanning = false;
2862 DBG("send scan for connecting");
2863 throw_wifi_scan(wifi->device, scan_callback);
2874 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
2876 unsigned char strength;
2878 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
2885 static void network_added(GSupplicantNetwork *supplicant_network)
2887 struct connman_network *network;
2888 GSupplicantInterface *interface;
2889 struct wifi_data *wifi;
2890 const char *name, *identifier, *security, *group, *mode;
2891 const unsigned char *ssid;
2892 unsigned int ssid_len;
2896 bool wps_advertizing;
2898 mode = g_supplicant_network_get_mode(supplicant_network);
2899 identifier = g_supplicant_network_get_identifier(supplicant_network);
2901 DBG("%s", identifier);
2903 if (!g_strcmp0(mode, "adhoc"))
2906 interface = g_supplicant_network_get_interface(supplicant_network);
2907 wifi = g_supplicant_interface_get_data(interface);
2908 name = g_supplicant_network_get_name(supplicant_network);
2909 security = g_supplicant_network_get_security(supplicant_network);
2910 group = g_supplicant_network_get_identifier(supplicant_network);
2911 wps = g_supplicant_network_get_wps(supplicant_network);
2912 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
2913 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
2914 wps_advertizing = g_supplicant_network_is_wps_advertizing(
2915 supplicant_network);
2920 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
2922 network = connman_device_get_network(wifi->device, identifier);
2925 network = connman_network_create(identifier,
2926 CONNMAN_NETWORK_TYPE_WIFI);
2930 connman_network_set_index(network, wifi->index);
2932 if (connman_device_add_network(wifi->device, network) < 0) {
2933 connman_network_unref(network);
2937 wifi->networks = g_slist_prepend(wifi->networks, network);
2940 if (name && name[0] != '\0')
2941 connman_network_set_name(network, name);
2943 connman_network_set_blob(network, "WiFi.SSID",
2945 connman_network_set_string(network, "WiFi.Security", security);
2946 connman_network_set_strength(network,
2947 calculate_strength(supplicant_network));
2948 connman_network_set_bool(network, "WiFi.WPS", wps);
2951 /* Is AP advertizing for WPS association?
2952 * If so, we decide to use WPS by default */
2953 if (wps_ready && wps_pbc &&
2955 #if !defined TIZEN_EXT
2956 connman_network_set_bool(network, "WiFi.UseWPS", true);
2958 DBG("wps is activating by ap but ignore it.");
2963 connman_network_set_frequency(network,
2964 g_supplicant_network_get_frequency(supplicant_network));
2965 #if defined TIZEN_EXT
2966 connman_network_set_bssid(network,
2967 g_supplicant_network_get_bssid(supplicant_network));
2968 connman_network_set_maxrate(network,
2969 g_supplicant_network_get_maxrate(supplicant_network));
2970 connman_network_set_enc_mode(network,
2971 g_supplicant_network_get_enc_mode(supplicant_network));
2972 connman_network_set_rsn_mode(network,
2973 g_supplicant_network_get_rsn_mode(supplicant_network));
2974 connman_network_set_keymgmt(network,
2975 g_supplicant_network_get_keymgmt(supplicant_network));
2977 connman_network_set_available(network, true);
2978 connman_network_set_string(network, "WiFi.Mode", mode);
2980 #if defined TIZEN_EXT
2985 connman_network_set_group(network, group);
2987 #if defined TIZEN_EXT
2988 if (wifi_first_scan == true)
2989 found_with_first_scan = true;
2992 if (wifi->hidden && ssid) {
2993 #if defined TIZEN_EXT
2994 if (network_security(wifi->hidden->security) ==
2995 network_security(security) &&
2997 if (!g_strcmp0(wifi->hidden->security, security) &&
2999 wifi->hidden->ssid_len == ssid_len &&
3000 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3001 connman_network_connect_hidden(network,
3002 wifi->hidden->identity,
3003 wifi->hidden->passphrase,
3004 wifi->hidden->user_data);
3005 wifi->hidden->user_data = NULL;
3006 hidden_free(wifi->hidden);
3007 wifi->hidden = NULL;
3012 static void network_removed(GSupplicantNetwork *network)
3014 GSupplicantInterface *interface;
3015 struct wifi_data *wifi;
3016 const char *name, *identifier;
3017 struct connman_network *connman_network;
3019 interface = g_supplicant_network_get_interface(network);
3020 wifi = g_supplicant_interface_get_data(interface);
3021 identifier = g_supplicant_network_get_identifier(network);
3022 name = g_supplicant_network_get_name(network);
3024 DBG("name %s", name);
3029 connman_network = connman_device_get_network(wifi->device, identifier);
3030 if (!connman_network)
3033 #if defined TIZEN_EXT
3034 if (connman_network == wifi->scan_pending_network)
3035 wifi->scan_pending_network = NULL;
3037 if (connman_network == wifi->pending_network)
3038 wifi->pending_network = NULL;
3040 if(connman_network_get_connecting(connman_network) == true){
3041 connman_network_set_connected(connman_network, false);
3045 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3047 connman_device_remove_network(wifi->device, connman_network);
3048 connman_network_unref(connman_network);
3051 static void network_changed(GSupplicantNetwork *network, const char *property)
3053 GSupplicantInterface *interface;
3054 struct wifi_data *wifi;
3055 const char *name, *identifier;
3056 struct connman_network *connman_network;
3058 #if defined TIZEN_EXT
3059 const unsigned char *bssid;
3060 unsigned int maxrate;
3065 interface = g_supplicant_network_get_interface(network);
3066 wifi = g_supplicant_interface_get_data(interface);
3067 identifier = g_supplicant_network_get_identifier(network);
3068 name = g_supplicant_network_get_name(network);
3070 DBG("name %s", name);
3075 connman_network = connman_device_get_network(wifi->device, identifier);
3076 if (!connman_network)
3079 if (g_str_equal(property, "Signal")) {
3080 connman_network_set_strength(connman_network,
3081 calculate_strength(network));
3082 connman_network_update(connman_network);
3085 #if defined TIZEN_EXT
3086 bssid = g_supplicant_network_get_bssid(network);
3087 maxrate = g_supplicant_network_get_maxrate(network);
3088 frequency = g_supplicant_network_get_frequency(network);
3089 wps = g_supplicant_network_get_wps(network);
3091 connman_network_set_bssid(connman_network, bssid);
3092 connman_network_set_maxrate(connman_network, maxrate);
3093 connman_network_set_frequency(connman_network, frequency);
3094 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3098 static void apply_peer_services(GSupplicantPeer *peer,
3099 struct connman_peer *connman_peer)
3101 const unsigned char *data;
3106 connman_peer_reset_services(connman_peer);
3108 data = g_supplicant_peer_get_widi_ies(peer, &length);
3110 connman_peer_add_service(connman_peer,
3111 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3115 static void add_station(const char *mac)
3117 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3121 static void remove_station(const char *mac)
3123 connman_technology_tethering_remove_station(mac);
3126 static void peer_found(GSupplicantPeer *peer)
3128 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3129 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3130 struct connman_peer *connman_peer;
3131 const char *identifier, *name;
3134 identifier = g_supplicant_peer_get_identifier(peer);
3135 name = g_supplicant_peer_get_name(peer);
3137 DBG("ident: %s", identifier);
3139 connman_peer = connman_peer_get(wifi->device, identifier);
3143 connman_peer = connman_peer_create(identifier);
3144 connman_peer_set_name(connman_peer, name);
3145 connman_peer_set_device(connman_peer, wifi->device);
3146 apply_peer_services(peer, connman_peer);
3148 ret = connman_peer_register(connman_peer);
3149 if (ret < 0 && ret != -EALREADY)
3150 connman_peer_unref(connman_peer);
3153 static void peer_lost(GSupplicantPeer *peer)
3155 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3156 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3157 struct connman_peer *connman_peer;
3158 const char *identifier;
3163 identifier = g_supplicant_peer_get_identifier(peer);
3165 DBG("ident: %s", identifier);
3167 connman_peer = connman_peer_get(wifi->device, identifier);
3169 if (wifi->p2p_connecting &&
3170 wifi->pending_peer == connman_peer) {
3171 peer_connect_timeout(wifi);
3173 connman_peer_unregister(connman_peer);
3174 connman_peer_unref(connman_peer);
3178 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3180 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3181 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3182 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3183 struct connman_peer *connman_peer;
3184 const char *identifier;
3186 identifier = g_supplicant_peer_get_identifier(peer);
3188 DBG("ident: %s", identifier);
3190 connman_peer = connman_peer_get(wifi->device, identifier);
3195 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3196 apply_peer_services(peer, connman_peer);
3197 connman_peer_services_changed(connman_peer);
3199 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3200 if (!g_supplicant_peer_is_in_a_group(peer))
3201 p_state = CONNMAN_PEER_STATE_IDLE;
3203 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3205 case G_SUPPLICANT_PEER_GROUP_STARTED:
3207 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3208 p_state = CONNMAN_PEER_STATE_IDLE;
3210 case G_SUPPLICANT_PEER_GROUP_JOINED:
3211 connman_peer_set_iface_address(connman_peer,
3212 g_supplicant_peer_get_iface_address(peer));
3214 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3215 p_state = CONNMAN_PEER_STATE_IDLE;
3217 case G_SUPPLICANT_PEER_GROUP_FAILED:
3218 if (g_supplicant_peer_has_requested_connection(peer))
3219 p_state = CONNMAN_PEER_STATE_IDLE;
3221 p_state = CONNMAN_PEER_STATE_FAILURE;
3225 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3226 p_state == CONNMAN_PEER_STATE_FAILURE) {
3227 if (wifi->p2p_connecting
3228 && connman_peer == wifi->pending_peer)
3229 peer_cancel_timeout(wifi);
3231 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3234 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3237 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3238 GSupplicantInterface *g_iface;
3239 struct wifi_data *g_wifi;
3241 g_iface = g_supplicant_peer_get_group_interface(peer);
3245 g_wifi = g_supplicant_interface_get_data(g_iface);
3249 connman_peer_set_as_master(connman_peer,
3250 !g_supplicant_peer_is_client(peer));
3251 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3254 connman_peer_set_state(connman_peer, p_state);
3257 static void peer_request(GSupplicantPeer *peer)
3259 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3260 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3261 struct connman_peer *connman_peer;
3262 const char *identifier;
3264 identifier = g_supplicant_peer_get_identifier(peer);
3266 DBG("ident: %s", identifier);
3268 connman_peer = connman_peer_get(wifi->device, identifier);
3272 connman_peer_request_connection(connman_peer);
3275 #if defined TIZEN_EXT
3276 static void system_power_off(void)
3279 struct wifi_data *wifi;
3280 struct connman_service *service;
3281 struct connman_ipconfig *ipconfig_ipv4;
3283 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3284 for (list = iface_list; list; list = list->next) {
3287 if (wifi->network != NULL) {
3288 service = connman_service_lookup_from_network(wifi->network);
3289 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3290 __connman_dhcp_stop(ipconfig_ipv4);
3296 static void network_merged(GSupplicantNetwork *network)
3298 GSupplicantInterface *interface;
3299 GSupplicantState state;
3300 struct wifi_data *wifi;
3301 const char *identifier;
3302 struct connman_network *connman_network;
3303 unsigned int ishs20AP = 0;
3306 interface = g_supplicant_network_get_interface(network);
3310 state = g_supplicant_interface_get_state(interface);
3311 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3314 wifi = g_supplicant_interface_get_data(interface);
3318 identifier = g_supplicant_network_get_identifier(network);
3320 connman_network = connman_device_get_network(wifi->device, identifier);
3321 if (!connman_network)
3324 DBG("merged identifier %s", identifier);
3326 if (wifi->connected == FALSE) {
3328 case G_SUPPLICANT_STATE_AUTHENTICATING:
3329 case G_SUPPLICANT_STATE_ASSOCIATING:
3330 case G_SUPPLICANT_STATE_ASSOCIATED:
3331 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3332 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3333 connman_network_set_associating(connman_network, TRUE);
3335 case G_SUPPLICANT_STATE_COMPLETED:
3336 connman_network_set_connected(connman_network, TRUE);
3339 DBG("Not handled the state : %d", state);
3344 ishs20AP = g_supplicant_network_is_hs20AP(network);
3345 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3348 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3349 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3350 connman_network_set_string(connman_network, "WiFi.EAP",
3352 connman_network_set_string(connman_network, "WiFi.Identity",
3353 g_supplicant_network_get_identity(network));
3354 connman_network_set_string(connman_network, "WiFi.Phase2",
3355 g_supplicant_network_get_phase2(network));
3360 wifi->network = connman_network;
3364 static void debug(const char *str)
3366 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3367 connman_debug("%s", str);
3370 static const GSupplicantCallbacks callbacks = {
3371 .system_ready = system_ready,
3372 .system_killed = system_killed,
3373 .interface_added = interface_added,
3374 .interface_state = interface_state,
3375 .interface_removed = interface_removed,
3376 .p2p_support = p2p_support,
3377 .scan_started = scan_started,
3378 .scan_finished = scan_finished,
3379 .network_added = network_added,
3380 .network_removed = network_removed,
3381 .network_changed = network_changed,
3382 .add_station = add_station,
3383 .remove_station = remove_station,
3384 .peer_found = peer_found,
3385 .peer_lost = peer_lost,
3386 .peer_changed = peer_changed,
3387 .peer_request = peer_request,
3388 #if defined TIZEN_EXT
3389 .system_power_off = system_power_off,
3390 .network_merged = network_merged,
3396 static int tech_probe(struct connman_technology *technology)
3398 wifi_technology = technology;
3403 static void tech_remove(struct connman_technology *technology)
3405 wifi_technology = NULL;
3408 struct wifi_tethering_info {
3409 struct wifi_data *wifi;
3410 struct connman_technology *technology;
3412 GSupplicantSSID *ssid;
3415 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3416 const char *passphrase, bool hidden)
3418 GSupplicantSSID *ap;
3420 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3424 ap->mode = G_SUPPLICANT_MODE_MASTER;
3426 ap->ssid_len = strlen(ssid);
3430 if (!passphrase || strlen(passphrase) == 0) {
3431 ap->security = G_SUPPLICANT_SECURITY_NONE;
3432 ap->passphrase = NULL;
3434 ap->security = G_SUPPLICANT_SECURITY_PSK;
3435 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3436 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3437 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3438 ap->passphrase = passphrase;
3442 ap->ignore_broadcast_ssid =
3443 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3445 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3450 static void ap_start_callback(int result, GSupplicantInterface *interface,
3453 struct wifi_tethering_info *info = user_data;
3455 DBG("result %d index %d bridge %s",
3456 result, info->wifi->index, info->wifi->bridge);
3459 connman_inet_remove_from_bridge(info->wifi->index,
3460 info->wifi->bridge);
3461 connman_technology_tethering_notify(info->technology, false);
3464 g_free(info->ifname);
3468 static void ap_create_callback(int result,
3469 GSupplicantInterface *interface,
3472 struct wifi_tethering_info *info = user_data;
3474 DBG("result %d ifname %s", result,
3475 g_supplicant_interface_get_ifname(interface));
3478 connman_inet_remove_from_bridge(info->wifi->index,
3479 info->wifi->bridge);
3480 connman_technology_tethering_notify(info->technology, false);
3482 g_free(info->ifname);
3488 info->wifi->interface = interface;
3489 g_supplicant_interface_set_data(interface, info->wifi);
3491 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3492 connman_error("Failed to set interface ap_scan property");
3494 g_supplicant_interface_connect(interface, info->ssid,
3495 ap_start_callback, info);
3498 static void sta_remove_callback(int result,
3499 GSupplicantInterface *interface,
3502 struct wifi_tethering_info *info = user_data;
3503 const char *driver = connman_option_get_string("wifi");
3505 DBG("ifname %s result %d ", info->ifname, result);
3508 info->wifi->tethering = true;
3510 g_free(info->ifname);
3516 info->wifi->interface = NULL;
3518 connman_technology_tethering_notify(info->technology, true);
3520 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3525 static int tech_set_tethering(struct connman_technology *technology,
3526 const char *identifier, const char *passphrase,
3527 const char *bridge, bool enabled, bool hidden)
3530 GSupplicantInterface *interface;
3531 struct wifi_data *wifi;
3532 struct wifi_tethering_info *info;
3540 for (list = iface_list; list; list = list->next) {
3543 if (wifi->tethering) {
3544 wifi->tethering = false;
3546 connman_inet_remove_from_bridge(wifi->index,
3548 wifi->bridged = false;
3552 connman_technology_tethering_notify(technology, false);
3557 for (list = iface_list; list; list = list->next) {
3560 interface = wifi->interface;
3565 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3567 mode = g_supplicant_interface_get_mode(interface);
3568 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3569 DBG("%s does not support AP mode", ifname);
3573 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3578 info->technology = technology;
3579 info->wifi->bridge = bridge;
3580 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3585 info->ifname = g_strdup(ifname);
3586 if (!info->ifname) {
3592 info->wifi->tethering = true;
3594 err = g_supplicant_interface_remove(interface,
3595 sta_remove_callback,
3604 static void regdom_callback(int result, const char *alpha2, void *user_data)
3608 if (!wifi_technology)
3614 connman_technology_regdom_notify(wifi_technology, alpha2);
3617 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3619 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3622 static struct connman_technology_driver tech_driver = {
3624 .type = CONNMAN_SERVICE_TYPE_WIFI,
3625 .probe = tech_probe,
3626 .remove = tech_remove,
3627 .set_tethering = tech_set_tethering,
3628 .set_regdom = tech_set_regdom,
3631 static int wifi_init(void)
3635 err = connman_network_driver_register(&network_driver);
3639 err = g_supplicant_register(&callbacks);
3641 connman_network_driver_unregister(&network_driver);
3645 err = connman_technology_driver_register(&tech_driver);
3647 g_supplicant_unregister(&callbacks);
3648 connman_network_driver_unregister(&network_driver);
3655 static void wifi_exit(void)
3659 connman_technology_driver_unregister(&tech_driver);
3661 g_supplicant_unregister(&callbacks);
3663 connman_network_driver_unregister(&network_driver);
3666 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3667 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)