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);
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 /* should be cleared scanning flag */
2621 bool scanning = connman_device_get_scanning(device);
2623 connman_device_set_scanning(device,
2624 CONNMAN_SERVICE_TYPE_WIFI, false);
2625 connman_device_unref(device);
2628 /* though it should be already stopped: */
2629 stop_autoscan(device);
2632 if (!handle_wps_completion(interface, network, device, wifi))
2635 connman_network_set_connected(network, true);
2638 case G_SUPPLICANT_STATE_DISCONNECTED:
2640 * If we're in one of the idle modes, we have
2641 * not started association yet and thus setting
2642 * those ones to FALSE could cancel an association
2645 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2647 if (is_idle_wps(interface, wifi))
2653 /* If previous state was 4way-handshake, then
2654 * it's either: psk was incorrect and thus we retry
2655 * or if we reach the maximum retries we declare the
2657 if (handle_4way_handshake_failure(interface,
2661 /* We disable the selected network, if not then
2662 * wpa_supplicant will loop retrying */
2663 if (g_supplicant_interface_enable_selected_network(interface,
2665 DBG("Could not disables selected network");
2667 #if defined TIZEN_EXT
2669 int reason_code = 0;
2671 err = g_supplicant_interface_remove_network(wifi->interface);
2673 DBG("Failed to remove network(%d)", err);
2675 reason_code = g_supplicant_interface_get_disconnect_reason(wifi->interface);
2677 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2678 * Retry association until its retry count is expired */
2679 if (handle_wifi_assoc_retry(network, wifi) == true) {
2680 throw_wifi_scan(wifi->device, scan_callback);
2681 wifi->scan_pending_network = wifi->network;
2685 if(reason_code > 0){
2686 DBG("Set disconnect reason code(%d)", reason_code);
2687 connman_network_set_disconnect_reason(network, reason_code);
2690 /* To avoid unnecessary repeated association in wpa_supplicant,
2691 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2692 if (wps != true && wifi->network && wifi->disconnecting == false) {
2693 wifi->disconnecting = true;
2694 err = g_supplicant_interface_disconnect(wifi->interface,
2695 disconnect_callback, wifi->network);
2697 wifi->disconnecting = false;
2699 connman_network_set_connected(network, false);
2700 connman_network_set_associating(network, false);
2702 start_autoscan(device);
2708 connman_network_set_connected(network, false);
2709 connman_network_set_associating(network, false);
2710 wifi->disconnecting = false;
2712 start_autoscan(device);
2716 case G_SUPPLICANT_STATE_INACTIVE:
2717 #if defined TIZEN_EXT
2718 if (handle_wps_completion(interface, network, device, wifi) == false)
2721 connman_network_set_associating(network, false);
2722 start_autoscan(device);
2726 case G_SUPPLICANT_STATE_UNKNOWN:
2727 case G_SUPPLICANT_STATE_DISABLED:
2728 case G_SUPPLICANT_STATE_ASSOCIATED:
2729 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2730 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2734 wifi->state = state;
2736 /* Saving wpa_s state policy:
2737 * If connected and if the state changes are roaming related:
2738 * --> We stay connected
2740 * --> We are connected
2742 * --> We are not connected
2745 #if defined TIZEN_EXT
2746 case G_SUPPLICANT_STATE_SCANNING:
2749 case G_SUPPLICANT_STATE_AUTHENTICATING:
2750 case G_SUPPLICANT_STATE_ASSOCIATING:
2751 case G_SUPPLICANT_STATE_ASSOCIATED:
2752 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2753 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2754 if (wifi->connected)
2755 connman_warn("Probably roaming right now!"
2756 " Staying connected...");
2758 wifi->connected = false;
2760 case G_SUPPLICANT_STATE_COMPLETED:
2761 wifi->connected = true;
2764 wifi->connected = false;
2771 static void interface_removed(GSupplicantInterface *interface)
2773 const char *ifname = g_supplicant_interface_get_ifname(interface);
2774 struct wifi_data *wifi;
2776 DBG("ifname %s", ifname);
2778 wifi = g_supplicant_interface_get_data(interface);
2781 wifi->interface = NULL;
2783 if (wifi && wifi->tethering)
2786 if (!wifi || !wifi->device) {
2787 DBG("wifi interface already removed");
2791 connman_device_set_powered(wifi->device, false);
2793 check_p2p_technology();
2796 static void set_device_type(const char *type, char dev_type[17])
2798 const char *oui = "0050F204";
2799 const char *category = "0100";
2800 const char *sub_category = "0000";
2802 if (!g_strcmp0(type, "handset")) {
2804 sub_category = "0500";
2805 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
2806 sub_category = "0100";
2807 else if (!g_strcmp0(type, "server"))
2808 sub_category = "0200";
2809 else if (!g_strcmp0(type, "laptop"))
2810 sub_category = "0500";
2811 else if (!g_strcmp0(type, "desktop"))
2812 sub_category = "0600";
2813 else if (!g_strcmp0(type, "tablet"))
2814 sub_category = "0900";
2815 else if (!g_strcmp0(type, "watch"))
2818 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
2821 static void p2p_support(GSupplicantInterface *interface)
2823 char dev_type[17] = {};
2824 const char *hostname;
2828 if (!g_supplicant_interface_has_p2p(interface))
2831 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
2832 DBG("Could not register P2P technology driver");
2836 hostname = connman_utsname_get_hostname();
2838 hostname = "ConnMan";
2840 set_device_type(connman_machine_get_type(), dev_type);
2841 g_supplicant_interface_set_p2p_device_config(interface,
2842 hostname, dev_type);
2843 connman_peer_driver_register(&peer_driver);
2846 static void scan_started(GSupplicantInterface *interface)
2851 static void scan_finished(GSupplicantInterface *interface)
2853 #if defined TIZEN_EXT
2854 struct wifi_data *wifi;
2855 bool is_associating = false;
2856 static bool is_scanning = true;
2861 #if defined TIZEN_EXT
2862 wifi = g_supplicant_interface_get_data(interface);
2863 if (wifi && wifi->scan_pending_network) {
2864 network_connect(wifi->scan_pending_network);
2865 wifi->scan_pending_network = NULL;
2868 //service state - associating
2869 if(!wifi || !wifi->network)
2872 is_associating = connman_network_get_associating(wifi->network);
2873 if(is_associating && is_scanning){
2874 is_scanning = false;
2875 DBG("send scan for connecting");
2876 throw_wifi_scan(wifi->device, scan_callback);
2887 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
2889 unsigned char strength;
2891 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
2898 static void network_added(GSupplicantNetwork *supplicant_network)
2900 struct connman_network *network;
2901 GSupplicantInterface *interface;
2902 struct wifi_data *wifi;
2903 const char *name, *identifier, *security, *group, *mode;
2904 const unsigned char *ssid;
2905 unsigned int ssid_len;
2909 bool wps_advertizing;
2911 mode = g_supplicant_network_get_mode(supplicant_network);
2912 identifier = g_supplicant_network_get_identifier(supplicant_network);
2914 DBG("%s", identifier);
2916 if (!g_strcmp0(mode, "adhoc"))
2919 interface = g_supplicant_network_get_interface(supplicant_network);
2920 wifi = g_supplicant_interface_get_data(interface);
2921 name = g_supplicant_network_get_name(supplicant_network);
2922 security = g_supplicant_network_get_security(supplicant_network);
2923 group = g_supplicant_network_get_identifier(supplicant_network);
2924 wps = g_supplicant_network_get_wps(supplicant_network);
2925 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
2926 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
2927 wps_advertizing = g_supplicant_network_is_wps_advertizing(
2928 supplicant_network);
2933 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
2935 network = connman_device_get_network(wifi->device, identifier);
2938 network = connman_network_create(identifier,
2939 CONNMAN_NETWORK_TYPE_WIFI);
2943 connman_network_set_index(network, wifi->index);
2945 if (connman_device_add_network(wifi->device, network) < 0) {
2946 connman_network_unref(network);
2950 wifi->networks = g_slist_prepend(wifi->networks, network);
2953 if (name && name[0] != '\0')
2954 connman_network_set_name(network, name);
2956 connman_network_set_blob(network, "WiFi.SSID",
2958 connman_network_set_string(network, "WiFi.Security", security);
2959 connman_network_set_strength(network,
2960 calculate_strength(supplicant_network));
2961 connman_network_set_bool(network, "WiFi.WPS", wps);
2964 /* Is AP advertizing for WPS association?
2965 * If so, we decide to use WPS by default */
2966 if (wps_ready && wps_pbc &&
2968 #if !defined TIZEN_EXT
2969 connman_network_set_bool(network, "WiFi.UseWPS", true);
2971 DBG("wps is activating by ap but ignore it.");
2976 connman_network_set_frequency(network,
2977 g_supplicant_network_get_frequency(supplicant_network));
2978 #if defined TIZEN_EXT
2979 connman_network_set_bssid(network,
2980 g_supplicant_network_get_bssid(supplicant_network));
2981 connman_network_set_maxrate(network,
2982 g_supplicant_network_get_maxrate(supplicant_network));
2983 connman_network_set_enc_mode(network,
2984 g_supplicant_network_get_enc_mode(supplicant_network));
2985 connman_network_set_rsn_mode(network,
2986 g_supplicant_network_get_rsn_mode(supplicant_network));
2987 connman_network_set_keymgmt(network,
2988 g_supplicant_network_get_keymgmt(supplicant_network));
2990 connman_network_set_available(network, true);
2991 connman_network_set_string(network, "WiFi.Mode", mode);
2993 #if defined TIZEN_EXT
2998 connman_network_set_group(network, group);
3000 #if defined TIZEN_EXT
3001 if (wifi_first_scan == true)
3002 found_with_first_scan = true;
3005 if (wifi->hidden && ssid) {
3006 #if defined TIZEN_EXT
3007 if (network_security(wifi->hidden->security) ==
3008 network_security(security) &&
3010 if (!g_strcmp0(wifi->hidden->security, security) &&
3012 wifi->hidden->ssid_len == ssid_len &&
3013 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3014 connman_network_connect_hidden(network,
3015 wifi->hidden->identity,
3016 wifi->hidden->passphrase,
3017 wifi->hidden->user_data);
3018 wifi->hidden->user_data = NULL;
3019 hidden_free(wifi->hidden);
3020 wifi->hidden = NULL;
3025 static void network_removed(GSupplicantNetwork *network)
3027 GSupplicantInterface *interface;
3028 struct wifi_data *wifi;
3029 const char *name, *identifier;
3030 struct connman_network *connman_network;
3032 interface = g_supplicant_network_get_interface(network);
3033 wifi = g_supplicant_interface_get_data(interface);
3034 identifier = g_supplicant_network_get_identifier(network);
3035 name = g_supplicant_network_get_name(network);
3037 DBG("name %s", name);
3042 connman_network = connman_device_get_network(wifi->device, identifier);
3043 if (!connman_network)
3046 #if defined TIZEN_EXT
3047 if (connman_network == wifi->scan_pending_network)
3048 wifi->scan_pending_network = NULL;
3050 if (connman_network == wifi->pending_network)
3051 wifi->pending_network = NULL;
3053 if(connman_network_get_connecting(connman_network) == true){
3054 connman_network_set_connected(connman_network, false);
3058 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3060 connman_device_remove_network(wifi->device, connman_network);
3061 connman_network_unref(connman_network);
3064 static void network_changed(GSupplicantNetwork *network, const char *property)
3066 GSupplicantInterface *interface;
3067 struct wifi_data *wifi;
3068 const char *name, *identifier;
3069 struct connman_network *connman_network;
3071 #if defined TIZEN_EXT
3072 const unsigned char *bssid;
3073 unsigned int maxrate;
3078 interface = g_supplicant_network_get_interface(network);
3079 wifi = g_supplicant_interface_get_data(interface);
3080 identifier = g_supplicant_network_get_identifier(network);
3081 name = g_supplicant_network_get_name(network);
3083 DBG("name %s", name);
3088 connman_network = connman_device_get_network(wifi->device, identifier);
3089 if (!connman_network)
3092 if (g_str_equal(property, "Signal")) {
3093 connman_network_set_strength(connman_network,
3094 calculate_strength(network));
3095 connman_network_update(connman_network);
3098 #if defined TIZEN_EXT
3099 bssid = g_supplicant_network_get_bssid(network);
3100 maxrate = g_supplicant_network_get_maxrate(network);
3101 frequency = g_supplicant_network_get_frequency(network);
3102 wps = g_supplicant_network_get_wps(network);
3104 connman_network_set_bssid(connman_network, bssid);
3105 connman_network_set_maxrate(connman_network, maxrate);
3106 connman_network_set_frequency(connman_network, frequency);
3107 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3111 static void apply_peer_services(GSupplicantPeer *peer,
3112 struct connman_peer *connman_peer)
3114 const unsigned char *data;
3119 connman_peer_reset_services(connman_peer);
3121 data = g_supplicant_peer_get_widi_ies(peer, &length);
3123 connman_peer_add_service(connman_peer,
3124 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3128 static void add_station(const char *mac)
3130 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3134 static void remove_station(const char *mac)
3136 connman_technology_tethering_remove_station(mac);
3139 static void peer_found(GSupplicantPeer *peer)
3141 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3142 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3143 struct connman_peer *connman_peer;
3144 const char *identifier, *name;
3147 identifier = g_supplicant_peer_get_identifier(peer);
3148 name = g_supplicant_peer_get_name(peer);
3150 DBG("ident: %s", identifier);
3152 connman_peer = connman_peer_get(wifi->device, identifier);
3156 connman_peer = connman_peer_create(identifier);
3157 connman_peer_set_name(connman_peer, name);
3158 connman_peer_set_device(connman_peer, wifi->device);
3159 apply_peer_services(peer, connman_peer);
3161 ret = connman_peer_register(connman_peer);
3162 if (ret < 0 && ret != -EALREADY)
3163 connman_peer_unref(connman_peer);
3166 static void peer_lost(GSupplicantPeer *peer)
3168 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3169 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3170 struct connman_peer *connman_peer;
3171 const char *identifier;
3176 identifier = g_supplicant_peer_get_identifier(peer);
3178 DBG("ident: %s", identifier);
3180 connman_peer = connman_peer_get(wifi->device, identifier);
3182 if (wifi->p2p_connecting &&
3183 wifi->pending_peer == connman_peer) {
3184 peer_connect_timeout(wifi);
3186 connman_peer_unregister(connman_peer);
3187 connman_peer_unref(connman_peer);
3191 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3193 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3194 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3195 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3196 struct connman_peer *connman_peer;
3197 const char *identifier;
3199 identifier = g_supplicant_peer_get_identifier(peer);
3201 DBG("ident: %s", identifier);
3203 connman_peer = connman_peer_get(wifi->device, identifier);
3208 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3209 apply_peer_services(peer, connman_peer);
3210 connman_peer_services_changed(connman_peer);
3212 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3213 if (!g_supplicant_peer_is_in_a_group(peer))
3214 p_state = CONNMAN_PEER_STATE_IDLE;
3216 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3218 case G_SUPPLICANT_PEER_GROUP_STARTED:
3220 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3221 p_state = CONNMAN_PEER_STATE_IDLE;
3223 case G_SUPPLICANT_PEER_GROUP_JOINED:
3224 connman_peer_set_iface_address(connman_peer,
3225 g_supplicant_peer_get_iface_address(peer));
3227 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3228 p_state = CONNMAN_PEER_STATE_IDLE;
3230 case G_SUPPLICANT_PEER_GROUP_FAILED:
3231 if (g_supplicant_peer_has_requested_connection(peer))
3232 p_state = CONNMAN_PEER_STATE_IDLE;
3234 p_state = CONNMAN_PEER_STATE_FAILURE;
3238 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3239 p_state == CONNMAN_PEER_STATE_FAILURE) {
3240 if (wifi->p2p_connecting
3241 && connman_peer == wifi->pending_peer)
3242 peer_cancel_timeout(wifi);
3244 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3247 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3250 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3251 GSupplicantInterface *g_iface;
3252 struct wifi_data *g_wifi;
3254 g_iface = g_supplicant_peer_get_group_interface(peer);
3258 g_wifi = g_supplicant_interface_get_data(g_iface);
3262 connman_peer_set_as_master(connman_peer,
3263 !g_supplicant_peer_is_client(peer));
3264 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3267 connman_peer_set_state(connman_peer, p_state);
3270 static void peer_request(GSupplicantPeer *peer)
3272 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3273 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3274 struct connman_peer *connman_peer;
3275 const char *identifier;
3277 identifier = g_supplicant_peer_get_identifier(peer);
3279 DBG("ident: %s", identifier);
3281 connman_peer = connman_peer_get(wifi->device, identifier);
3285 connman_peer_request_connection(connman_peer);
3288 #if defined TIZEN_EXT
3289 static void system_power_off(void)
3292 struct wifi_data *wifi;
3293 struct connman_service *service;
3294 struct connman_ipconfig *ipconfig_ipv4;
3296 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3297 for (list = iface_list; list; list = list->next) {
3300 if (wifi->network != NULL) {
3301 service = connman_service_lookup_from_network(wifi->network);
3302 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3303 __connman_dhcp_stop(ipconfig_ipv4);
3309 static void network_merged(GSupplicantNetwork *network)
3311 GSupplicantInterface *interface;
3312 GSupplicantState state;
3313 struct wifi_data *wifi;
3314 const char *identifier;
3315 struct connman_network *connman_network;
3316 unsigned int ishs20AP = 0;
3319 interface = g_supplicant_network_get_interface(network);
3323 state = g_supplicant_interface_get_state(interface);
3324 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3327 wifi = g_supplicant_interface_get_data(interface);
3331 identifier = g_supplicant_network_get_identifier(network);
3333 connman_network = connman_device_get_network(wifi->device, identifier);
3334 if (!connman_network)
3337 DBG("merged identifier %s", identifier);
3339 if (wifi->connected == FALSE) {
3341 case G_SUPPLICANT_STATE_AUTHENTICATING:
3342 case G_SUPPLICANT_STATE_ASSOCIATING:
3343 case G_SUPPLICANT_STATE_ASSOCIATED:
3344 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3345 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3346 connman_network_set_associating(connman_network, TRUE);
3348 case G_SUPPLICANT_STATE_COMPLETED:
3349 connman_network_set_connected(connman_network, TRUE);
3352 DBG("Not handled the state : %d", state);
3357 ishs20AP = g_supplicant_network_is_hs20AP(network);
3358 connman_network_set_is_hs20AP(connman_network, ishs20AP);
3361 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3362 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3363 connman_network_set_string(connman_network, "WiFi.EAP",
3365 connman_network_set_string(connman_network, "WiFi.Identity",
3366 g_supplicant_network_get_identity(network));
3367 connman_network_set_string(connman_network, "WiFi.Phase2",
3368 g_supplicant_network_get_phase2(network));
3373 wifi->network = connman_network;
3377 static void debug(const char *str)
3379 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3380 connman_debug("%s", str);
3383 static const GSupplicantCallbacks callbacks = {
3384 .system_ready = system_ready,
3385 .system_killed = system_killed,
3386 .interface_added = interface_added,
3387 .interface_state = interface_state,
3388 .interface_removed = interface_removed,
3389 .p2p_support = p2p_support,
3390 .scan_started = scan_started,
3391 .scan_finished = scan_finished,
3392 .network_added = network_added,
3393 .network_removed = network_removed,
3394 .network_changed = network_changed,
3395 .add_station = add_station,
3396 .remove_station = remove_station,
3397 .peer_found = peer_found,
3398 .peer_lost = peer_lost,
3399 .peer_changed = peer_changed,
3400 .peer_request = peer_request,
3401 #if defined TIZEN_EXT
3402 .system_power_off = system_power_off,
3403 .network_merged = network_merged,
3409 static int tech_probe(struct connman_technology *technology)
3411 wifi_technology = technology;
3416 static void tech_remove(struct connman_technology *technology)
3418 wifi_technology = NULL;
3421 struct wifi_tethering_info {
3422 struct wifi_data *wifi;
3423 struct connman_technology *technology;
3425 GSupplicantSSID *ssid;
3428 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3429 const char *passphrase, bool hidden)
3431 GSupplicantSSID *ap;
3433 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3437 ap->mode = G_SUPPLICANT_MODE_MASTER;
3439 ap->ssid_len = strlen(ssid);
3443 if (!passphrase || strlen(passphrase) == 0) {
3444 ap->security = G_SUPPLICANT_SECURITY_NONE;
3445 ap->passphrase = NULL;
3447 ap->security = G_SUPPLICANT_SECURITY_PSK;
3448 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3449 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3450 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3451 ap->passphrase = passphrase;
3455 ap->ignore_broadcast_ssid =
3456 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3458 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3463 static void ap_start_callback(int result, GSupplicantInterface *interface,
3466 struct wifi_tethering_info *info = user_data;
3468 DBG("result %d index %d bridge %s",
3469 result, info->wifi->index, info->wifi->bridge);
3472 connman_inet_remove_from_bridge(info->wifi->index,
3473 info->wifi->bridge);
3474 connman_technology_tethering_notify(info->technology, false);
3477 g_free(info->ifname);
3481 static void ap_create_callback(int result,
3482 GSupplicantInterface *interface,
3485 struct wifi_tethering_info *info = user_data;
3487 DBG("result %d ifname %s", result,
3488 g_supplicant_interface_get_ifname(interface));
3491 connman_inet_remove_from_bridge(info->wifi->index,
3492 info->wifi->bridge);
3493 connman_technology_tethering_notify(info->technology, false);
3495 g_free(info->ifname);
3501 info->wifi->interface = interface;
3502 g_supplicant_interface_set_data(interface, info->wifi);
3504 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3505 connman_error("Failed to set interface ap_scan property");
3507 g_supplicant_interface_connect(interface, info->ssid,
3508 ap_start_callback, info);
3511 static void sta_remove_callback(int result,
3512 GSupplicantInterface *interface,
3515 struct wifi_tethering_info *info = user_data;
3516 const char *driver = connman_option_get_string("wifi");
3518 DBG("ifname %s result %d ", info->ifname, result);
3521 info->wifi->tethering = true;
3523 g_free(info->ifname);
3529 info->wifi->interface = NULL;
3531 connman_technology_tethering_notify(info->technology, true);
3533 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3538 static int tech_set_tethering(struct connman_technology *technology,
3539 const char *identifier, const char *passphrase,
3540 const char *bridge, bool enabled, bool hidden)
3543 GSupplicantInterface *interface;
3544 struct wifi_data *wifi;
3545 struct wifi_tethering_info *info;
3553 for (list = iface_list; list; list = list->next) {
3556 if (wifi->tethering) {
3557 wifi->tethering = false;
3559 connman_inet_remove_from_bridge(wifi->index,
3561 wifi->bridged = false;
3565 connman_technology_tethering_notify(technology, false);
3570 for (list = iface_list; list; list = list->next) {
3573 interface = wifi->interface;
3578 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3580 mode = g_supplicant_interface_get_mode(interface);
3581 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3582 DBG("%s does not support AP mode", ifname);
3586 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3591 info->technology = technology;
3592 info->wifi->bridge = bridge;
3593 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3598 info->ifname = g_strdup(ifname);
3599 if (!info->ifname) {
3605 info->wifi->tethering = true;
3607 err = g_supplicant_interface_remove(interface,
3608 sta_remove_callback,
3617 static void regdom_callback(int result, const char *alpha2, void *user_data)
3621 if (!wifi_technology)
3627 connman_technology_regdom_notify(wifi_technology, alpha2);
3630 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3632 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3635 static struct connman_technology_driver tech_driver = {
3637 .type = CONNMAN_SERVICE_TYPE_WIFI,
3638 .probe = tech_probe,
3639 .remove = tech_remove,
3640 .set_tethering = tech_set_tethering,
3641 .set_regdom = tech_set_regdom,
3644 static int wifi_init(void)
3648 err = connman_network_driver_register(&network_driver);
3652 err = g_supplicant_register(&callbacks);
3654 connman_network_driver_unregister(&network_driver);
3658 err = connman_technology_driver_register(&tech_driver);
3660 g_supplicant_unregister(&callbacks);
3661 connman_network_driver_unregister(&network_driver);
3668 static void wifi_exit(void)
3672 connman_technology_driver_unregister(&tech_driver);
3674 g_supplicant_unregister(&callbacks);
3676 connman_network_driver_unregister(&network_driver);
3679 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
3680 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)