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 && !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);
2171 #if defined TIZEN_EXT
2172 ssid->freq = connman_network_get_frequency(network);
2175 if (connman_setting_get_bool("BackgroundScanning"))
2176 ssid->bgscan = BGSCAN_DEFAULT;
2179 static int network_connect(struct connman_network *network)
2181 struct connman_device *device = connman_network_get_device(network);
2182 struct wifi_data *wifi;
2183 GSupplicantInterface *interface;
2184 GSupplicantSSID *ssid;
2186 DBG("network %p", network);
2191 wifi = connman_device_get_data(device);
2195 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2199 interface = wifi->interface;
2201 ssid_init(ssid, network);
2203 if (wifi->disconnecting) {
2204 wifi->pending_network = network;
2207 wifi->network = connman_network_ref(network);
2209 #if defined TIZEN_EXT
2210 wifi->scan_pending_network = NULL;
2213 return g_supplicant_interface_connect(interface, ssid,
2214 connect_callback, network);
2217 return -EINPROGRESS;
2220 static void disconnect_callback(int result, GSupplicantInterface *interface,
2223 #if defined TIZEN_EXT
2225 struct wifi_data *wifi;
2226 struct connman_network *network = user_data;
2228 DBG("network %p result %d", network, result);
2230 for (list = iface_list; list; list = list->next) {
2233 if (wifi->network == NULL && wifi->disconnecting == true)
2234 wifi->disconnecting = false;
2236 if (wifi->network == network)
2240 /* wifi_data may be invalid because wifi is already disabled */
2245 struct wifi_data *wifi = user_data;
2248 DBG("result %d supplicant interface %p wifi %p",
2249 result, interface, wifi);
2251 if (result == -ECONNABORTED) {
2252 DBG("wifi interface no longer available");
2256 if (wifi->network) {
2258 * if result < 0 supplican return an error because
2259 * the network is not current.
2260 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2261 * failed, call connman_network_set_connected to report
2262 * disconnect is completed.
2265 connman_network_set_connected(wifi->network, false);
2268 wifi->network = NULL;
2270 wifi->disconnecting = false;
2272 if (wifi->pending_network) {
2273 network_connect(wifi->pending_network);
2274 wifi->pending_network = NULL;
2277 start_autoscan(wifi->device);
2280 static int network_disconnect(struct connman_network *network)
2282 struct connman_device *device = connman_network_get_device(network);
2283 struct wifi_data *wifi;
2285 #if defined TIZEN_EXT
2286 struct connman_service *service;
2289 DBG("network %p", network);
2291 wifi = connman_device_get_data(device);
2292 if (!wifi || !wifi->interface)
2295 #if defined TIZEN_EXT
2296 if (connman_network_get_associating(network) == true) {
2297 connman_network_clear_associating(network);
2298 connman_network_set_bool(network, "WiFi.UseWPS", false);
2300 service = connman_service_lookup_from_network(network);
2302 if (service != NULL &&
2303 (__connman_service_is_connected_state(service,
2304 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2305 __connman_service_is_connected_state(service,
2306 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2307 (connman_service_get_favorite(service) == false))
2308 __connman_service_set_passphrase(service, NULL);
2311 if (wifi->pending_network == network)
2312 wifi->pending_network = NULL;
2314 if (wifi->scan_pending_network == network)
2315 wifi->scan_pending_network = NULL;
2318 connman_network_set_associating(network, false);
2320 if (wifi->disconnecting)
2323 wifi->disconnecting = true;
2325 #if defined TIZEN_EXT
2326 err = g_supplicant_interface_disconnect(wifi->interface,
2327 disconnect_callback, network);
2329 err = g_supplicant_interface_disconnect(wifi->interface,
2330 disconnect_callback, wifi);
2334 wifi->disconnecting = false;
2339 static struct connman_network_driver network_driver = {
2341 .type = CONNMAN_NETWORK_TYPE_WIFI,
2342 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2343 .probe = network_probe,
2344 .remove = network_remove,
2345 .connect = network_connect,
2346 .disconnect = network_disconnect,
2349 static void interface_added(GSupplicantInterface *interface)
2351 const char *ifname = g_supplicant_interface_get_ifname(interface);
2352 const char *driver = g_supplicant_interface_get_driver(interface);
2353 struct wifi_data *wifi;
2355 wifi = g_supplicant_interface_get_data(interface);
2357 wifi = get_pending_wifi_data(ifname);
2361 g_supplicant_interface_set_data(interface, wifi);
2362 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2363 wifi->p2p_device = true;
2366 DBG("ifname %s driver %s wifi %p tethering %d",
2367 ifname, driver, wifi, wifi->tethering);
2369 if (!wifi->device) {
2370 connman_error("WiFi device not set");
2374 connman_device_set_powered(wifi->device, true);
2377 static bool is_idle(struct wifi_data *wifi)
2379 DBG("state %d", wifi->state);
2381 switch (wifi->state) {
2382 case G_SUPPLICANT_STATE_UNKNOWN:
2383 case G_SUPPLICANT_STATE_DISABLED:
2384 case G_SUPPLICANT_STATE_DISCONNECTED:
2385 case G_SUPPLICANT_STATE_INACTIVE:
2386 case G_SUPPLICANT_STATE_SCANNING:
2389 case G_SUPPLICANT_STATE_AUTHENTICATING:
2390 case G_SUPPLICANT_STATE_ASSOCIATING:
2391 case G_SUPPLICANT_STATE_ASSOCIATED:
2392 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2393 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2394 case G_SUPPLICANT_STATE_COMPLETED:
2401 static bool is_idle_wps(GSupplicantInterface *interface,
2402 struct wifi_data *wifi)
2404 /* First, let's check if WPS processing did not went wrong */
2405 if (g_supplicant_interface_get_wps_state(interface) ==
2406 G_SUPPLICANT_WPS_STATE_FAIL)
2409 /* Unlike normal connection, being associated while processing wps
2410 * actually means that we are idling. */
2411 switch (wifi->state) {
2412 case G_SUPPLICANT_STATE_UNKNOWN:
2413 case G_SUPPLICANT_STATE_DISABLED:
2414 case G_SUPPLICANT_STATE_DISCONNECTED:
2415 case G_SUPPLICANT_STATE_INACTIVE:
2416 case G_SUPPLICANT_STATE_SCANNING:
2417 case G_SUPPLICANT_STATE_ASSOCIATED:
2419 case G_SUPPLICANT_STATE_AUTHENTICATING:
2420 case G_SUPPLICANT_STATE_ASSOCIATING:
2421 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2422 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2423 case G_SUPPLICANT_STATE_COMPLETED:
2430 static bool handle_wps_completion(GSupplicantInterface *interface,
2431 struct connman_network *network,
2432 struct connman_device *device,
2433 struct wifi_data *wifi)
2437 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2439 const unsigned char *ssid, *wps_ssid;
2440 unsigned int ssid_len, wps_ssid_len;
2441 const char *wps_key;
2443 /* Checking if we got associated with requested
2445 ssid = connman_network_get_blob(network, "WiFi.SSID",
2448 wps_ssid = g_supplicant_interface_get_wps_ssid(
2449 interface, &wps_ssid_len);
2451 if (!wps_ssid || wps_ssid_len != ssid_len ||
2452 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2453 connman_network_set_associating(network, false);
2454 #if defined TIZEN_EXT
2455 g_supplicant_interface_disconnect(wifi->interface,
2456 disconnect_callback, wifi->network);
2458 connman_network_set_bool(network, "WiFi.UseWPS", false);
2459 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2461 g_supplicant_interface_disconnect(wifi->interface,
2462 disconnect_callback, wifi);
2467 wps_key = g_supplicant_interface_get_wps_key(interface);
2468 connman_network_set_string(network, "WiFi.Passphrase",
2471 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2477 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2478 struct connman_network *network,
2479 struct wifi_data *wifi)
2481 #if defined TIZEN_EXT
2482 const char *security;
2483 struct connman_service *service;
2485 if (wifi->connected)
2488 security = connman_network_get_string(network, "WiFi.Security");
2490 if (g_str_equal(security, "ieee8021x") == true &&
2491 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2493 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2498 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2501 struct connman_service *service;
2503 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2506 if (wifi->connected)
2510 service = connman_service_lookup_from_network(network);
2516 if (connman_service_get_favorite(service)) {
2517 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2522 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2527 #if defined TIZEN_EXT
2528 static bool handle_wifi_assoc_retry(struct connman_network *network,
2529 struct wifi_data *wifi)
2531 const char *security;
2533 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2534 connman_network_get_connecting(network) != true) {
2535 wifi->assoc_retry_count = 0;
2539 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2540 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2541 wifi->assoc_retry_count = 0;
2545 security = connman_network_get_string(network, "WiFi.Security");
2546 if (g_str_equal(security, "ieee8021x") == true &&
2547 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2548 wifi->assoc_retry_count = 0;
2552 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2553 wifi->assoc_retry_count = 0;
2555 /* Honestly it's not an invalid-key error,
2556 * however QA team recommends that the invalid-key error
2557 * might be better to display for user experience.
2559 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2568 static void interface_state(GSupplicantInterface *interface)
2570 struct connman_network *network;
2571 struct connman_device *device;
2572 struct wifi_data *wifi;
2573 GSupplicantState state = g_supplicant_interface_get_state(interface);
2576 wifi = g_supplicant_interface_get_data(interface);
2578 DBG("wifi %p interface state %d", wifi, state);
2583 device = wifi->device;
2587 if (g_supplicant_interface_get_ready(interface) &&
2588 !wifi->interface_ready) {
2589 wifi->interface_ready = true;
2590 finalize_interface_creation(wifi);
2593 network = wifi->network;
2598 case G_SUPPLICANT_STATE_SCANNING:
2601 case G_SUPPLICANT_STATE_AUTHENTICATING:
2602 case G_SUPPLICANT_STATE_ASSOCIATING:
2603 #if defined TIZEN_EXT
2604 reset_autoscan(device);
2606 stop_autoscan(device);
2609 if (!wifi->connected)
2610 connman_network_set_associating(network, true);
2614 case G_SUPPLICANT_STATE_COMPLETED:
2615 #if defined TIZEN_EXT
2616 /* though it should be already reset: */
2617 reset_autoscan(device);
2619 wifi->assoc_retry_count = 0;
2621 wifi->scan_pending_network = NULL;
2623 /* should be cleared scanning flag */
2624 bool scanning = connman_device_get_scanning(device);
2626 connman_device_set_scanning(device,
2627 CONNMAN_SERVICE_TYPE_WIFI, false);
2628 connman_device_unref(device);
2631 /* though it should be already stopped: */
2632 stop_autoscan(device);
2635 if (!handle_wps_completion(interface, network, device, wifi))
2638 connman_network_set_connected(network, true);
2641 case G_SUPPLICANT_STATE_DISCONNECTED:
2643 * If we're in one of the idle modes, we have
2644 * not started association yet and thus setting
2645 * those ones to FALSE could cancel an association
2648 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2650 if (is_idle_wps(interface, wifi))
2656 /* If previous state was 4way-handshake, then
2657 * it's either: psk was incorrect and thus we retry
2658 * or if we reach the maximum retries we declare the
2660 if (handle_4way_handshake_failure(interface,
2664 /* We disable the selected network, if not then
2665 * wpa_supplicant will loop retrying */
2666 if (g_supplicant_interface_enable_selected_network(interface,
2668 DBG("Could not disables selected network");
2670 #if defined TIZEN_EXT
2672 int reason_code = 0;
2674 err = g_supplicant_interface_remove_network(wifi->interface);
2676 DBG("Failed to remove network(%d)", err);
2678 reason_code = g_supplicant_interface_get_disconnect_reason(wifi->interface);
2680 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2681 * Retry association until its retry count is expired */
2682 if (handle_wifi_assoc_retry(network, wifi) == true) {
2683 throw_wifi_scan(wifi->device, scan_callback);
2684 wifi->scan_pending_network = wifi->network;
2688 if(reason_code > 0){
2689 DBG("Set disconnect reason code(%d)", reason_code);
2690 connman_network_set_disconnect_reason(network, reason_code);
2693 /* To avoid unnecessary repeated association in wpa_supplicant,
2694 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2695 if (wps != true && wifi->network && wifi->disconnecting == false) {
2696 wifi->disconnecting = true;
2697 err = g_supplicant_interface_disconnect(wifi->interface,
2698 disconnect_callback, wifi->network);
2700 wifi->disconnecting = false;
2702 connman_network_set_connected(network, false);
2703 connman_network_set_associating(network, false);
2705 start_autoscan(device);
2711 connman_network_set_connected(network, false);
2712 connman_network_set_associating(network, false);
2713 wifi->disconnecting = false;
2715 start_autoscan(device);
2719 case G_SUPPLICANT_STATE_INACTIVE:
2720 #if defined TIZEN_EXT
2721 if (handle_wps_completion(interface, network, device, wifi) == false)
2724 connman_network_set_associating(network, false);
2725 start_autoscan(device);
2729 case G_SUPPLICANT_STATE_UNKNOWN:
2730 case G_SUPPLICANT_STATE_DISABLED:
2731 case G_SUPPLICANT_STATE_ASSOCIATED:
2732 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2733 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2737 wifi->state = state;
2739 /* Saving wpa_s state policy:
2740 * If connected and if the state changes are roaming related:
2741 * --> We stay connected
2743 * --> We are connected
2745 * --> We are not connected
2748 #if defined TIZEN_EXT
2749 case G_SUPPLICANT_STATE_SCANNING:
2752 case G_SUPPLICANT_STATE_AUTHENTICATING:
2753 case G_SUPPLICANT_STATE_ASSOCIATING:
2754 case G_SUPPLICANT_STATE_ASSOCIATED:
2755 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2756 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2757 if (wifi->connected)
2758 connman_warn("Probably roaming right now!"
2759 " Staying connected...");
2761 wifi->connected = false;
2763 case G_SUPPLICANT_STATE_COMPLETED:
2764 wifi->connected = true;
2767 wifi->connected = false;
2774 static void interface_removed(GSupplicantInterface *interface)
2776 const char *ifname = g_supplicant_interface_get_ifname(interface);
2777 struct wifi_data *wifi;
2779 DBG("ifname %s", ifname);
2781 wifi = g_supplicant_interface_get_data(interface);
2784 wifi->interface = NULL;
2786 if (wifi && wifi->tethering)
2789 if (!wifi || !wifi->device) {
2790 DBG("wifi interface already removed");
2794 connman_device_set_powered(wifi->device, false);
2796 check_p2p_technology();
2799 static void set_device_type(const char *type, char dev_type[17])
2801 const char *oui = "0050F204";
2802 const char *category = "0100";
2803 const char *sub_category = "0000";
2805 if (!g_strcmp0(type, "handset")) {
2807 sub_category = "0500";
2808 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2809 sub_category = "0100";
2810 else if (!g_strcmp0(type, "server"))
2811 sub_category = "0200";
2812 else if (!g_strcmp0(type, "laptop"))
2813 sub_category = "0500";
2814 else if (!g_strcmp0(type, "desktop"))
2815 sub_category = "0600";
2816 else if (!g_strcmp0(type, "tablet"))
2817 sub_category = "0900";
2818 else if (!g_strcmp0(type, "watch"))
2821 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2824 static void p2p_support(GSupplicantInterface *interface)
2826 char dev_type[17] = {};
2827 const char *hostname;
2831 if (!g_supplicant_interface_has_p2p(interface))
2834 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2835 DBG("Could not register P2P technology driver");
2839 hostname = connman_utsname_get_hostname();
2841 hostname = "ConnMan";
2843 set_device_type(connman_machine_get_type(), dev_type);
2844 g_supplicant_interface_set_p2p_device_config(interface,
2845 hostname, dev_type);
2846 connman_peer_driver_register(&peer_driver);
2849 static void scan_started(GSupplicantInterface *interface)
2854 static void scan_finished(GSupplicantInterface *interface)
2856 #if defined TIZEN_EXT
2857 struct wifi_data *wifi;
2858 bool is_associating = false;
2859 static bool is_scanning = true;
2864 #if defined TIZEN_EXT
2865 wifi = g_supplicant_interface_get_data(interface);
2866 if (wifi && wifi->scan_pending_network) {
2867 network_connect(wifi->scan_pending_network);
2868 wifi->scan_pending_network = NULL;
2871 //service state - associating
2872 if(!wifi || !wifi->network)
2875 is_associating = connman_network_get_associating(wifi->network);
2876 if(is_associating && is_scanning){
2877 is_scanning = false;
2878 DBG("send scan for connecting");
2879 throw_wifi_scan(wifi->device, scan_callback);
2890 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
2892 unsigned char strength;
2894 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
2901 static void network_added(GSupplicantNetwork *supplicant_network)
2903 struct connman_network *network;
2904 GSupplicantInterface *interface;
2905 struct wifi_data *wifi;
2906 const char *name, *identifier, *security, *group, *mode;
2907 const unsigned char *ssid;
2908 unsigned int ssid_len;
2912 bool wps_advertizing;
2914 mode = g_supplicant_network_get_mode(supplicant_network);
2915 identifier = g_supplicant_network_get_identifier(supplicant_network);
2917 DBG("%s", identifier);
2919 if (!g_strcmp0(mode, "adhoc"))
2922 interface = g_supplicant_network_get_interface(supplicant_network);
2923 wifi = g_supplicant_interface_get_data(interface);
2924 name = g_supplicant_network_get_name(supplicant_network);
2925 security = g_supplicant_network_get_security(supplicant_network);
2926 group = g_supplicant_network_get_identifier(supplicant_network);
2927 wps = g_supplicant_network_get_wps(supplicant_network);
2928 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
2929 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
2930 wps_advertizing = g_supplicant_network_is_wps_advertizing(
2931 supplicant_network);
2936 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
2938 network = connman_device_get_network(wifi->device, identifier);
2941 network = connman_network_create(identifier,
2942 CONNMAN_NETWORK_TYPE_WIFI);
2946 connman_network_set_index(network, wifi->index);
2948 if (connman_device_add_network(wifi->device, network) < 0) {
2949 connman_network_unref(network);
2953 wifi->networks = g_slist_prepend(wifi->networks, network);
2956 if (name && name[0] != '\0')
2957 connman_network_set_name(network, name);
2959 connman_network_set_blob(network, "WiFi.SSID",
2961 connman_network_set_string(network, "WiFi.Security", security);
2962 connman_network_set_strength(network,
2963 calculate_strength(supplicant_network));
2964 connman_network_set_bool(network, "WiFi.WPS", wps);
2967 /* Is AP advertizing for WPS association?
2968 * If so, we decide to use WPS by default */
2969 if (wps_ready && wps_pbc &&
2971 #if !defined TIZEN_EXT
2972 connman_network_set_bool(network, "WiFi.UseWPS", true);
2974 DBG("wps is activating by ap but ignore it.");
2979 connman_network_set_frequency(network,
2980 g_supplicant_network_get_frequency(supplicant_network));
2981 #if defined TIZEN_EXT
2982 connman_network_set_bssid(network,
2983 g_supplicant_network_get_bssid(supplicant_network));
2984 connman_network_set_maxrate(network,
2985 g_supplicant_network_get_maxrate(supplicant_network));
2986 connman_network_set_enc_mode(network,
2987 g_supplicant_network_get_enc_mode(supplicant_network));
2988 connman_network_set_rsn_mode(network,
2989 g_supplicant_network_get_rsn_mode(supplicant_network));
2990 connman_network_set_keymgmt(network,
2991 g_supplicant_network_get_keymgmt(supplicant_network));
2993 connman_network_set_available(network, true);
2994 connman_network_set_string(network, "WiFi.Mode", mode);
2996 #if defined TIZEN_EXT
3001 connman_network_set_group(network, group);
3003 #if defined TIZEN_EXT
3004 if (wifi_first_scan == true)
3005 found_with_first_scan = true;
3008 if (wifi->hidden && ssid) {
3009 #if defined TIZEN_EXT
3010 if (network_security(wifi->hidden->security) ==
3011 network_security(security) &&
3013 if (!g_strcmp0(wifi->hidden->security, security) &&
3015 wifi->hidden->ssid_len == ssid_len &&
3016 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3017 connman_network_connect_hidden(network,
3018 wifi->hidden->identity,
3019 wifi->hidden->passphrase,
3020 wifi->hidden->user_data);
3021 wifi->hidden->user_data = NULL;
3022 hidden_free(wifi->hidden);
3023 wifi->hidden = NULL;
3028 static void network_removed(GSupplicantNetwork *network)
3030 GSupplicantInterface *interface;
3031 struct wifi_data *wifi;
3032 const char *name, *identifier;
3033 struct connman_network *connman_network;
3035 interface = g_supplicant_network_get_interface(network);
3036 wifi = g_supplicant_interface_get_data(interface);
3037 identifier = g_supplicant_network_get_identifier(network);
3038 name = g_supplicant_network_get_name(network);
3040 DBG("name %s", name);
3045 connman_network = connman_device_get_network(wifi->device, identifier);
3046 if (!connman_network)
3049 #if defined TIZEN_EXT
3050 if (connman_network == wifi->scan_pending_network)
3051 wifi->scan_pending_network = NULL;
3053 if (connman_network == wifi->pending_network)
3054 wifi->pending_network = NULL;
3056 if(connman_network_get_connecting(connman_network) == true){
3057 connman_network_set_connected(connman_network, false);
3061 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3063 connman_device_remove_network(wifi->device, connman_network);
3064 connman_network_unref(connman_network);
3067 static void network_changed(GSupplicantNetwork *network, const char *property)
3069 GSupplicantInterface *interface;
3070 struct wifi_data *wifi;
3071 const char *name, *identifier;
3072 struct connman_network *connman_network;
3074 #if defined TIZEN_EXT
3075 const unsigned char *bssid;
3076 unsigned int maxrate;
3081 interface = g_supplicant_network_get_interface(network);
3082 wifi = g_supplicant_interface_get_data(interface);
3083 identifier = g_supplicant_network_get_identifier(network);
3084 name = g_supplicant_network_get_name(network);
3086 DBG("name %s", name);
3091 connman_network = connman_device_get_network(wifi->device, identifier);
3092 if (!connman_network)
3095 if (g_str_equal(property, "Signal")) {
3096 connman_network_set_strength(connman_network,
3097 calculate_strength(network));
3098 connman_network_update(connman_network);
3101 #if defined TIZEN_EXT
3102 bssid = g_supplicant_network_get_bssid(network);
3103 maxrate = g_supplicant_network_get_maxrate(network);
3104 frequency = g_supplicant_network_get_frequency(network);
3105 wps = g_supplicant_network_get_wps(network);
3107 connman_network_set_bssid(connman_network, bssid);
3108 connman_network_set_maxrate(connman_network, maxrate);
3109 connman_network_set_frequency(connman_network, frequency);
3110 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3114 static void apply_peer_services(GSupplicantPeer *peer,
3115 struct connman_peer *connman_peer)
3117 const unsigned char *data;
3122 connman_peer_reset_services(connman_peer);
3124 data = g_supplicant_peer_get_widi_ies(peer, &length);
3126 connman_peer_add_service(connman_peer,
3127 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3131 static void add_station(const char *mac)
3133 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3137 static void remove_station(const char *mac)
3139 connman_technology_tethering_remove_station(mac);
3142 static void peer_found(GSupplicantPeer *peer)
3144 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3145 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3146 struct connman_peer *connman_peer;
3147 const char *identifier, *name;
3150 identifier = g_supplicant_peer_get_identifier(peer);
3151 name = g_supplicant_peer_get_name(peer);
3153 DBG("ident: %s", identifier);
3155 connman_peer = connman_peer_get(wifi->device, identifier);
3159 connman_peer = connman_peer_create(identifier);
3160 connman_peer_set_name(connman_peer, name);
3161 connman_peer_set_device(connman_peer, wifi->device);
3162 apply_peer_services(peer, connman_peer);
3164 ret = connman_peer_register(connman_peer);
3165 if (ret < 0 && ret != -EALREADY)
3166 connman_peer_unref(connman_peer);
3169 static void peer_lost(GSupplicantPeer *peer)
3171 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3172 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3173 struct connman_peer *connman_peer;
3174 const char *identifier;
3179 identifier = g_supplicant_peer_get_identifier(peer);
3181 DBG("ident: %s", identifier);
3183 connman_peer = connman_peer_get(wifi->device, identifier);
3185 if (wifi->p2p_connecting &&
3186 wifi->pending_peer == connman_peer) {
3187 peer_connect_timeout(wifi);
3189 connman_peer_unregister(connman_peer);
3190 connman_peer_unref(connman_peer);
3194 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3196 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3197 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3198 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3199 struct connman_peer *connman_peer;
3200 const char *identifier;
3202 identifier = g_supplicant_peer_get_identifier(peer);
3204 DBG("ident: %s", identifier);
3206 connman_peer = connman_peer_get(wifi->device, identifier);
3211 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3212 apply_peer_services(peer, connman_peer);
3213 connman_peer_services_changed(connman_peer);
3215 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3216 if (!g_supplicant_peer_is_in_a_group(peer))
3217 p_state = CONNMAN_PEER_STATE_IDLE;
3219 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3221 case G_SUPPLICANT_PEER_GROUP_STARTED:
3223 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3224 p_state = CONNMAN_PEER_STATE_IDLE;
3226 case G_SUPPLICANT_PEER_GROUP_JOINED:
3227 connman_peer_set_iface_address(connman_peer,
3228 g_supplicant_peer_get_iface_address(peer));
3230 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3231 p_state = CONNMAN_PEER_STATE_IDLE;
3233 case G_SUPPLICANT_PEER_GROUP_FAILED:
3234 if (g_supplicant_peer_has_requested_connection(peer))
3235 p_state = CONNMAN_PEER_STATE_IDLE;
3237 p_state = CONNMAN_PEER_STATE_FAILURE;
3241 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3242 p_state == CONNMAN_PEER_STATE_FAILURE) {
3243 if (wifi->p2p_connecting
3244 && connman_peer == wifi->pending_peer)
3245 peer_cancel_timeout(wifi);
3247 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3250 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3253 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3254 GSupplicantInterface *g_iface;
3255 struct wifi_data *g_wifi;
3257 g_iface = g_supplicant_peer_get_group_interface(peer);
3261 g_wifi = g_supplicant_interface_get_data(g_iface);
3265 connman_peer_set_as_master(connman_peer,
3266 !g_supplicant_peer_is_client(peer));
3267 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3270 connman_peer_set_state(connman_peer, p_state);
3273 static void peer_request(GSupplicantPeer *peer)
3275 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3276 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3277 struct connman_peer *connman_peer;
3278 const char *identifier;
3280 identifier = g_supplicant_peer_get_identifier(peer);
3282 DBG("ident: %s", identifier);
3284 connman_peer = connman_peer_get(wifi->device, identifier);
3288 connman_peer_request_connection(connman_peer);
3291 #if defined TIZEN_EXT
3292 static void system_power_off(void)
3295 struct wifi_data *wifi;
3296 struct connman_service *service;
3297 struct connman_ipconfig *ipconfig_ipv4;
3299 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3300 for (list = iface_list; list; list = list->next) {
3303 if (wifi->network != NULL) {
3304 service = connman_service_lookup_from_network(wifi->network);
3305 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3306 __connman_dhcp_stop(ipconfig_ipv4);
3312 static void network_merged(GSupplicantNetwork *network)
3314 GSupplicantInterface *interface;
3315 GSupplicantState state;
3316 struct wifi_data *wifi;
3317 const char *identifier;
3318 struct connman_network *connman_network;
3319 unsigned int ishs20AP = 0;
3322 interface = g_supplicant_network_get_interface(network);
3326 state = g_supplicant_interface_get_state(interface);
3327 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3330 wifi = g_supplicant_interface_get_data(interface);
3334 identifier = g_supplicant_network_get_identifier(network);
3336 connman_network = connman_device_get_network(wifi->device, identifier);
3337 if (!connman_network)
3340 DBG("merged identifier %s", identifier);
3342 if (wifi->connected == FALSE) {
3344 case G_SUPPLICANT_STATE_AUTHENTICATING:
3345 case G_SUPPLICANT_STATE_ASSOCIATING:
3346 case G_SUPPLICANT_STATE_ASSOCIATED:
3347 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3348 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3349 connman_network_set_associating(connman_network, TRUE);
3351 case G_SUPPLICANT_STATE_COMPLETED:
3352 connman_network_set_connected(connman_network, TRUE);
3355 DBG("Not handled the state : %d", state);
3360 ishs20AP = g_supplicant_network_is_hs20AP(network);
3361 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3364 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3365 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3366 connman_network_set_string(connman_network, "WiFi.EAP",
3368 connman_network_set_string(connman_network, "WiFi.Identity",
3369 g_supplicant_network_get_identity(network));
3370 connman_network_set_string(connman_network, "WiFi.Phase2",
3371 g_supplicant_network_get_phase2(network));
3376 wifi->network = connman_network;
3380 static void debug(const char *str)
3382 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3383 connman_debug("%s", str);
3386 static const GSupplicantCallbacks callbacks = {
3387 .system_ready = system_ready,
3388 .system_killed = system_killed,
3389 .interface_added = interface_added,
3390 .interface_state = interface_state,
3391 .interface_removed = interface_removed,
3392 .p2p_support = p2p_support,
3393 .scan_started = scan_started,
3394 .scan_finished = scan_finished,
3395 .network_added = network_added,
3396 .network_removed = network_removed,
3397 .network_changed = network_changed,
3398 .add_station = add_station,
3399 .remove_station = remove_station,
3400 .peer_found = peer_found,
3401 .peer_lost = peer_lost,
3402 .peer_changed = peer_changed,
3403 .peer_request = peer_request,
3404 #if defined TIZEN_EXT
3405 .system_power_off = system_power_off,
3406 .network_merged = network_merged,
3412 static int tech_probe(struct connman_technology *technology)
3414 wifi_technology = technology;
3419 static void tech_remove(struct connman_technology *technology)
3421 wifi_technology = NULL;
3424 struct wifi_tethering_info {
3425 struct wifi_data *wifi;
3426 struct connman_technology *technology;
3428 GSupplicantSSID *ssid;
3431 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3432 const char *passphrase, bool hidden)
3434 GSupplicantSSID *ap;
3436 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3440 ap->mode = G_SUPPLICANT_MODE_MASTER;
3442 ap->ssid_len = strlen(ssid);
3446 if (!passphrase || strlen(passphrase) == 0) {
3447 ap->security = G_SUPPLICANT_SECURITY_NONE;
3448 ap->passphrase = NULL;
3450 ap->security = G_SUPPLICANT_SECURITY_PSK;
3451 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3452 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3453 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3454 ap->passphrase = passphrase;
3458 ap->ignore_broadcast_ssid =
3459 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3461 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3466 static void ap_start_callback(int result, GSupplicantInterface *interface,
3469 struct wifi_tethering_info *info = user_data;
3471 DBG("result %d index %d bridge %s",
3472 result, info->wifi->index, info->wifi->bridge);
3475 connman_inet_remove_from_bridge(info->wifi->index,
3476 info->wifi->bridge);
3477 connman_technology_tethering_notify(info->technology, false);
3480 g_free(info->ifname);
3484 static void ap_create_callback(int result,
3485 GSupplicantInterface *interface,
3488 struct wifi_tethering_info *info = user_data;
3490 DBG("result %d ifname %s", result,
3491 g_supplicant_interface_get_ifname(interface));
3494 connman_inet_remove_from_bridge(info->wifi->index,
3495 info->wifi->bridge);
3496 connman_technology_tethering_notify(info->technology, false);
3498 g_free(info->ifname);
3504 info->wifi->interface = interface;
3505 g_supplicant_interface_set_data(interface, info->wifi);
3507 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3508 connman_error("Failed to set interface ap_scan property");
3510 g_supplicant_interface_connect(interface, info->ssid,
3511 ap_start_callback, info);
3514 static void sta_remove_callback(int result,
3515 GSupplicantInterface *interface,
3518 struct wifi_tethering_info *info = user_data;
3519 const char *driver = connman_option_get_string("wifi");
3521 DBG("ifname %s result %d ", info->ifname, result);
3524 info->wifi->tethering = true;
3526 g_free(info->ifname);
3532 info->wifi->interface = NULL;
3534 connman_technology_tethering_notify(info->technology, true);
3536 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3541 static int tech_set_tethering(struct connman_technology *technology,
3542 const char *identifier, const char *passphrase,
3543 const char *bridge, bool enabled, bool hidden)
3546 GSupplicantInterface *interface;
3547 struct wifi_data *wifi;
3548 struct wifi_tethering_info *info;
3556 for (list = iface_list; list; list = list->next) {
3559 if (wifi->tethering) {
3560 wifi->tethering = false;
3562 connman_inet_remove_from_bridge(wifi->index,
3564 wifi->bridged = false;
3568 connman_technology_tethering_notify(technology, false);
3573 for (list = iface_list; list; list = list->next) {
3576 interface = wifi->interface;
3581 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3583 mode = g_supplicant_interface_get_mode(interface);
3584 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3585 DBG("%s does not support AP mode", ifname);
3589 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3594 info->technology = technology;
3595 info->wifi->bridge = bridge;
3596 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3601 info->ifname = g_strdup(ifname);
3602 if (!info->ifname) {
3608 info->wifi->tethering = true;
3610 err = g_supplicant_interface_remove(interface,
3611 sta_remove_callback,
3620 static void regdom_callback(int result, const char *alpha2, void *user_data)
3624 if (!wifi_technology)
3630 connman_technology_regdom_notify(wifi_technology, alpha2);
3633 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3635 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3638 static struct connman_technology_driver tech_driver = {
3640 .type = CONNMAN_SERVICE_TYPE_WIFI,
3641 .probe = tech_probe,
3642 .remove = tech_remove,
3643 .set_tethering = tech_set_tethering,
3644 .set_regdom = tech_set_regdom,
3647 static int wifi_init(void)
3651 err = connman_network_driver_register(&network_driver);
3655 err = g_supplicant_register(&callbacks);
3657 connman_network_driver_unregister(&network_driver);
3661 err = connman_technology_driver_register(&tech_driver);
3663 g_supplicant_unregister(&callbacks);
3664 connman_network_driver_unregister(&network_driver);
3671 static void wifi_exit(void)
3675 connman_technology_driver_unregister(&tech_driver);
3677 g_supplicant_unregister(&callbacks);
3679 connman_network_driver_unregister(&network_driver);
3682 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3683 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)