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)
1186 #if defined TIZEN_EXT
1187 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1189 if (connman_device_get_scanning(device))
1193 connman_device_ref(device);
1195 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1198 connman_device_set_scanning(device,
1199 CONNMAN_SERVICE_TYPE_WIFI, true);
1201 connman_device_unref(device);
1206 static void hidden_free(struct hidden_params *hidden)
1211 if (hidden->scan_params)
1212 g_supplicant_free_scan_params(hidden->scan_params);
1213 g_free(hidden->identity);
1214 g_free(hidden->passphrase);
1215 g_free(hidden->security);
1219 #if defined TIZEN_EXT
1220 static void service_state_changed(struct connman_service *service,
1221 enum connman_service_state state);
1223 static int network_connect(struct connman_network *network);
1225 static struct connman_notifier notifier = {
1227 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1228 .service_state_changed = service_state_changed,
1231 static void service_state_changed(struct connman_service *service,
1232 enum connman_service_state state)
1234 enum connman_service_type type;
1236 type = connman_service_get_type(service);
1237 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1240 DBG("service %p state %d", service, state);
1243 case CONNMAN_SERVICE_STATE_READY:
1244 case CONNMAN_SERVICE_STATE_ONLINE:
1245 case CONNMAN_SERVICE_STATE_FAILURE:
1246 connman_notifier_unregister(¬ifier);
1247 is_wifi_notifier_registered = FALSE;
1249 __connman_device_request_scan(type);
1258 static void scan_callback(int result, GSupplicantInterface *interface,
1261 struct connman_device *device = user_data;
1262 struct wifi_data *wifi = connman_device_get_data(device);
1265 DBG("result %d wifi %p", result, wifi);
1268 if (wifi->hidden && !wifi->postpone_hidden) {
1269 connman_network_clear_hidden(wifi->hidden->user_data);
1270 hidden_free(wifi->hidden);
1271 wifi->hidden = NULL;
1274 if (wifi->scan_params) {
1275 g_supplicant_free_scan_params(wifi->scan_params);
1276 wifi->scan_params = NULL;
1281 connman_device_reset_scanning(device);
1283 /* User is connecting to a hidden AP, let's wait for finished event */
1284 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1285 GSupplicantScanParams *scan_params;
1288 wifi->postpone_hidden = false;
1289 scan_params = wifi->hidden->scan_params;
1290 wifi->hidden->scan_params = NULL;
1292 reset_autoscan(device);
1294 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1295 scan_callback, device);
1299 /* On error, let's recall scan_callback, which will cleanup */
1300 return scan_callback(ret, interface, user_data);
1303 scanning = connman_device_get_scanning(device);
1304 #if defined TIZEN_EXT
1305 if (scanning && !wifi->allow_full_scan)
1309 connman_device_set_scanning(device,
1310 CONNMAN_SERVICE_TYPE_WIFI, false);
1312 if (result != -ENOLINK)
1313 #if defined TIZEN_EXT
1316 start_autoscan(device);
1319 * If we are here then we were scanning; however, if we are
1320 * also mid-flight disabling the interface, then wifi_disable
1321 * has already cleared the device scanning state and
1322 * unreferenced the device, obviating the need to do it here.
1326 connman_device_unref(device);
1328 #if defined TIZEN_EXT
1329 if (wifi && wifi->allow_full_scan) {
1330 DBG("Trigger Full Channel Scan");
1331 throw_wifi_scan(device, scan_callback);
1332 wifi->allow_full_scan = FALSE;
1334 if (wifi && wifi->scan_pending_network && result != -EIO) {
1335 network_connect(wifi->scan_pending_network);
1336 wifi->scan_pending_network = NULL;
1337 connman_network_set_connecting(wifi->network);
1340 if (is_wifi_notifier_registered != true &&
1341 wifi_first_scan == true && found_with_first_scan == true) {
1342 wifi_first_scan = false;
1343 found_with_first_scan = false;
1345 connman_notifier_register(¬ifier);
1346 is_wifi_notifier_registered = true;
1351 static void scan_callback_hidden(int result,
1352 GSupplicantInterface *interface, void *user_data)
1354 struct connman_device *device = user_data;
1355 struct wifi_data *wifi = connman_device_get_data(device);
1356 GSupplicantScanParams *scan_params;
1359 DBG("result %d wifi %p", result, wifi);
1364 /* User is trying to connect to a hidden AP */
1365 if (wifi->hidden && wifi->postpone_hidden)
1368 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1372 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1373 ret = g_supplicant_interface_scan(wifi->interface,
1375 scan_callback_hidden,
1381 g_supplicant_free_scan_params(scan_params);
1384 scan_callback(result, interface, user_data);
1387 static gboolean autoscan_timeout(gpointer data)
1389 struct connman_device *device = data;
1390 struct wifi_data *wifi = connman_device_get_data(device);
1391 struct autoscan_params *autoscan;
1397 autoscan = wifi->autoscan;
1399 if (autoscan->interval <= 0) {
1400 interval = autoscan->base;
1403 interval = autoscan->interval * autoscan->base;
1405 #if defined TIZEN_EXT
1406 if (autoscan->interval >= autoscan->limit)
1408 if (interval > autoscan->limit)
1410 interval = autoscan->limit;
1412 throw_wifi_scan(wifi->device, scan_callback_hidden);
1415 DBG("interval %d", interval);
1417 autoscan->interval = interval;
1419 autoscan->timeout = g_timeout_add_seconds(interval,
1420 autoscan_timeout, device);
1425 static void start_autoscan(struct connman_device *device)
1427 struct wifi_data *wifi = connman_device_get_data(device);
1428 struct autoscan_params *autoscan;
1435 if (wifi->p2p_device)
1438 if (wifi->connected)
1441 autoscan = wifi->autoscan;
1445 if (autoscan->timeout > 0 || autoscan->interval > 0)
1448 connman_device_ref(device);
1450 autoscan_timeout(device);
1453 static struct autoscan_params *parse_autoscan_params(const char *params)
1455 struct autoscan_params *autoscan;
1460 DBG("Emulating autoscan");
1462 list_params = g_strsplit(params, ":", 0);
1463 if (list_params == 0)
1466 if (g_strv_length(list_params) < 3) {
1467 g_strfreev(list_params);
1471 base = atoi(list_params[1]);
1472 limit = atoi(list_params[2]);
1474 g_strfreev(list_params);
1476 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1478 DBG("Could not allocate memory for autoscan");
1482 DBG("base %d - limit %d", base, limit);
1483 autoscan->base = base;
1484 autoscan->limit = limit;
1489 static void setup_autoscan(struct wifi_data *wifi)
1491 if (!wifi->autoscan)
1492 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1494 start_autoscan(wifi->device);
1497 static void finalize_interface_creation(struct wifi_data *wifi)
1499 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1501 if (!wifi->device) {
1502 connman_error("WiFi device not set");
1506 connman_device_set_powered(wifi->device, true);
1508 if (!connman_setting_get_bool("BackgroundScanning"))
1511 if (wifi->p2p_device)
1514 setup_autoscan(wifi);
1517 static void interface_create_callback(int result,
1518 GSupplicantInterface *interface,
1521 struct wifi_data *wifi = user_data;
1523 DBG("result %d ifname %s, wifi %p", result,
1524 g_supplicant_interface_get_ifname(interface),
1527 if (result < 0 || !wifi)
1530 wifi->interface = interface;
1531 g_supplicant_interface_set_data(interface, wifi);
1533 if (g_supplicant_interface_get_ready(interface)) {
1534 wifi->interface_ready = true;
1535 finalize_interface_creation(wifi);
1539 static int wifi_enable(struct connman_device *device)
1541 struct wifi_data *wifi = connman_device_get_data(device);
1544 const char *driver = connman_option_get_string("wifi");
1547 DBG("device %p %p", device, wifi);
1549 index = connman_device_get_index(device);
1550 if (!wifi || index < 0)
1553 if (is_p2p_connecting())
1554 return -EINPROGRESS;
1556 interface = connman_inet_ifname(index);
1557 ret = g_supplicant_interface_create(interface, driver, NULL,
1558 interface_create_callback,
1565 return -EINPROGRESS;
1568 static int wifi_disable(struct connman_device *device)
1570 struct wifi_data *wifi = connman_device_get_data(device);
1573 DBG("device %p wifi %p", device, wifi);
1578 wifi->connected = false;
1579 wifi->disconnecting = false;
1581 if (wifi->pending_network)
1582 wifi->pending_network = NULL;
1584 stop_autoscan(device);
1586 if (wifi->p2p_find_timeout) {
1587 g_source_remove(wifi->p2p_find_timeout);
1588 wifi->p2p_find_timeout = 0;
1589 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1590 connman_device_unref(wifi->device);
1593 /* In case of a user scan, device is still referenced */
1594 if (connman_device_get_scanning(device)) {
1595 connman_device_set_scanning(device,
1596 CONNMAN_SERVICE_TYPE_WIFI, false);
1597 connman_device_unref(wifi->device);
1600 remove_networks(device, wifi);
1602 #if defined TIZEN_EXT
1603 wifi->scan_pending_network = NULL;
1605 if (is_wifi_notifier_registered == true) {
1606 connman_notifier_unregister(¬ifier);
1607 is_wifi_notifier_registered = false;
1611 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1615 return -EINPROGRESS;
1618 struct last_connected {
1624 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1626 GTimeVal *aval = (GTimeVal *)a;
1627 GTimeVal *bval = (GTimeVal *)b;
1629 /* Note that the sort order is descending */
1630 if (aval->tv_sec < bval->tv_sec)
1633 if (aval->tv_sec > bval->tv_sec)
1639 static void free_entry(gpointer data)
1641 struct last_connected *entry = data;
1643 g_free(entry->ssid);
1647 static int get_latest_connections(int max_ssids,
1648 GSupplicantScanParams *scan_data)
1650 GSequenceIter *iter;
1651 GSequence *latest_list;
1652 struct last_connected *entry;
1661 latest_list = g_sequence_new(free_entry);
1665 services = connman_storage_get_services();
1666 for (i = 0; services && services[i]; i++) {
1667 if (strncmp(services[i], "wifi_", 5) != 0)
1670 keyfile = connman_storage_load_service(services[i]);
1674 str = g_key_file_get_string(keyfile,
1675 services[i], "Favorite", NULL);
1676 if (!str || g_strcmp0(str, "true")) {
1678 g_key_file_free(keyfile);
1683 str = g_key_file_get_string(keyfile,
1684 services[i], "AutoConnect", NULL);
1685 if (!str || g_strcmp0(str, "true")) {
1687 g_key_file_free(keyfile);
1692 str = g_key_file_get_string(keyfile,
1693 services[i], "Modified", NULL);
1695 g_key_file_free(keyfile);
1698 g_time_val_from_iso8601(str, &modified);
1701 ssid = g_key_file_get_string(keyfile,
1702 services[i], "SSID", NULL);
1704 freq = g_key_file_get_integer(keyfile, services[i],
1707 entry = g_try_new(struct last_connected, 1);
1709 g_sequence_free(latest_list);
1710 g_key_file_free(keyfile);
1716 entry->modified = modified;
1719 g_sequence_insert_sorted(latest_list, entry,
1725 g_key_file_free(keyfile);
1728 g_strfreev(services);
1730 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1732 iter = g_sequence_get_begin_iter(latest_list);
1734 for (i = 0; i < num_ssids; i++) {
1735 entry = g_sequence_get(iter);
1737 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1738 entry->modified.tv_sec);
1740 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1741 max_ssids, entry->ssid);
1743 iter = g_sequence_iter_next(iter);
1746 g_sequence_free(latest_list);
1750 static int wifi_scan_simple(struct connman_device *device)
1752 reset_autoscan(device);
1754 return throw_wifi_scan(device, scan_callback_hidden);
1757 static gboolean p2p_find_stop(gpointer data)
1759 struct connman_device *device = data;
1760 struct wifi_data *wifi = connman_device_get_data(device);
1764 wifi->p2p_find_timeout = 0;
1766 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1768 g_supplicant_interface_p2p_stop_find(wifi->interface);
1770 connman_device_unref(device);
1771 reset_autoscan(device);
1776 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1779 struct connman_device *device = user_data;
1780 struct wifi_data *wifi = connman_device_get_data(device);
1782 DBG("result %d wifi %p", result, wifi);
1784 if (wifi->p2p_find_timeout) {
1785 g_source_remove(wifi->p2p_find_timeout);
1786 wifi->p2p_find_timeout = 0;
1792 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1793 p2p_find_stop, device);
1794 if (!wifi->p2p_find_timeout)
1799 p2p_find_stop(device);
1802 static int p2p_find(struct connman_device *device)
1804 struct wifi_data *wifi;
1809 if (!p2p_technology)
1812 wifi = connman_device_get_data(device);
1814 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1817 reset_autoscan(device);
1818 connman_device_ref(device);
1820 ret = g_supplicant_interface_p2p_find(wifi->interface,
1821 p2p_find_callback, device);
1823 connman_device_unref(device);
1824 start_autoscan(device);
1826 connman_device_set_scanning(device,
1827 CONNMAN_SERVICE_TYPE_P2P, true);
1834 * Note that the hidden scan is only used when connecting to this specific
1835 * hidden AP first time. It is not used when system autoconnects to hidden AP.
1837 static int wifi_scan(enum connman_service_type type,
1838 struct connman_device *device,
1839 const char *ssid, unsigned int ssid_len,
1840 const char *identity, const char* passphrase,
1841 const char *security, void *user_data)
1843 struct wifi_data *wifi = connman_device_get_data(device);
1844 GSupplicantScanParams *scan_params = NULL;
1845 struct scan_ssid *scan_ssid;
1846 struct hidden_params *hidden;
1848 int driver_max_ssids = 0;
1855 if (wifi->p2p_device)
1858 if (type == CONNMAN_SERVICE_TYPE_P2P)
1859 return p2p_find(device);
1861 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
1863 if (wifi->tethering)
1866 scanning = connman_device_get_scanning(device);
1868 if (!ssid || ssid_len == 0 || ssid_len > 32) {
1872 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1874 DBG("max ssids %d", driver_max_ssids);
1875 if (driver_max_ssids == 0)
1876 return wifi_scan_simple(device);
1880 if (scanning && wifi->hidden && wifi->postpone_hidden)
1886 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1891 scan_ssid = g_try_new(struct scan_ssid, 1);
1893 g_free(scan_params);
1897 memcpy(scan_ssid->ssid, ssid, ssid_len);
1898 scan_ssid->ssid_len = ssid_len;
1899 scan_params->ssids = g_slist_prepend(scan_params->ssids,
1901 scan_params->num_ssids = 1;
1903 hidden = g_try_new0(struct hidden_params, 1);
1905 g_supplicant_free_scan_params(scan_params);
1910 hidden_free(wifi->hidden);
1911 wifi->hidden = NULL;
1914 memcpy(hidden->ssid, ssid, ssid_len);
1915 hidden->ssid_len = ssid_len;
1916 hidden->identity = g_strdup(identity);
1917 hidden->passphrase = g_strdup(passphrase);
1918 hidden->security = g_strdup(security);
1919 hidden->user_data = user_data;
1920 wifi->hidden = hidden;
1923 /* Let's keep this active scan for later,
1924 * when current scan will be over. */
1925 wifi->postpone_hidden = TRUE;
1926 hidden->scan_params = scan_params;
1930 } else if (wifi->connected) {
1931 g_supplicant_free_scan_params(scan_params);
1932 return wifi_scan_simple(device);
1934 ret = get_latest_connections(driver_max_ssids, scan_params);
1936 g_supplicant_free_scan_params(scan_params);
1937 return wifi_scan_simple(device);
1941 connman_device_ref(device);
1943 #if defined TIZEN_EXT
1944 /*To allow the Full Scan after ssid based scan, set the flag here
1945 It is required because Tizen does not use the ConnMan specific
1946 backgroung Scan feature.Tizen has added the BG Scan feature in net-config
1947 To sync with up ConnMan, we need to issue the Full Scan after SSID specific scan.*/
1948 wifi->allow_full_scan = TRUE;
1950 reset_autoscan(device);
1952 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1953 scan_callback, device);
1956 connman_device_set_scanning(device,
1957 CONNMAN_SERVICE_TYPE_WIFI, true);
1959 g_supplicant_free_scan_params(scan_params);
1960 connman_device_unref(device);
1963 hidden_free(wifi->hidden);
1964 wifi->hidden = NULL;
1971 static void wifi_regdom_callback(int result,
1975 struct connman_device *device = user_data;
1977 connman_device_regdom_notify(device, result, alpha2);
1979 connman_device_unref(device);
1982 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
1984 struct wifi_data *wifi = connman_device_get_data(device);
1990 connman_device_ref(device);
1992 ret = g_supplicant_interface_set_country(wifi->interface,
1993 wifi_regdom_callback,
1996 connman_device_unref(device);
2001 static struct connman_device_driver wifi_ng_driver = {
2003 .type = CONNMAN_DEVICE_TYPE_WIFI,
2004 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2005 .probe = wifi_probe,
2006 .remove = wifi_remove,
2007 .enable = wifi_enable,
2008 .disable = wifi_disable,
2010 .set_regdom = wifi_set_regdom,
2013 static void system_ready(void)
2017 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2018 connman_error("Failed to register WiFi driver");
2021 static void system_killed(void)
2025 connman_device_driver_unregister(&wifi_ng_driver);
2028 static int network_probe(struct connman_network *network)
2030 DBG("network %p", network);
2035 static void network_remove(struct connman_network *network)
2037 struct connman_device *device = connman_network_get_device(network);
2038 struct wifi_data *wifi;
2040 DBG("network %p", network);
2042 wifi = connman_device_get_data(device);
2046 if (wifi->network != network)
2049 wifi->network = NULL;
2051 #if defined TIZEN_EXT
2052 wifi->disconnecting = false;
2054 if (wifi->pending_network == network)
2055 wifi->pending_network = NULL;
2057 if (wifi->scan_pending_network == network)
2058 wifi->scan_pending_network = NULL;
2062 static void connect_callback(int result, GSupplicantInterface *interface,
2065 #if defined TIZEN_EXT
2067 struct wifi_data *wifi;
2069 struct connman_network *network = user_data;
2071 DBG("network %p result %d", network, result);
2073 #if defined TIZEN_EXT
2074 for (list = iface_list; list; list = list->next) {
2077 if (wifi && wifi->network == network)
2081 /* wifi_data may be invalid because wifi is already disabled */
2086 if (result == -ENOKEY) {
2087 connman_network_set_error(network,
2088 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2089 } else if (result < 0) {
2090 connman_network_set_error(network,
2091 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2094 connman_network_unref(network);
2097 static GSupplicantSecurity network_security(const char *security)
2099 if (g_str_equal(security, "none"))
2100 return G_SUPPLICANT_SECURITY_NONE;
2101 else if (g_str_equal(security, "wep"))
2102 return G_SUPPLICANT_SECURITY_WEP;
2103 else if (g_str_equal(security, "psk"))
2104 return G_SUPPLICANT_SECURITY_PSK;
2105 else if (g_str_equal(security, "wpa"))
2106 return G_SUPPLICANT_SECURITY_PSK;
2107 else if (g_str_equal(security, "rsn"))
2108 return G_SUPPLICANT_SECURITY_PSK;
2109 else if (g_str_equal(security, "ieee8021x"))
2110 return G_SUPPLICANT_SECURITY_IEEE8021X;
2111 #if defined TIZEN_EXT
2112 else if (g_str_equal(security, "ft_psk") == TRUE)
2113 return G_SUPPLICANT_SECURITY_FT_PSK;
2114 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2115 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2118 return G_SUPPLICANT_SECURITY_UNKNOWN;
2121 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2123 const char *security;
2125 memset(ssid, 0, sizeof(*ssid));
2126 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2127 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2129 ssid->scan_ssid = 1;
2130 security = connman_network_get_string(network, "WiFi.Security");
2131 ssid->security = network_security(security);
2132 ssid->passphrase = connman_network_get_string(network,
2135 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2138 * If our private key password is unset,
2139 * we use the supplied passphrase. That is needed
2140 * for PEAP where 2 passphrases (identity and client
2141 * cert may have to be provided.
2143 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2144 connman_network_set_string(network,
2145 "WiFi.PrivateKeyPassphrase",
2147 /* We must have an identity for both PEAP and TLS */
2148 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2150 /* Use agent provided identity as a fallback */
2151 if (!ssid->identity || strlen(ssid->identity) == 0)
2152 ssid->identity = connman_network_get_string(network,
2153 "WiFi.AgentIdentity");
2155 ssid->ca_cert_path = connman_network_get_string(network,
2157 ssid->client_cert_path = connman_network_get_string(network,
2158 "WiFi.ClientCertFile");
2159 ssid->private_key_path = connman_network_get_string(network,
2160 "WiFi.PrivateKeyFile");
2161 ssid->private_key_passphrase = connman_network_get_string(network,
2162 "WiFi.PrivateKeyPassphrase");
2163 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2165 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2166 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2168 #if defined TIZEN_EXT
2169 ssid->bssid = connman_network_get_bssid(network);
2172 if (connman_setting_get_bool("BackgroundScanning"))
2173 ssid->bgscan = BGSCAN_DEFAULT;
2176 static int network_connect(struct connman_network *network)
2178 struct connman_device *device = connman_network_get_device(network);
2179 struct wifi_data *wifi;
2180 GSupplicantInterface *interface;
2181 GSupplicantSSID *ssid;
2183 DBG("network %p", network);
2188 wifi = connman_device_get_data(device);
2192 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2196 interface = wifi->interface;
2198 ssid_init(ssid, network);
2200 if (wifi->disconnecting) {
2201 wifi->pending_network = network;
2204 wifi->network = connman_network_ref(network);
2206 #if defined TIZEN_EXT
2207 wifi->scan_pending_network = NULL;
2210 return g_supplicant_interface_connect(interface, ssid,
2211 connect_callback, network);
2214 return -EINPROGRESS;
2217 static void disconnect_callback(int result, GSupplicantInterface *interface,
2220 #if defined TIZEN_EXT
2222 struct wifi_data *wifi;
2223 struct connman_network *network = user_data;
2225 DBG("network %p result %d", network, result);
2227 for (list = iface_list; list; list = list->next) {
2230 if (wifi->network == NULL && wifi->disconnecting == true)
2231 wifi->disconnecting = false;
2233 if (wifi->network == network)
2237 /* wifi_data may be invalid because wifi is already disabled */
2242 struct wifi_data *wifi = user_data;
2245 DBG("result %d supplicant interface %p wifi %p",
2246 result, interface, wifi);
2248 if (result == -ECONNABORTED) {
2249 DBG("wifi interface no longer available");
2253 if (wifi->network) {
2255 * if result < 0 supplican return an error because
2256 * the network is not current.
2257 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2258 * failed, call connman_network_set_connected to report
2259 * disconnect is completed.
2262 connman_network_set_connected(wifi->network, false);
2265 wifi->network = NULL;
2267 wifi->disconnecting = false;
2269 if (wifi->pending_network) {
2270 network_connect(wifi->pending_network);
2271 wifi->pending_network = NULL;
2274 start_autoscan(wifi->device);
2277 static int network_disconnect(struct connman_network *network)
2279 struct connman_device *device = connman_network_get_device(network);
2280 struct wifi_data *wifi;
2282 #if defined TIZEN_EXT
2283 struct connman_service *service;
2286 DBG("network %p", network);
2288 wifi = connman_device_get_data(device);
2289 if (!wifi || !wifi->interface)
2292 #if defined TIZEN_EXT
2293 if (connman_network_get_associating(network) == true) {
2294 connman_network_clear_associating(network);
2295 connman_network_set_bool(network, "WiFi.UseWPS", false);
2297 service = connman_service_lookup_from_network(network);
2299 if (service != NULL &&
2300 (__connman_service_is_connected_state(service,
2301 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2302 __connman_service_is_connected_state(service,
2303 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2304 (connman_service_get_favorite(service) == false))
2305 __connman_service_set_passphrase(service, NULL);
2308 if (wifi->pending_network == network)
2309 wifi->pending_network = NULL;
2311 if (wifi->scan_pending_network == network)
2312 wifi->scan_pending_network = NULL;
2315 connman_network_set_associating(network, false);
2317 if (wifi->disconnecting)
2320 wifi->disconnecting = true;
2322 #if defined TIZEN_EXT
2323 err = g_supplicant_interface_disconnect(wifi->interface,
2324 disconnect_callback, network);
2326 err = g_supplicant_interface_disconnect(wifi->interface,
2327 disconnect_callback, wifi);
2331 wifi->disconnecting = false;
2336 static struct connman_network_driver network_driver = {
2338 .type = CONNMAN_NETWORK_TYPE_WIFI,
2339 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2340 .probe = network_probe,
2341 .remove = network_remove,
2342 .connect = network_connect,
2343 .disconnect = network_disconnect,
2346 static void interface_added(GSupplicantInterface *interface)
2348 const char *ifname = g_supplicant_interface_get_ifname(interface);
2349 const char *driver = g_supplicant_interface_get_driver(interface);
2350 struct wifi_data *wifi;
2352 wifi = g_supplicant_interface_get_data(interface);
2354 wifi = get_pending_wifi_data(ifname);
2358 g_supplicant_interface_set_data(interface, wifi);
2359 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2360 wifi->p2p_device = true;
2363 DBG("ifname %s driver %s wifi %p tethering %d",
2364 ifname, driver, wifi, wifi->tethering);
2366 if (!wifi->device) {
2367 connman_error("WiFi device not set");
2371 connman_device_set_powered(wifi->device, true);
2374 static bool is_idle(struct wifi_data *wifi)
2376 DBG("state %d", wifi->state);
2378 switch (wifi->state) {
2379 case G_SUPPLICANT_STATE_UNKNOWN:
2380 case G_SUPPLICANT_STATE_DISABLED:
2381 case G_SUPPLICANT_STATE_DISCONNECTED:
2382 case G_SUPPLICANT_STATE_INACTIVE:
2383 case G_SUPPLICANT_STATE_SCANNING:
2386 case G_SUPPLICANT_STATE_AUTHENTICATING:
2387 case G_SUPPLICANT_STATE_ASSOCIATING:
2388 case G_SUPPLICANT_STATE_ASSOCIATED:
2389 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2390 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2391 case G_SUPPLICANT_STATE_COMPLETED:
2398 static bool is_idle_wps(GSupplicantInterface *interface,
2399 struct wifi_data *wifi)
2401 /* First, let's check if WPS processing did not went wrong */
2402 if (g_supplicant_interface_get_wps_state(interface) ==
2403 G_SUPPLICANT_WPS_STATE_FAIL)
2406 /* Unlike normal connection, being associated while processing wps
2407 * actually means that we are idling. */
2408 switch (wifi->state) {
2409 case G_SUPPLICANT_STATE_UNKNOWN:
2410 case G_SUPPLICANT_STATE_DISABLED:
2411 case G_SUPPLICANT_STATE_DISCONNECTED:
2412 case G_SUPPLICANT_STATE_INACTIVE:
2413 case G_SUPPLICANT_STATE_SCANNING:
2414 case G_SUPPLICANT_STATE_ASSOCIATED:
2416 case G_SUPPLICANT_STATE_AUTHENTICATING:
2417 case G_SUPPLICANT_STATE_ASSOCIATING:
2418 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2419 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2420 case G_SUPPLICANT_STATE_COMPLETED:
2427 static bool handle_wps_completion(GSupplicantInterface *interface,
2428 struct connman_network *network,
2429 struct connman_device *device,
2430 struct wifi_data *wifi)
2434 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2436 const unsigned char *ssid, *wps_ssid;
2437 unsigned int ssid_len, wps_ssid_len;
2438 const char *wps_key;
2440 /* Checking if we got associated with requested
2442 ssid = connman_network_get_blob(network, "WiFi.SSID",
2445 wps_ssid = g_supplicant_interface_get_wps_ssid(
2446 interface, &wps_ssid_len);
2448 if (!wps_ssid || wps_ssid_len != ssid_len ||
2449 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2450 connman_network_set_associating(network, false);
2451 #if defined TIZEN_EXT
2452 g_supplicant_interface_disconnect(wifi->interface,
2453 disconnect_callback, wifi->network);
2455 connman_network_set_bool(network, "WiFi.UseWPS", false);
2456 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2458 g_supplicant_interface_disconnect(wifi->interface,
2459 disconnect_callback, wifi);
2464 wps_key = g_supplicant_interface_get_wps_key(interface);
2465 connman_network_set_string(network, "WiFi.Passphrase",
2468 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2474 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2475 struct connman_network *network,
2476 struct wifi_data *wifi)
2478 #if defined TIZEN_EXT
2479 const char *security;
2480 struct connman_service *service;
2482 if (wifi->connected)
2485 security = connman_network_get_string(network, "WiFi.Security");
2487 if (g_str_equal(security, "ieee8021x") == true &&
2488 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2490 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2495 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2498 struct connman_service *service;
2500 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2503 if (wifi->connected)
2507 service = connman_service_lookup_from_network(network);
2513 if (connman_service_get_favorite(service)) {
2514 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2519 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2524 #if defined TIZEN_EXT
2525 static bool handle_wifi_assoc_retry(struct connman_network *network,
2526 struct wifi_data *wifi)
2528 const char *security;
2530 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2531 connman_network_get_connecting(network) != true) {
2532 wifi->assoc_retry_count = 0;
2536 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2537 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2538 wifi->assoc_retry_count = 0;
2542 security = connman_network_get_string(network, "WiFi.Security");
2543 if (g_str_equal(security, "ieee8021x") == true &&
2544 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2545 wifi->assoc_retry_count = 0;
2549 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2550 wifi->assoc_retry_count = 0;
2552 /* Honestly it's not an invalid-key error,
2553 * however QA team recommends that the invalid-key error
2554 * might be better to display for user experience.
2556 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2565 static void interface_state(GSupplicantInterface *interface)
2567 struct connman_network *network;
2568 struct connman_device *device;
2569 struct wifi_data *wifi;
2570 GSupplicantState state = g_supplicant_interface_get_state(interface);
2573 wifi = g_supplicant_interface_get_data(interface);
2575 DBG("wifi %p interface state %d", wifi, state);
2580 device = wifi->device;
2584 if (g_supplicant_interface_get_ready(interface) &&
2585 !wifi->interface_ready) {
2586 wifi->interface_ready = true;
2587 finalize_interface_creation(wifi);
2590 network = wifi->network;
2595 case G_SUPPLICANT_STATE_SCANNING:
2598 case G_SUPPLICANT_STATE_AUTHENTICATING:
2599 case G_SUPPLICANT_STATE_ASSOCIATING:
2600 #if defined TIZEN_EXT
2601 reset_autoscan(device);
2603 stop_autoscan(device);
2606 if (!wifi->connected)
2607 connman_network_set_associating(network, true);
2611 case G_SUPPLICANT_STATE_COMPLETED:
2612 #if defined TIZEN_EXT
2613 /* though it should be already reset: */
2614 reset_autoscan(device);
2616 wifi->assoc_retry_count = 0;
2618 wifi->scan_pending_network = NULL;
2620 /* though it should be already stopped: */
2621 stop_autoscan(device);
2624 if (!handle_wps_completion(interface, network, device, wifi))
2627 connman_network_set_connected(network, true);
2630 case G_SUPPLICANT_STATE_DISCONNECTED:
2632 * If we're in one of the idle modes, we have
2633 * not started association yet and thus setting
2634 * those ones to FALSE could cancel an association
2637 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2639 if (is_idle_wps(interface, wifi))
2645 /* If previous state was 4way-handshake, then
2646 * it's either: psk was incorrect and thus we retry
2647 * or if we reach the maximum retries we declare the
2649 if (handle_4way_handshake_failure(interface,
2653 /* We disable the selected network, if not then
2654 * wpa_supplicant will loop retrying */
2655 if (g_supplicant_interface_enable_selected_network(interface,
2657 DBG("Could not disables selected network");
2659 #if defined TIZEN_EXT
2661 int reason_code = 0;
2663 err = g_supplicant_interface_remove_network(wifi->interface);
2665 DBG("Failed to remove network(%d)", err);
2667 reason_code = g_supplicant_interface_get_disconnect_reason(wifi->interface);
2669 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2670 * Retry association until its retry count is expired */
2671 if (handle_wifi_assoc_retry(network, wifi) == true) {
2672 throw_wifi_scan(wifi->device, scan_callback);
2673 wifi->scan_pending_network = wifi->network;
2677 if(reason_code > 0){
2678 DBG("Set disconnect reason code(%d)", reason_code);
2679 connman_network_set_disconnect_reason(network, reason_code);
2682 /* To avoid unnecessary repeated association in wpa_supplicant,
2683 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2684 if (wps != true && wifi->network && wifi->disconnecting == false) {
2685 wifi->disconnecting = true;
2686 err = g_supplicant_interface_disconnect(wifi->interface,
2687 disconnect_callback, wifi->network);
2689 wifi->disconnecting = false;
2691 connman_network_set_connected(network, false);
2692 connman_network_set_associating(network, false);
2694 start_autoscan(device);
2700 connman_network_set_connected(network, false);
2701 connman_network_set_associating(network, false);
2702 wifi->disconnecting = false;
2704 start_autoscan(device);
2708 case G_SUPPLICANT_STATE_INACTIVE:
2709 #if defined TIZEN_EXT
2710 if (handle_wps_completion(interface, network, device, wifi) == false)
2713 connman_network_set_associating(network, false);
2714 start_autoscan(device);
2718 case G_SUPPLICANT_STATE_UNKNOWN:
2719 case G_SUPPLICANT_STATE_DISABLED:
2720 case G_SUPPLICANT_STATE_ASSOCIATED:
2721 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2722 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2726 wifi->state = state;
2728 /* Saving wpa_s state policy:
2729 * If connected and if the state changes are roaming related:
2730 * --> We stay connected
2732 * --> We are connected
2734 * --> We are not connected
2737 #if defined TIZEN_EXT
2738 case G_SUPPLICANT_STATE_SCANNING:
2741 case G_SUPPLICANT_STATE_AUTHENTICATING:
2742 case G_SUPPLICANT_STATE_ASSOCIATING:
2743 case G_SUPPLICANT_STATE_ASSOCIATED:
2744 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2745 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2746 if (wifi->connected)
2747 connman_warn("Probably roaming right now!"
2748 " Staying connected...");
2750 wifi->connected = false;
2752 case G_SUPPLICANT_STATE_COMPLETED:
2753 wifi->connected = true;
2756 wifi->connected = false;
2763 static void interface_removed(GSupplicantInterface *interface)
2765 const char *ifname = g_supplicant_interface_get_ifname(interface);
2766 struct wifi_data *wifi;
2768 DBG("ifname %s", ifname);
2770 wifi = g_supplicant_interface_get_data(interface);
2773 wifi->interface = NULL;
2775 if (wifi && wifi->tethering)
2778 if (!wifi || !wifi->device) {
2779 DBG("wifi interface already removed");
2783 connman_device_set_powered(wifi->device, false);
2785 check_p2p_technology();
2788 static void set_device_type(const char *type, char dev_type[17])
2790 const char *oui = "0050F204";
2791 const char *category = "0100";
2792 const char *sub_category = "0000";
2794 if (!g_strcmp0(type, "handset")) {
2796 sub_category = "0500";
2797 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2798 sub_category = "0100";
2799 else if (!g_strcmp0(type, "server"))
2800 sub_category = "0200";
2801 else if (!g_strcmp0(type, "laptop"))
2802 sub_category = "0500";
2803 else if (!g_strcmp0(type, "desktop"))
2804 sub_category = "0600";
2805 else if (!g_strcmp0(type, "tablet"))
2806 sub_category = "0900";
2807 else if (!g_strcmp0(type, "watch"))
2810 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2813 static void p2p_support(GSupplicantInterface *interface)
2815 char dev_type[17] = {};
2816 const char *hostname;
2820 if (!g_supplicant_interface_has_p2p(interface))
2823 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2824 DBG("Could not register P2P technology driver");
2828 hostname = connman_utsname_get_hostname();
2830 hostname = "ConnMan";
2832 set_device_type(connman_machine_get_type(), dev_type);
2833 g_supplicant_interface_set_p2p_device_config(interface,
2834 hostname, dev_type);
2835 connman_peer_driver_register(&peer_driver);
2838 static void scan_started(GSupplicantInterface *interface)
2843 static void scan_finished(GSupplicantInterface *interface)
2845 #if defined TIZEN_EXT
2846 struct wifi_data *wifi;
2847 bool is_associating = false;
2848 static bool is_scanning = true;
2853 #if defined TIZEN_EXT
2854 wifi = g_supplicant_interface_get_data(interface);
2855 if (wifi && wifi->scan_pending_network) {
2856 network_connect(wifi->scan_pending_network);
2857 wifi->scan_pending_network = NULL;
2860 //service state - associating
2861 if(!wifi || !wifi->network)
2864 is_associating = connman_network_get_associating(wifi->network);
2865 if(is_associating && is_scanning){
2866 is_scanning = false;
2867 DBG("send scan for connecting");
2868 throw_wifi_scan(wifi->device, scan_callback);
2879 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
2881 unsigned char strength;
2883 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
2890 static void network_added(GSupplicantNetwork *supplicant_network)
2892 struct connman_network *network;
2893 GSupplicantInterface *interface;
2894 struct wifi_data *wifi;
2895 const char *name, *identifier, *security, *group, *mode;
2896 const unsigned char *ssid;
2897 unsigned int ssid_len;
2901 bool wps_advertizing;
2903 mode = g_supplicant_network_get_mode(supplicant_network);
2904 identifier = g_supplicant_network_get_identifier(supplicant_network);
2906 DBG("%s", identifier);
2908 if (!g_strcmp0(mode, "adhoc"))
2911 interface = g_supplicant_network_get_interface(supplicant_network);
2912 wifi = g_supplicant_interface_get_data(interface);
2913 name = g_supplicant_network_get_name(supplicant_network);
2914 security = g_supplicant_network_get_security(supplicant_network);
2915 group = g_supplicant_network_get_identifier(supplicant_network);
2916 wps = g_supplicant_network_get_wps(supplicant_network);
2917 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
2918 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
2919 wps_advertizing = g_supplicant_network_is_wps_advertizing(
2920 supplicant_network);
2925 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
2927 network = connman_device_get_network(wifi->device, identifier);
2930 network = connman_network_create(identifier,
2931 CONNMAN_NETWORK_TYPE_WIFI);
2935 connman_network_set_index(network, wifi->index);
2937 if (connman_device_add_network(wifi->device, network) < 0) {
2938 connman_network_unref(network);
2942 wifi->networks = g_slist_prepend(wifi->networks, network);
2945 if (name && name[0] != '\0')
2946 connman_network_set_name(network, name);
2948 connman_network_set_blob(network, "WiFi.SSID",
2950 connman_network_set_string(network, "WiFi.Security", security);
2951 connman_network_set_strength(network,
2952 calculate_strength(supplicant_network));
2953 connman_network_set_bool(network, "WiFi.WPS", wps);
2956 /* Is AP advertizing for WPS association?
2957 * If so, we decide to use WPS by default */
2958 if (wps_ready && wps_pbc &&
2960 #if !defined TIZEN_EXT
2961 connman_network_set_bool(network, "WiFi.UseWPS", true);
2963 DBG("wps is activating by ap but ignore it.");
2968 connman_network_set_frequency(network,
2969 g_supplicant_network_get_frequency(supplicant_network));
2970 #if defined TIZEN_EXT
2971 connman_network_set_bssid(network,
2972 g_supplicant_network_get_bssid(supplicant_network));
2973 connman_network_set_maxrate(network,
2974 g_supplicant_network_get_maxrate(supplicant_network));
2975 connman_network_set_enc_mode(network,
2976 g_supplicant_network_get_enc_mode(supplicant_network));
2977 connman_network_set_rsn_mode(network,
2978 g_supplicant_network_get_rsn_mode(supplicant_network));
2979 connman_network_set_keymgmt(network,
2980 g_supplicant_network_get_keymgmt(supplicant_network));
2982 connman_network_set_available(network, true);
2983 connman_network_set_string(network, "WiFi.Mode", mode);
2985 #if defined TIZEN_EXT
2990 connman_network_set_group(network, group);
2992 #if defined TIZEN_EXT
2993 if (wifi_first_scan == true)
2994 found_with_first_scan = true;
2997 if (wifi->hidden && ssid) {
2998 #if defined TIZEN_EXT
2999 if (network_security(wifi->hidden->security) ==
3000 network_security(security) &&
3002 if (!g_strcmp0(wifi->hidden->security, security) &&
3004 wifi->hidden->ssid_len == ssid_len &&
3005 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3006 connman_network_connect_hidden(network,
3007 wifi->hidden->identity,
3008 wifi->hidden->passphrase,
3009 wifi->hidden->user_data);
3010 wifi->hidden->user_data = NULL;
3011 hidden_free(wifi->hidden);
3012 wifi->hidden = NULL;
3017 static void network_removed(GSupplicantNetwork *network)
3019 GSupplicantInterface *interface;
3020 struct wifi_data *wifi;
3021 const char *name, *identifier;
3022 struct connman_network *connman_network;
3024 interface = g_supplicant_network_get_interface(network);
3025 wifi = g_supplicant_interface_get_data(interface);
3026 identifier = g_supplicant_network_get_identifier(network);
3027 name = g_supplicant_network_get_name(network);
3029 DBG("name %s", name);
3034 connman_network = connman_device_get_network(wifi->device, identifier);
3035 if (!connman_network)
3038 #if defined TIZEN_EXT
3039 if (connman_network == wifi->scan_pending_network)
3040 wifi->scan_pending_network = NULL;
3042 if (connman_network == wifi->pending_network)
3043 wifi->pending_network = NULL;
3045 if(connman_network_get_connecting(connman_network) == true){
3046 connman_network_set_connected(connman_network, false);
3050 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3052 connman_device_remove_network(wifi->device, connman_network);
3053 connman_network_unref(connman_network);
3056 static void network_changed(GSupplicantNetwork *network, const char *property)
3058 GSupplicantInterface *interface;
3059 struct wifi_data *wifi;
3060 const char *name, *identifier;
3061 struct connman_network *connman_network;
3063 #if defined TIZEN_EXT
3064 const unsigned char *bssid;
3065 unsigned int maxrate;
3070 interface = g_supplicant_network_get_interface(network);
3071 wifi = g_supplicant_interface_get_data(interface);
3072 identifier = g_supplicant_network_get_identifier(network);
3073 name = g_supplicant_network_get_name(network);
3075 DBG("name %s", name);
3080 connman_network = connman_device_get_network(wifi->device, identifier);
3081 if (!connman_network)
3084 if (g_str_equal(property, "Signal")) {
3085 connman_network_set_strength(connman_network,
3086 calculate_strength(network));
3087 connman_network_update(connman_network);
3090 #if defined TIZEN_EXT
3091 bssid = g_supplicant_network_get_bssid(network);
3092 maxrate = g_supplicant_network_get_maxrate(network);
3093 frequency = g_supplicant_network_get_frequency(network);
3094 wps = g_supplicant_network_get_wps(network);
3096 connman_network_set_bssid(connman_network, bssid);
3097 connman_network_set_maxrate(connman_network, maxrate);
3098 connman_network_set_frequency(connman_network, frequency);
3099 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3103 static void apply_peer_services(GSupplicantPeer *peer,
3104 struct connman_peer *connman_peer)
3106 const unsigned char *data;
3111 connman_peer_reset_services(connman_peer);
3113 data = g_supplicant_peer_get_widi_ies(peer, &length);
3115 connman_peer_add_service(connman_peer,
3116 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3120 static void add_station(const char *mac)
3122 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3126 static void remove_station(const char *mac)
3128 connman_technology_tethering_remove_station(mac);
3131 static void peer_found(GSupplicantPeer *peer)
3133 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3134 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3135 struct connman_peer *connman_peer;
3136 const char *identifier, *name;
3139 identifier = g_supplicant_peer_get_identifier(peer);
3140 name = g_supplicant_peer_get_name(peer);
3142 DBG("ident: %s", identifier);
3144 connman_peer = connman_peer_get(wifi->device, identifier);
3148 connman_peer = connman_peer_create(identifier);
3149 connman_peer_set_name(connman_peer, name);
3150 connman_peer_set_device(connman_peer, wifi->device);
3151 apply_peer_services(peer, connman_peer);
3153 ret = connman_peer_register(connman_peer);
3154 if (ret < 0 && ret != -EALREADY)
3155 connman_peer_unref(connman_peer);
3158 static void peer_lost(GSupplicantPeer *peer)
3160 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3161 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3162 struct connman_peer *connman_peer;
3163 const char *identifier;
3168 identifier = g_supplicant_peer_get_identifier(peer);
3170 DBG("ident: %s", identifier);
3172 connman_peer = connman_peer_get(wifi->device, identifier);
3174 if (wifi->p2p_connecting &&
3175 wifi->pending_peer == connman_peer) {
3176 peer_connect_timeout(wifi);
3178 connman_peer_unregister(connman_peer);
3179 connman_peer_unref(connman_peer);
3183 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3185 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3186 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3187 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3188 struct connman_peer *connman_peer;
3189 const char *identifier;
3191 identifier = g_supplicant_peer_get_identifier(peer);
3193 DBG("ident: %s", identifier);
3195 connman_peer = connman_peer_get(wifi->device, identifier);
3200 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3201 apply_peer_services(peer, connman_peer);
3202 connman_peer_services_changed(connman_peer);
3204 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3205 if (!g_supplicant_peer_is_in_a_group(peer))
3206 p_state = CONNMAN_PEER_STATE_IDLE;
3208 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3210 case G_SUPPLICANT_PEER_GROUP_STARTED:
3212 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3213 p_state = CONNMAN_PEER_STATE_IDLE;
3215 case G_SUPPLICANT_PEER_GROUP_JOINED:
3216 connman_peer_set_iface_address(connman_peer,
3217 g_supplicant_peer_get_iface_address(peer));
3219 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3220 p_state = CONNMAN_PEER_STATE_IDLE;
3222 case G_SUPPLICANT_PEER_GROUP_FAILED:
3223 if (g_supplicant_peer_has_requested_connection(peer))
3224 p_state = CONNMAN_PEER_STATE_IDLE;
3226 p_state = CONNMAN_PEER_STATE_FAILURE;
3230 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3231 p_state == CONNMAN_PEER_STATE_FAILURE) {
3232 if (wifi->p2p_connecting
3233 && connman_peer == wifi->pending_peer)
3234 peer_cancel_timeout(wifi);
3236 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3239 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3242 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3243 GSupplicantInterface *g_iface;
3244 struct wifi_data *g_wifi;
3246 g_iface = g_supplicant_peer_get_group_interface(peer);
3250 g_wifi = g_supplicant_interface_get_data(g_iface);
3254 connman_peer_set_as_master(connman_peer,
3255 !g_supplicant_peer_is_client(peer));
3256 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3259 connman_peer_set_state(connman_peer, p_state);
3262 static void peer_request(GSupplicantPeer *peer)
3264 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3265 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3266 struct connman_peer *connman_peer;
3267 const char *identifier;
3269 identifier = g_supplicant_peer_get_identifier(peer);
3271 DBG("ident: %s", identifier);
3273 connman_peer = connman_peer_get(wifi->device, identifier);
3277 connman_peer_request_connection(connman_peer);
3280 #if defined TIZEN_EXT
3281 static void system_power_off(void)
3284 struct wifi_data *wifi;
3285 struct connman_service *service;
3286 struct connman_ipconfig *ipconfig_ipv4;
3288 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3289 for (list = iface_list; list; list = list->next) {
3292 if (wifi->network != NULL) {
3293 service = connman_service_lookup_from_network(wifi->network);
3294 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3295 __connman_dhcp_stop(ipconfig_ipv4);
3301 static void network_merged(GSupplicantNetwork *network)
3303 GSupplicantInterface *interface;
3304 GSupplicantState state;
3305 struct wifi_data *wifi;
3306 const char *identifier;
3307 struct connman_network *connman_network;
3308 unsigned int ishs20AP = 0;
3311 interface = g_supplicant_network_get_interface(network);
3315 state = g_supplicant_interface_get_state(interface);
3316 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3319 wifi = g_supplicant_interface_get_data(interface);
3323 identifier = g_supplicant_network_get_identifier(network);
3325 connman_network = connman_device_get_network(wifi->device, identifier);
3326 if (!connman_network)
3329 DBG("merged identifier %s", identifier);
3331 if (wifi->connected == FALSE) {
3333 case G_SUPPLICANT_STATE_AUTHENTICATING:
3334 case G_SUPPLICANT_STATE_ASSOCIATING:
3335 case G_SUPPLICANT_STATE_ASSOCIATED:
3336 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3337 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3338 connman_network_set_associating(connman_network, TRUE);
3340 case G_SUPPLICANT_STATE_COMPLETED:
3341 connman_network_set_connected(connman_network, TRUE);
3344 DBG("Not handled the state : %d", state);
3349 ishs20AP = g_supplicant_network_is_hs20AP(network);
3350 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3353 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3354 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3355 connman_network_set_string(connman_network, "WiFi.EAP",
3357 connman_network_set_string(connman_network, "WiFi.Identity",
3358 g_supplicant_network_get_identity(network));
3359 connman_network_set_string(connman_network, "WiFi.Phase2",
3360 g_supplicant_network_get_phase2(network));
3365 wifi->network = connman_network;
3369 static void debug(const char *str)
3371 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3372 connman_debug("%s", str);
3375 static const GSupplicantCallbacks callbacks = {
3376 .system_ready = system_ready,
3377 .system_killed = system_killed,
3378 .interface_added = interface_added,
3379 .interface_state = interface_state,
3380 .interface_removed = interface_removed,
3381 .p2p_support = p2p_support,
3382 .scan_started = scan_started,
3383 .scan_finished = scan_finished,
3384 .network_added = network_added,
3385 .network_removed = network_removed,
3386 .network_changed = network_changed,
3387 .add_station = add_station,
3388 .remove_station = remove_station,
3389 .peer_found = peer_found,
3390 .peer_lost = peer_lost,
3391 .peer_changed = peer_changed,
3392 .peer_request = peer_request,
3393 #if defined TIZEN_EXT
3394 .system_power_off = system_power_off,
3395 .network_merged = network_merged,
3401 static int tech_probe(struct connman_technology *technology)
3403 wifi_technology = technology;
3408 static void tech_remove(struct connman_technology *technology)
3410 wifi_technology = NULL;
3413 struct wifi_tethering_info {
3414 struct wifi_data *wifi;
3415 struct connman_technology *technology;
3417 GSupplicantSSID *ssid;
3420 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3421 const char *passphrase, bool hidden)
3423 GSupplicantSSID *ap;
3425 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3429 ap->mode = G_SUPPLICANT_MODE_MASTER;
3431 ap->ssid_len = strlen(ssid);
3435 if (!passphrase || strlen(passphrase) == 0) {
3436 ap->security = G_SUPPLICANT_SECURITY_NONE;
3437 ap->passphrase = NULL;
3439 ap->security = G_SUPPLICANT_SECURITY_PSK;
3440 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3441 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3442 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3443 ap->passphrase = passphrase;
3447 ap->ignore_broadcast_ssid =
3448 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3450 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3455 static void ap_start_callback(int result, GSupplicantInterface *interface,
3458 struct wifi_tethering_info *info = user_data;
3460 DBG("result %d index %d bridge %s",
3461 result, info->wifi->index, info->wifi->bridge);
3464 connman_inet_remove_from_bridge(info->wifi->index,
3465 info->wifi->bridge);
3466 connman_technology_tethering_notify(info->technology, false);
3469 g_free(info->ifname);
3473 static void ap_create_callback(int result,
3474 GSupplicantInterface *interface,
3477 struct wifi_tethering_info *info = user_data;
3479 DBG("result %d ifname %s", result,
3480 g_supplicant_interface_get_ifname(interface));
3483 connman_inet_remove_from_bridge(info->wifi->index,
3484 info->wifi->bridge);
3485 connman_technology_tethering_notify(info->technology, false);
3487 g_free(info->ifname);
3493 info->wifi->interface = interface;
3494 g_supplicant_interface_set_data(interface, info->wifi);
3496 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3497 connman_error("Failed to set interface ap_scan property");
3499 g_supplicant_interface_connect(interface, info->ssid,
3500 ap_start_callback, info);
3503 static void sta_remove_callback(int result,
3504 GSupplicantInterface *interface,
3507 struct wifi_tethering_info *info = user_data;
3508 const char *driver = connman_option_get_string("wifi");
3510 DBG("ifname %s result %d ", info->ifname, result);
3513 info->wifi->tethering = true;
3515 g_free(info->ifname);
3521 info->wifi->interface = NULL;
3523 connman_technology_tethering_notify(info->technology, true);
3525 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3530 static int tech_set_tethering(struct connman_technology *technology,
3531 const char *identifier, const char *passphrase,
3532 const char *bridge, bool enabled, bool hidden)
3535 GSupplicantInterface *interface;
3536 struct wifi_data *wifi;
3537 struct wifi_tethering_info *info;
3545 for (list = iface_list; list; list = list->next) {
3548 if (wifi->tethering) {
3549 wifi->tethering = false;
3551 connman_inet_remove_from_bridge(wifi->index,
3553 wifi->bridged = false;
3557 connman_technology_tethering_notify(technology, false);
3562 for (list = iface_list; list; list = list->next) {
3565 interface = wifi->interface;
3570 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3572 mode = g_supplicant_interface_get_mode(interface);
3573 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3574 DBG("%s does not support AP mode", ifname);
3578 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3583 info->technology = technology;
3584 info->wifi->bridge = bridge;
3585 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3590 info->ifname = g_strdup(ifname);
3591 if (!info->ifname) {
3597 info->wifi->tethering = true;
3599 err = g_supplicant_interface_remove(interface,
3600 sta_remove_callback,
3609 static void regdom_callback(int result, const char *alpha2, void *user_data)
3613 if (!wifi_technology)
3619 connman_technology_regdom_notify(wifi_technology, alpha2);
3622 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3624 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3627 static struct connman_technology_driver tech_driver = {
3629 .type = CONNMAN_SERVICE_TYPE_WIFI,
3630 .probe = tech_probe,
3631 .remove = tech_remove,
3632 .set_tethering = tech_set_tethering,
3633 .set_regdom = tech_set_regdom,
3636 static int wifi_init(void)
3640 err = connman_network_driver_register(&network_driver);
3644 err = g_supplicant_register(&callbacks);
3646 connman_network_driver_unregister(&network_driver);
3650 err = connman_technology_driver_register(&tech_driver);
3652 g_supplicant_unregister(&callbacks);
3653 connman_network_driver_unregister(&network_driver);
3660 static void wifi_exit(void)
3664 connman_technology_driver_unregister(&tech_driver);
3666 g_supplicant_unregister(&callbacks);
3668 connman_network_driver_unregister(&network_driver);
3671 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3672 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)