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 #define ASSOC_STATUS_NO_CLIENT 17
75 #define LOAD_SHAPING_MAX_RETRIES 3
77 static struct connman_technology *wifi_technology = NULL;
78 static struct connman_technology *p2p_technology = NULL;
80 enum wifi_ap_capability{
82 WIFI_AP_SUPPORTED = 1,
83 WIFI_AP_NOT_SUPPORTED = 2,
86 struct hidden_params {
88 unsigned int ssid_len;
90 char *anonymous_identity;
92 char *altsubject_match;
93 char *domain_suffix_match;
97 GSupplicantScanParams *scan_params;
102 * Used for autoscan "emulation".
103 * Should be removed when wpa_s autoscan support will be by default.
105 struct autoscan_params {
109 unsigned int timeout;
112 struct wifi_tethering_info {
113 struct wifi_data *wifi;
114 struct connman_technology *technology;
116 GSupplicantSSID *ssid;
121 struct connman_device *device;
122 struct connman_network *network;
123 struct connman_network *pending_network;
125 GSupplicantInterface *interface;
126 GSupplicantState state;
130 enum wifi_ap_capability ap_supported;
132 bool interface_ready;
138 int load_shaping_retries;
139 struct hidden_params *hidden;
140 bool postpone_hidden;
141 struct wifi_tethering_info *tethering_param;
143 * autoscan "emulation".
145 struct autoscan_params *autoscan;
147 GSupplicantScanParams *scan_params;
148 unsigned int p2p_find_timeout;
149 unsigned int p2p_connection_timeout;
150 struct connman_peer *pending_peer;
155 #if defined TIZEN_EXT
156 int assoc_retry_count;
157 struct connman_network *scan_pending_network;
158 bool allow_full_scan;
164 #if defined TIZEN_EXT
168 #define TIZEN_ASSOC_RETRY_COUNT 4
170 static gboolean wifi_first_scan = false;
171 static gboolean found_with_first_scan = false;
172 static gboolean is_wifi_notifier_registered = false;
176 static GList *iface_list = NULL;
178 static GList *pending_wifi_device = NULL;
179 static GList *p2p_iface_list = NULL;
180 bool wfd_service_registered = false;
182 static void start_autoscan(struct connman_device *device);
184 static int tech_set_tethering(struct connman_technology *technology,
185 const char *identifier, const char *passphrase,
186 const char *bridge, bool enabled);
188 #if defined TIZEN_EXT
189 #define NETCONFIG_SERVICE "net.netconfig"
190 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
191 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
193 struct enc_method_call_data {
194 DBusConnection *connection;
195 struct connman_network *network;
198 static struct enc_method_call_data encrypt_request_data;
200 static void encryption_request_reply(DBusPendingCall *call,
205 DBusMessageIter args;
207 struct connman_service *service;
208 gchar* encrypted_value = NULL;
209 struct connman_network *network = encrypt_request_data.network;
213 reply = dbus_pending_call_steal_reply(call);
215 dbus_error_init(&error);
216 if (dbus_set_error_from_message(&error, reply)) {
217 DBG("send_encryption_request() %s %s", error.name, error.message);
218 dbus_error_free(&error);
222 if (dbus_message_iter_init(reply, &args) == FALSE)
225 dbus_message_iter_get_basic(&args, &out_data);
227 encrypted_value = g_strdup((const gchar *)out_data);
228 service = connman_service_lookup_from_network(network);
231 DBG("encryption result: no service");
235 if (connman_service_get_favorite(service)) {
236 __connman_service_set_passphrase(service, encrypted_value);
237 __connman_service_save(service);
239 connman_network_set_string(network, "WiFi.Passphrase",
242 DBG("encryption result: succeeded");
245 dbus_message_unref(reply);
246 dbus_pending_call_unref(call);
247 dbus_connection_unref(encrypt_request_data.connection);
248 g_free(encrypted_value);
250 encrypt_request_data.connection = NULL;
251 encrypt_request_data.network = NULL;
254 static int send_encryption_request(const char *passphrase,
255 struct connman_network *network)
257 DBusConnection *connection = NULL;
258 DBusMessage *msg = NULL;
259 DBusPendingCall *call;
262 DBG("Invalid parameter");
266 connection = connman_dbus_get_connection();
268 DBG("dbus connection does not exist");
272 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
273 NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
275 dbus_connection_unref(connection);
279 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
282 if (!dbus_connection_send_with_reply(connection, msg,
283 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
284 dbus_message_unref(msg);
285 dbus_connection_unref(connection);
290 dbus_message_unref(msg);
291 dbus_connection_unref(connection);
295 encrypt_request_data.connection = connection;
296 encrypt_request_data.network = network;
298 dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
299 dbus_message_unref(msg);
305 static int p2p_tech_probe(struct connman_technology *technology)
307 p2p_technology = technology;
312 static void p2p_tech_remove(struct connman_technology *technology)
314 p2p_technology = NULL;
317 static struct connman_technology_driver p2p_tech_driver = {
319 .type = CONNMAN_SERVICE_TYPE_P2P,
320 .probe = p2p_tech_probe,
321 .remove = p2p_tech_remove,
324 static bool is_p2p_connecting(void)
328 for (list = iface_list; list; list = list->next) {
329 struct wifi_data *wifi = list->data;
331 if (wifi->p2p_connecting)
338 static void add_pending_wifi_device(struct wifi_data *wifi)
340 if (g_list_find(pending_wifi_device, wifi))
343 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
346 static struct wifi_data *get_pending_wifi_data(const char *ifname)
350 for (list = pending_wifi_device; list; list = list->next) {
351 struct wifi_data *wifi;
352 const char *dev_name;
355 if (!wifi || !wifi->device)
358 dev_name = connman_device_get_string(wifi->device, "Interface");
359 if (!g_strcmp0(ifname, dev_name)) {
360 pending_wifi_device = g_list_delete_link(
361 pending_wifi_device, list);
369 static void remove_pending_wifi_device(struct wifi_data *wifi)
373 link = g_list_find(pending_wifi_device, wifi);
378 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
381 static void peer_cancel_timeout(struct wifi_data *wifi)
383 if (wifi->p2p_connection_timeout > 0)
384 g_source_remove(wifi->p2p_connection_timeout);
386 wifi->p2p_connection_timeout = 0;
387 wifi->p2p_connecting = false;
389 if (wifi->pending_peer) {
390 connman_peer_unref(wifi->pending_peer);
391 wifi->pending_peer = NULL;
395 static gboolean peer_connect_timeout(gpointer data)
397 struct wifi_data *wifi = data;
401 if (wifi->p2p_connecting) {
402 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
403 GSupplicantPeer *gs_peer =
404 g_supplicant_interface_peer_lookup(wifi->interface,
405 connman_peer_get_identifier(wifi->pending_peer));
407 if (g_supplicant_peer_has_requested_connection(gs_peer))
408 state = CONNMAN_PEER_STATE_IDLE;
410 connman_peer_set_state(wifi->pending_peer, state);
413 peer_cancel_timeout(wifi);
418 static void peer_connect_callback(int result, GSupplicantInterface *interface,
421 struct wifi_data *wifi = user_data;
422 struct connman_peer *peer = wifi->pending_peer;
424 DBG("peer %p - %d", peer, result);
430 peer_connect_timeout(wifi);
434 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
436 wifi->p2p_connection_timeout = g_timeout_add_seconds(
437 P2P_CONNECTION_TIMEOUT,
438 peer_connect_timeout, wifi);
441 static int peer_connect(struct connman_peer *peer,
442 enum connman_peer_wps_method wps_method,
445 struct connman_device *device = connman_peer_get_device(peer);
446 GSupplicantPeerParams *peer_params;
447 GSupplicantPeer *gs_peer;
448 struct wifi_data *wifi;
452 DBG("peer %p", peer);
457 wifi = connman_device_get_data(device);
458 if (!wifi || !wifi->interface)
461 if (wifi->p2p_connecting)
464 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
465 connman_peer_get_identifier(peer));
469 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
470 pin = g_supplicant_peer_is_wps_pin(gs_peer);
472 switch (wps_method) {
473 case CONNMAN_PEER_WPS_UNKNOWN:
474 if ((pbc && pin) || pin)
477 case CONNMAN_PEER_WPS_PBC:
482 case CONNMAN_PEER_WPS_PIN:
483 if (!pin || !wps_pin)
488 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
492 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
494 peer_params->wps_pin = g_strdup(wps_pin);
496 peer_params->master = connman_peer_service_is_master();
498 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
499 peer_connect_callback, wifi);
500 if (ret == -EINPROGRESS) {
501 wifi->pending_peer = connman_peer_ref(peer);
502 wifi->p2p_connecting = true;
503 } else if (ret < 0) {
504 g_free(peer_params->path);
505 g_free(peer_params->wps_pin);
512 static int peer_disconnect(struct connman_peer *peer)
514 struct connman_device *device = connman_peer_get_device(peer);
515 GSupplicantPeerParams peer_params = {};
516 GSupplicantPeer *gs_peer;
517 struct wifi_data *wifi;
520 DBG("peer %p", peer);
525 wifi = connman_device_get_data(device);
529 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
530 connman_peer_get_identifier(peer));
534 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
536 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
538 g_free(peer_params.path);
540 if (ret == -EINPROGRESS) {
541 peer_cancel_timeout(wifi);
542 wifi->p2p_device = false;
548 struct peer_service_registration {
549 peer_service_registration_cb_t callback;
553 static bool is_service_wfd(const unsigned char *specs, int length)
555 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
561 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
563 struct wifi_data *wifi = data;
565 if (!wifi->interface ||
566 !g_supplicant_interface_has_p2p(wifi->interface))
569 if (!wifi->servicing) {
570 g_supplicant_interface_p2p_listen(wifi->interface,
571 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
577 static void register_wfd_service_cb(int result,
578 GSupplicantInterface *iface, void *user_data)
580 struct peer_service_registration *reg_data = user_data;
585 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
587 if (reg_data && reg_data->callback) {
588 reg_data->callback(result, reg_data->user_data);
593 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
594 const unsigned char *spec,
595 int spec_length, const unsigned char *query,
596 int query_length, int version)
598 GSupplicantP2PServiceParams *params;
600 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
605 params->version = version;
606 params->service = g_memdup(spec, spec_length);
607 } else if (query_length > 0 && spec_length > 0) {
608 params->query = g_memdup(query, query_length);
609 params->query_length = query_length;
611 params->response = g_memdup(spec, spec_length);
612 params->response_length = spec_length;
614 params->wfd_ies = g_memdup(spec, spec_length);
615 params->wfd_ies_length = spec_length;
621 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
626 g_free(params->service);
627 g_free(params->query);
628 g_free(params->response);
629 g_free(params->wfd_ies);
634 static int peer_register_wfd_service(const unsigned char *specification,
635 int specification_length,
636 peer_service_registration_cb_t callback,
639 struct peer_service_registration *reg_data = NULL;
640 static GSupplicantP2PServiceParams *params;
645 if (wfd_service_registered)
648 params = fill_in_peer_service_params(specification,
649 specification_length, NULL, 0, 0);
653 reg_data = g_try_malloc0(sizeof(*reg_data));
659 reg_data->callback = callback;
660 reg_data->user_data = user_data;
662 ret = g_supplicant_set_widi_ies(params,
663 register_wfd_service_cb, reg_data);
664 if (ret < 0 && ret != -EINPROGRESS)
667 wfd_service_registered = true;
671 free_peer_service_params(params);
677 static void register_peer_service_cb(int result,
678 GSupplicantInterface *iface, void *user_data)
680 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
681 struct peer_service_registration *reg_data = user_data;
683 #if defined TIZEN_EXT
691 apply_p2p_listen_on_iface(wifi, NULL);
693 if (reg_data->callback)
694 reg_data->callback(result, reg_data->user_data);
699 static int peer_register_service(const unsigned char *specification,
700 int specification_length,
701 const unsigned char *query,
702 int query_length, int version,
703 peer_service_registration_cb_t callback,
706 struct peer_service_registration *reg_data;
707 GSupplicantP2PServiceParams *params;
714 if (specification && !version && !query &&
715 is_service_wfd(specification, specification_length)) {
716 return peer_register_wfd_service(specification,
717 specification_length, callback, user_data);
720 reg_data = g_try_malloc0(sizeof(*reg_data));
724 reg_data->callback = callback;
725 reg_data->user_data = user_data;
729 for (list = iface_list; list; list = list->next) {
730 struct wifi_data *wifi = list->data;
731 GSupplicantInterface *iface = wifi->interface;
733 if (!g_supplicant_interface_has_p2p(iface))
736 params = fill_in_peer_service_params(specification,
737 specification_length, query,
738 query_length, version);
745 ret_f = g_supplicant_interface_p2p_add_service(iface,
746 register_peer_service_cb, params, reg_data);
747 if (ret_f == 0 || ret_f == -EINPROGRESS)
751 ret = g_supplicant_interface_p2p_add_service(iface,
752 register_peer_service_cb, params, NULL);
753 if (ret != 0 && ret != -EINPROGRESS)
754 free_peer_service_params(params);
757 if (ret_f != 0 && ret_f != -EINPROGRESS)
763 static int peer_unregister_wfd_service(void)
765 GSupplicantP2PServiceParams *params;
768 if (!wfd_service_registered)
771 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
775 wfd_service_registered = false;
777 g_supplicant_set_widi_ies(params, NULL, NULL);
779 for (list = iface_list; list; list = list->next) {
780 struct wifi_data *wifi = list->data;
782 if (!g_supplicant_interface_has_p2p(wifi->interface))
786 if (!wifi->servicing || wifi->servicing < 0) {
787 g_supplicant_interface_p2p_listen(wifi->interface,
796 static int peer_unregister_service(const unsigned char *specification,
797 int specification_length,
798 const unsigned char *query,
799 int query_length, int version)
801 GSupplicantP2PServiceParams *params;
806 if (specification && !version && !query &&
807 is_service_wfd(specification, specification_length)) {
808 ret = peer_unregister_wfd_service();
809 if (ret != 0 && ret != -EINPROGRESS)
814 for (list = iface_list; list; list = list->next) {
815 struct wifi_data *wifi = list->data;
816 GSupplicantInterface *iface = wifi->interface;
821 if (!g_supplicant_interface_has_p2p(iface))
824 params = fill_in_peer_service_params(specification,
825 specification_length, query,
826 query_length, version);
832 ret = g_supplicant_interface_p2p_del_service(iface, params);
833 if (ret != 0 && ret != -EINPROGRESS)
834 free_peer_service_params(params);
837 if (!wifi->servicing || wifi->servicing < 0) {
838 g_supplicant_interface_p2p_listen(iface, 0, 0);
846 static struct connman_peer_driver peer_driver = {
847 .connect = peer_connect,
848 .disconnect = peer_disconnect,
849 .register_service = peer_register_service,
850 .unregister_service = peer_unregister_service,
853 static void handle_tethering(struct wifi_data *wifi)
855 if (!wifi->tethering)
864 DBG("index %d bridge %s", wifi->index, wifi->bridge);
866 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
869 wifi->bridged = true;
872 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
874 struct connman_device *device = user_data;
875 struct wifi_data *wifi = connman_device_get_data(device);
880 DBG("index %d flags %d change %d", wifi->index, flags, change);
882 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
886 DBG("interface down");
889 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
890 if (flags & IFF_LOWER_UP) {
893 handle_tethering(wifi);
901 static int wifi_probe(struct connman_device *device)
903 struct wifi_data *wifi;
905 DBG("device %p", device);
907 wifi = g_try_new0(struct wifi_data, 1);
911 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
912 wifi->ap_supported = WIFI_AP_UNKNOWN;
913 wifi->tethering_param = NULL;
915 connman_device_set_data(device, wifi);
916 wifi->device = connman_device_ref(device);
918 wifi->index = connman_device_get_index(device);
921 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
922 wifi_newlink, device);
923 if (is_p2p_connecting())
924 add_pending_wifi_device(wifi);
926 iface_list = g_list_append(iface_list, wifi);
931 static void remove_networks(struct connman_device *device,
932 struct wifi_data *wifi)
936 for (list = wifi->networks; list; list = list->next) {
937 struct connman_network *network = list->data;
939 connman_device_remove_network(device, network);
940 connman_network_unref(network);
943 g_slist_free(wifi->networks);
944 wifi->networks = NULL;
947 static void remove_peers(struct wifi_data *wifi)
951 for (list = wifi->peers; list; list = list->next) {
952 struct connman_peer *peer = list->data;
954 connman_peer_unregister(peer);
955 connman_peer_unref(peer);
958 g_slist_free(wifi->peers);
962 static void reset_autoscan(struct connman_device *device)
964 struct wifi_data *wifi = connman_device_get_data(device);
965 struct autoscan_params *autoscan;
969 if (!wifi || !wifi->autoscan)
972 autoscan = wifi->autoscan;
974 if (autoscan->timeout == 0 && autoscan->interval == 0)
977 g_source_remove(autoscan->timeout);
979 autoscan->timeout = 0;
980 autoscan->interval = 0;
982 connman_device_unref(device);
985 static void stop_autoscan(struct connman_device *device)
987 const struct wifi_data *wifi = connman_device_get_data(device);
989 if (!wifi || !wifi->autoscan)
992 reset_autoscan(device);
994 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
997 static void check_p2p_technology(void)
999 bool p2p_exists = false;
1002 for (list = iface_list; list; list = list->next) {
1003 struct wifi_data *w = list->data;
1006 g_supplicant_interface_has_p2p(w->interface))
1011 connman_technology_driver_unregister(&p2p_tech_driver);
1012 connman_peer_driver_unregister(&peer_driver);
1016 static void wifi_remove(struct connman_device *device)
1018 struct wifi_data *wifi = connman_device_get_data(device);
1020 DBG("device %p wifi %p", device, wifi);
1025 stop_autoscan(device);
1027 if (wifi->p2p_device)
1028 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
1030 iface_list = g_list_remove(iface_list, wifi);
1032 check_p2p_technology();
1034 remove_pending_wifi_device(wifi);
1036 if (wifi->p2p_find_timeout) {
1037 g_source_remove(wifi->p2p_find_timeout);
1038 connman_device_unref(wifi->device);
1041 if (wifi->p2p_connection_timeout)
1042 g_source_remove(wifi->p2p_connection_timeout);
1044 remove_networks(device, wifi);
1047 connman_device_set_powered(device, false);
1048 connman_device_set_data(device, NULL);
1049 connman_device_unref(wifi->device);
1050 connman_rtnl_remove_watch(wifi->watch);
1052 g_supplicant_interface_set_data(wifi->interface, NULL);
1054 g_supplicant_interface_cancel(wifi->interface);
1056 if (wifi->scan_params)
1057 g_supplicant_free_scan_params(wifi->scan_params);
1059 g_free(wifi->autoscan);
1060 g_free(wifi->identifier);
1064 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
1068 for (iter = list; iter; iter = g_slist_next(iter)) {
1069 struct scan_ssid *scan_ssid = iter->data;
1071 if (ssid_len == scan_ssid->ssid_len &&
1072 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
1079 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
1080 int freq, GSupplicantScanParams *scan_data,
1081 int driver_max_scan_ssids, char *ssid_name)
1084 struct scan_ssid *scan_ssid;
1086 if ((driver_max_scan_ssids == 0 ||
1087 driver_max_scan_ssids > scan_data->num_ssids) &&
1088 (hex_ssid || raw_ssid)) {
1090 unsigned int j = 0, hex;
1093 size_t hex_ssid_len = strlen(hex_ssid);
1095 ssid = g_try_malloc0(hex_ssid_len / 2);
1099 for (i = 0; i < hex_ssid_len; i += 2) {
1100 sscanf(hex_ssid + i, "%02x", &hex);
1109 * If we have already added hidden AP to the list,
1110 * then do not do it again. This might happen if you have
1111 * used or are using multiple wifi cards, so in that case
1112 * you might have multiple service files for same AP.
1114 if (is_duplicate(scan_data->ssids, ssid, j)) {
1120 scan_ssid = g_try_new(struct scan_ssid, 1);
1127 memcpy(scan_ssid->ssid, ssid, j);
1128 scan_ssid->ssid_len = j;
1129 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1132 scan_data->num_ssids++;
1134 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1135 scan_data->num_ssids);
1142 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1144 if (!scan_data->freqs) {
1145 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1146 if (!scan_data->freqs) {
1147 g_slist_free_full(scan_data->ssids, g_free);
1151 scan_data->num_freqs = 1;
1152 scan_data->freqs[0] = freq;
1154 bool duplicate = false;
1156 /* Don't add duplicate entries */
1157 for (i = 0; i < scan_data->num_freqs; i++) {
1158 if (scan_data->freqs[i] == freq) {
1165 scan_data->num_freqs++;
1166 scan_data->freqs = g_try_realloc(scan_data->freqs,
1167 sizeof(uint16_t) * scan_data->num_freqs);
1168 if (!scan_data->freqs) {
1169 g_slist_free_full(scan_data->ssids, g_free);
1172 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1179 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1181 struct connman_config_entry **entries;
1187 int num_ssids = 0, add_param_failed = 0;
1189 services = connman_storage_get_services();
1190 for (i = 0; services && services[i]; i++) {
1191 if (strncmp(services[i], "wifi_", 5) != 0)
1194 keyfile = connman_storage_load_service(services[i]);
1198 value = g_key_file_get_boolean(keyfile,
1199 services[i], "Hidden", NULL);
1201 g_key_file_free(keyfile);
1205 value = g_key_file_get_boolean(keyfile,
1206 services[i], "Favorite", NULL);
1208 g_key_file_free(keyfile);
1212 #if defined TIZEN_EXT
1213 value = g_key_file_get_boolean(keyfile,
1214 services[i], "AutoConnect", NULL);
1216 g_key_file_free(keyfile);
1221 ssid = g_key_file_get_string(keyfile,
1222 services[i], "SSID", NULL);
1224 name = g_key_file_get_string(keyfile, services[i], "Name",
1227 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1235 g_key_file_free(keyfile);
1239 * Check if there are any hidden AP that needs to be provisioned.
1241 entries = connman_config_get_entries("wifi");
1242 for (i = 0; entries && entries[i]; i++) {
1245 if (!entries[i]->hidden)
1248 if (!entries[i]->ssid) {
1249 ssid = entries[i]->name;
1252 ssid = entries[i]->ssid;
1253 len = entries[i]->ssid_len;
1259 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1266 connman_config_free_entries(entries);
1268 if (add_param_failed > 0)
1269 DBG("Unable to scan %d out of %d SSIDs",
1270 add_param_failed, num_ssids);
1272 g_strfreev(services);
1277 static int get_hidden_connections_params(struct wifi_data *wifi,
1278 GSupplicantScanParams *scan_params)
1280 int driver_max_ssids, i;
1281 GSupplicantScanParams *orig_params;
1284 * Scan hidden networks so that we can autoconnect to them.
1285 * We will assume 1 as a default number of ssid to scan.
1287 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1289 if (driver_max_ssids == 0)
1290 driver_max_ssids = 1;
1292 DBG("max ssids %d", driver_max_ssids);
1294 if (!wifi->scan_params) {
1295 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1296 if (!wifi->scan_params)
1299 if (get_hidden_connections(wifi->scan_params) == 0) {
1300 g_supplicant_free_scan_params(wifi->scan_params);
1301 wifi->scan_params = NULL;
1307 orig_params = wifi->scan_params;
1309 /* Let's transfer driver_max_ssids params */
1310 for (i = 0; i < driver_max_ssids; i++) {
1311 struct scan_ssid *ssid;
1313 if (!wifi->scan_params->ssids)
1316 ssid = orig_params->ssids->data;
1317 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1318 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1322 scan_params->num_ssids = i;
1323 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1325 scan_params->freqs = g_memdup(orig_params->freqs,
1326 sizeof(uint16_t) * orig_params->num_freqs);
1327 if (!scan_params->freqs)
1330 scan_params->num_freqs = orig_params->num_freqs;
1335 orig_params->num_ssids -= scan_params->num_ssids;
1337 return scan_params->num_ssids;
1340 g_slist_free_full(scan_params->ssids, g_free);
1341 g_supplicant_free_scan_params(wifi->scan_params);
1342 wifi->scan_params = NULL;
1347 static int throw_wifi_scan(struct connman_device *device,
1348 GSupplicantInterfaceCallback callback)
1350 struct wifi_data *wifi = connman_device_get_data(device);
1356 DBG("device %p %p", device, wifi->interface);
1358 if (wifi->tethering)
1360 #if defined TIZEN_EXT
1361 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1363 if (connman_device_get_scanning(device))
1367 connman_device_ref(device);
1369 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1372 connman_device_set_scanning(device,
1373 CONNMAN_SERVICE_TYPE_WIFI, true);
1375 connman_device_unref(device);
1380 static void hidden_free(struct hidden_params *hidden)
1385 if (hidden->scan_params)
1386 g_supplicant_free_scan_params(hidden->scan_params);
1387 g_free(hidden->identity);
1388 g_free(hidden->passphrase);
1389 g_free(hidden->security);
1393 #if defined TIZEN_EXT
1394 static void service_state_changed(struct connman_service *service,
1395 enum connman_service_state state);
1397 static int network_connect(struct connman_network *network);
1399 static struct connman_notifier notifier = {
1401 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1402 .service_state_changed = service_state_changed,
1405 static void service_state_changed(struct connman_service *service,
1406 enum connman_service_state state)
1408 enum connman_service_type type;
1410 type = connman_service_get_type(service);
1411 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1414 DBG("service %p state %d", service, state);
1417 case CONNMAN_SERVICE_STATE_READY:
1418 case CONNMAN_SERVICE_STATE_ONLINE:
1419 case CONNMAN_SERVICE_STATE_FAILURE:
1420 connman_notifier_unregister(¬ifier);
1421 is_wifi_notifier_registered = FALSE;
1423 __connman_device_request_scan(type);
1432 static void scan_callback(int result, GSupplicantInterface *interface,
1435 struct connman_device *device = user_data;
1436 struct wifi_data *wifi = connman_device_get_data(device);
1439 DBG("result %d wifi %p", result, wifi);
1442 if (wifi->hidden && !wifi->postpone_hidden) {
1443 connman_network_clear_hidden(wifi->hidden->user_data);
1444 hidden_free(wifi->hidden);
1445 wifi->hidden = NULL;
1448 if (wifi->scan_params) {
1449 g_supplicant_free_scan_params(wifi->scan_params);
1450 wifi->scan_params = NULL;
1455 connman_device_reset_scanning(device);
1457 /* User is connecting to a hidden AP, let's wait for finished event */
1458 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1459 GSupplicantScanParams *scan_params;
1462 wifi->postpone_hidden = false;
1463 scan_params = wifi->hidden->scan_params;
1464 wifi->hidden->scan_params = NULL;
1466 reset_autoscan(device);
1468 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1469 scan_callback, device);
1473 /* On error, let's recall scan_callback, which will cleanup */
1474 return scan_callback(ret, interface, user_data);
1477 #if defined TIZEN_EXT
1478 if (wifi && wifi->allow_full_scan) {
1480 DBG("Trigger Full Channel Scan");
1481 wifi->allow_full_scan = FALSE;
1483 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1484 scan_callback, device);
1488 /* On error, let's recall scan_callback, which will cleanup */
1489 return scan_callback(ret, interface, user_data);
1493 scanning = connman_device_get_scanning(device);
1495 connman_device_set_scanning(device,
1496 CONNMAN_SERVICE_TYPE_WIFI, false);
1498 if (result != -ENOLINK)
1499 #if defined TIZEN_EXT
1502 start_autoscan(device);
1505 * If we are here then we were scanning; however, if we are
1506 * also mid-flight disabling the interface, then wifi_disable
1507 * has already cleared the device scanning state and
1508 * unreferenced the device, obviating the need to do it here.
1512 connman_device_unref(device);
1514 #if defined TIZEN_EXT
1515 if (wifi && wifi->scan_pending_network && result != -EIO) {
1516 network_connect(wifi->scan_pending_network);
1517 wifi->scan_pending_network = NULL;
1518 connman_network_set_connecting(wifi->network);
1521 if (is_wifi_notifier_registered != true &&
1522 wifi_first_scan == true && found_with_first_scan == true) {
1523 wifi_first_scan = false;
1524 found_with_first_scan = false;
1526 connman_notifier_register(¬ifier);
1527 is_wifi_notifier_registered = true;
1532 static void scan_callback_hidden(int result,
1533 GSupplicantInterface *interface, void *user_data)
1535 struct connman_device *device = user_data;
1536 struct wifi_data *wifi = connman_device_get_data(device);
1537 GSupplicantScanParams *scan_params;
1540 DBG("result %d wifi %p", result, wifi);
1545 /* User is trying to connect to a hidden AP */
1546 if (wifi->hidden && wifi->postpone_hidden)
1549 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1553 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1554 ret = g_supplicant_interface_scan(wifi->interface,
1556 scan_callback_hidden,
1562 g_supplicant_free_scan_params(scan_params);
1565 scan_callback(result, interface, user_data);
1568 static gboolean autoscan_timeout(gpointer data)
1570 struct connman_device *device = data;
1571 struct wifi_data *wifi = connman_device_get_data(device);
1572 struct autoscan_params *autoscan;
1578 autoscan = wifi->autoscan;
1580 if (autoscan->interval <= 0) {
1581 interval = autoscan->base;
1584 interval = autoscan->interval * autoscan->base;
1586 #if defined TIZEN_EXT
1587 if (autoscan->interval >= autoscan->limit)
1589 if (interval > autoscan->limit)
1591 interval = autoscan->limit;
1593 throw_wifi_scan(wifi->device, scan_callback_hidden);
1596 DBG("interval %d", interval);
1598 autoscan->interval = interval;
1600 autoscan->timeout = g_timeout_add_seconds(interval,
1601 autoscan_timeout, device);
1606 static void start_autoscan(struct connman_device *device)
1608 struct wifi_data *wifi = connman_device_get_data(device);
1609 struct autoscan_params *autoscan;
1616 if (wifi->p2p_device)
1619 if (wifi->connected)
1622 autoscan = wifi->autoscan;
1626 if (autoscan->timeout > 0 || autoscan->interval > 0)
1629 connman_device_ref(device);
1631 autoscan_timeout(device);
1634 static struct autoscan_params *parse_autoscan_params(const char *params)
1636 struct autoscan_params *autoscan;
1641 DBG("Emulating autoscan");
1643 list_params = g_strsplit(params, ":", 0);
1644 if (list_params == 0)
1647 if (g_strv_length(list_params) < 3) {
1648 g_strfreev(list_params);
1652 base = atoi(list_params[1]);
1653 limit = atoi(list_params[2]);
1655 g_strfreev(list_params);
1657 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1659 DBG("Could not allocate memory for autoscan");
1663 DBG("base %d - limit %d", base, limit);
1664 autoscan->base = base;
1665 autoscan->limit = limit;
1670 static void setup_autoscan(struct wifi_data *wifi)
1672 if (!wifi->autoscan)
1673 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1675 start_autoscan(wifi->device);
1678 static void finalize_interface_creation(struct wifi_data *wifi)
1680 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1682 if (!wifi->device) {
1683 connman_error("WiFi device not set");
1687 connman_device_set_powered(wifi->device, true);
1689 if (!connman_setting_get_bool("BackgroundScanning"))
1692 if (wifi->p2p_device)
1695 setup_autoscan(wifi);
1698 static void interface_create_callback(int result,
1699 GSupplicantInterface *interface,
1702 struct wifi_data *wifi = user_data;
1704 DBG("result %d ifname %s, wifi %p", result,
1705 g_supplicant_interface_get_ifname(interface),
1708 if (result < 0 || !wifi)
1711 wifi->interface = interface;
1712 g_supplicant_interface_set_data(interface, wifi);
1714 if (g_supplicant_interface_get_ready(interface)) {
1715 wifi->interface_ready = true;
1716 finalize_interface_creation(wifi);
1720 static int wifi_enable(struct connman_device *device)
1722 struct wifi_data *wifi = connman_device_get_data(device);
1725 const char *driver = connman_option_get_string("wifi");
1728 DBG("device %p %p", device, wifi);
1730 index = connman_device_get_index(device);
1731 if (!wifi || index < 0)
1734 if (is_p2p_connecting())
1735 return -EINPROGRESS;
1737 interface = connman_inet_ifname(index);
1738 ret = g_supplicant_interface_create(interface, driver, NULL,
1739 interface_create_callback,
1746 return -EINPROGRESS;
1749 static int wifi_disable(struct connman_device *device)
1751 struct wifi_data *wifi = connman_device_get_data(device);
1754 DBG("device %p wifi %p", device, wifi);
1759 wifi->connected = false;
1760 wifi->disconnecting = false;
1762 if (wifi->pending_network)
1763 wifi->pending_network = NULL;
1765 stop_autoscan(device);
1767 if (wifi->p2p_find_timeout) {
1768 g_source_remove(wifi->p2p_find_timeout);
1769 wifi->p2p_find_timeout = 0;
1770 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1771 connman_device_unref(wifi->device);
1774 /* In case of a user scan, device is still referenced */
1775 if (connman_device_get_scanning(device)) {
1776 connman_device_set_scanning(device,
1777 CONNMAN_SERVICE_TYPE_WIFI, false);
1778 connman_device_unref(wifi->device);
1781 remove_networks(device, wifi);
1784 #if defined TIZEN_EXT
1785 wifi->scan_pending_network = NULL;
1787 if (is_wifi_notifier_registered == true) {
1788 connman_notifier_unregister(¬ifier);
1789 is_wifi_notifier_registered = false;
1793 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1797 return -EINPROGRESS;
1800 struct last_connected {
1806 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1808 GTimeVal *aval = (GTimeVal *)a;
1809 GTimeVal *bval = (GTimeVal *)b;
1811 /* Note that the sort order is descending */
1812 if (aval->tv_sec < bval->tv_sec)
1815 if (aval->tv_sec > bval->tv_sec)
1821 static void free_entry(gpointer data)
1823 struct last_connected *entry = data;
1825 g_free(entry->ssid);
1829 static int get_latest_connections(int max_ssids,
1830 GSupplicantScanParams *scan_data)
1832 GSequenceIter *iter;
1833 GSequence *latest_list;
1834 struct last_connected *entry;
1843 latest_list = g_sequence_new(free_entry);
1847 services = connman_storage_get_services();
1848 for (i = 0; services && services[i]; i++) {
1849 if (strncmp(services[i], "wifi_", 5) != 0)
1852 keyfile = connman_storage_load_service(services[i]);
1856 str = g_key_file_get_string(keyfile,
1857 services[i], "Favorite", NULL);
1858 if (!str || g_strcmp0(str, "true")) {
1860 g_key_file_free(keyfile);
1865 str = g_key_file_get_string(keyfile,
1866 services[i], "AutoConnect", NULL);
1867 if (!str || g_strcmp0(str, "true")) {
1869 g_key_file_free(keyfile);
1874 str = g_key_file_get_string(keyfile,
1875 services[i], "Modified", NULL);
1877 g_key_file_free(keyfile);
1880 g_time_val_from_iso8601(str, &modified);
1883 ssid = g_key_file_get_string(keyfile,
1884 services[i], "SSID", NULL);
1886 freq = g_key_file_get_integer(keyfile, services[i],
1889 entry = g_try_new(struct last_connected, 1);
1891 g_sequence_free(latest_list);
1892 g_key_file_free(keyfile);
1898 entry->modified = modified;
1901 g_sequence_insert_sorted(latest_list, entry,
1907 g_key_file_free(keyfile);
1910 g_strfreev(services);
1912 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1914 iter = g_sequence_get_begin_iter(latest_list);
1916 for (i = 0; i < num_ssids; i++) {
1917 entry = g_sequence_get(iter);
1919 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1920 entry->modified.tv_sec);
1922 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1923 max_ssids, entry->ssid);
1925 iter = g_sequence_iter_next(iter);
1928 g_sequence_free(latest_list);
1932 static int wifi_scan_simple(struct connman_device *device)
1934 reset_autoscan(device);
1936 return throw_wifi_scan(device, scan_callback_hidden);
1939 static gboolean p2p_find_stop(gpointer data)
1941 struct connman_device *device = data;
1942 struct wifi_data *wifi = connman_device_get_data(device);
1947 wifi->p2p_find_timeout = 0;
1949 g_supplicant_interface_p2p_stop_find(wifi->interface);
1952 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1954 connman_device_unref(device);
1955 reset_autoscan(device);
1960 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1963 struct connman_device *device = user_data;
1964 struct wifi_data *wifi = connman_device_get_data(device);
1966 DBG("result %d wifi %p", result, wifi);
1971 if (wifi->p2p_find_timeout) {
1972 g_source_remove(wifi->p2p_find_timeout);
1973 wifi->p2p_find_timeout = 0;
1979 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1980 p2p_find_stop, device);
1981 if (!wifi->p2p_find_timeout)
1986 p2p_find_stop(device);
1989 static int p2p_find(struct connman_device *device)
1991 struct wifi_data *wifi;
1996 if (!p2p_technology)
1999 wifi = connman_device_get_data(device);
2001 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
2004 reset_autoscan(device);
2005 connman_device_ref(device);
2007 ret = g_supplicant_interface_p2p_find(wifi->interface,
2008 p2p_find_callback, device);
2010 connman_device_unref(device);
2011 start_autoscan(device);
2013 connman_device_set_scanning(device,
2014 CONNMAN_SERVICE_TYPE_P2P, true);
2020 #if defined TIZEN_EXT
2021 static void specific_scan_callback(int result, GSupplicantInterface *interface,
2024 struct connman_device *device = user_data;
2025 struct wifi_data *wifi = connman_device_get_data(device);
2028 DBG("result %d wifi %p", result, wifi);
2030 if (wifi && wifi->scan_params) {
2031 g_supplicant_free_scan_params(wifi->scan_params);
2032 wifi->scan_params = NULL;
2035 scanning = connman_device_get_scanning(device);
2037 connman_device_set_scanning(device,
2038 CONNMAN_SERVICE_TYPE_WIFI, false);
2039 connman_device_unref(device);
2043 static int wifi_specific_scan(enum connman_service_type type,
2044 struct connman_device *device, int scan_type,
2045 GSList *specific_scan_list, void *user_data)
2047 GSList *list = NULL;
2049 struct wifi_data *wifi = connman_device_get_data(device);
2050 GSupplicantScanParams *scan_params = NULL;
2051 struct scan_ssid *scan_ssid = NULL;
2060 if (wifi->p2p_device)
2063 if (type == CONNMAN_SERVICE_TYPE_P2P)
2064 return p2p_find(device);
2066 if (wifi->tethering)
2069 scanning = connman_device_get_scanning(device);
2073 DBG("scan_type: %d", scan_type);
2074 if (scan_type == 1) { /* ssid based scan */
2075 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2077 DBG("Failed to allocate memory.");
2081 for (list = specific_scan_list; list; list = list->next) {
2082 ssid = (char *)list->data;
2083 int ssid_len = strlen(ssid);
2085 scan_ssid = g_try_new0(struct scan_ssid, 1);
2087 DBG("Failed to allocate memory.");
2088 g_supplicant_free_scan_params(scan_params);
2092 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
2093 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
2094 scan_ssid->ssid_len = ssid_len;
2095 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
2098 scan_params->num_ssids = count;
2100 } else if (scan_type == 2) { /* frequency based scan */
2102 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2104 DBG("Failed to allocate memory.");
2108 guint num_freqs = g_slist_length(specific_scan_list);
2109 DBG("num_freqs: %d", num_freqs);
2111 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2112 if (!scan_params->freqs) {
2113 DBG("Failed to allocate memory.");
2114 g_free(scan_params);
2119 for (list = specific_scan_list; list; list = list->next) {
2120 freq = (int)list->data;
2122 scan_params->freqs[count] = freq;
2123 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2126 scan_params->num_freqs = count;
2129 DBG("Invalid scan");
2133 reset_autoscan(device);
2134 connman_device_ref(device);
2136 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2137 specific_scan_callback, device);
2140 connman_device_set_scanning(device,
2141 CONNMAN_SERVICE_TYPE_WIFI, true);
2143 g_supplicant_free_scan_params(scan_params);
2144 connman_device_unref(device);
2152 * Note that the hidden scan is only used when connecting to this specific
2153 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2155 static int wifi_scan(enum connman_service_type type,
2156 struct connman_device *device,
2157 const char *ssid, unsigned int ssid_len,
2158 const char *identity, const char* passphrase,
2159 const char *security, void *user_data)
2161 struct wifi_data *wifi = connman_device_get_data(device);
2162 GSupplicantScanParams *scan_params = NULL;
2163 struct scan_ssid *scan_ssid;
2164 struct hidden_params *hidden;
2166 int driver_max_ssids = 0;
2173 if (wifi->p2p_device)
2176 if (wifi->tethering)
2179 if (type == CONNMAN_SERVICE_TYPE_P2P)
2180 return p2p_find(device);
2182 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2184 scanning = connman_device_get_scanning(device);
2186 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2190 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2192 DBG("max ssids %d", driver_max_ssids);
2193 if (driver_max_ssids == 0)
2194 return wifi_scan_simple(device);
2198 if (scanning && wifi->hidden && wifi->postpone_hidden)
2204 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2209 scan_ssid = g_try_new(struct scan_ssid, 1);
2211 g_free(scan_params);
2215 memcpy(scan_ssid->ssid, ssid, ssid_len);
2216 scan_ssid->ssid_len = ssid_len;
2217 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2219 scan_params->num_ssids = 1;
2221 hidden = g_try_new0(struct hidden_params, 1);
2223 g_supplicant_free_scan_params(scan_params);
2228 hidden_free(wifi->hidden);
2229 wifi->hidden = NULL;
2232 memcpy(hidden->ssid, ssid, ssid_len);
2233 hidden->ssid_len = ssid_len;
2234 hidden->identity = g_strdup(identity);
2235 hidden->passphrase = g_strdup(passphrase);
2236 hidden->security = g_strdup(security);
2237 hidden->user_data = user_data;
2238 wifi->hidden = hidden;
2241 /* Let's keep this active scan for later,
2242 * when current scan will be over. */
2243 wifi->postpone_hidden = TRUE;
2244 hidden->scan_params = scan_params;
2248 } else if (wifi->connected) {
2249 g_supplicant_free_scan_params(scan_params);
2250 return wifi_scan_simple(device);
2252 ret = get_latest_connections(driver_max_ssids, scan_params);
2254 g_supplicant_free_scan_params(scan_params);
2255 return wifi_scan_simple(device);
2259 connman_device_ref(device);
2261 reset_autoscan(device);
2263 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2264 scan_callback, device);
2267 connman_device_set_scanning(device,
2268 CONNMAN_SERVICE_TYPE_WIFI, true);
2269 #if defined TIZEN_EXT
2270 /*To allow the Full Scan after ssid based scan, set the flag here
2271 It is required because Tizen does not use the ConnMan specific
2272 backgroung Scan feature.Tizen has added the BG Scan feature in
2273 net-config. To sync with up ConnMan, we need to issue the Full Scan
2274 after SSID specific scan.*/
2275 wifi->allow_full_scan = TRUE;
2278 g_supplicant_free_scan_params(scan_params);
2279 connman_device_unref(device);
2282 hidden_free(wifi->hidden);
2283 wifi->hidden = NULL;
2290 static void wifi_regdom_callback(int result,
2294 struct connman_device *device = user_data;
2296 connman_device_regdom_notify(device, result, alpha2);
2298 connman_device_unref(device);
2301 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2303 struct wifi_data *wifi = connman_device_get_data(device);
2309 connman_device_ref(device);
2311 ret = g_supplicant_interface_set_country(wifi->interface,
2312 wifi_regdom_callback,
2315 connman_device_unref(device);
2320 static struct connman_device_driver wifi_ng_driver = {
2322 .type = CONNMAN_DEVICE_TYPE_WIFI,
2323 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2324 .probe = wifi_probe,
2325 .remove = wifi_remove,
2326 .enable = wifi_enable,
2327 .disable = wifi_disable,
2329 .set_regdom = wifi_set_regdom,
2330 #if defined TIZEN_EXT
2331 .specific_scan = wifi_specific_scan,
2335 static void system_ready(void)
2339 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2340 connman_error("Failed to register WiFi driver");
2343 static void system_killed(void)
2347 connman_device_driver_unregister(&wifi_ng_driver);
2350 static int network_probe(struct connman_network *network)
2352 DBG("network %p", network);
2357 static void network_remove(struct connman_network *network)
2359 struct connman_device *device = connman_network_get_device(network);
2360 struct wifi_data *wifi;
2362 DBG("network %p", network);
2364 wifi = connman_device_get_data(device);
2368 if (wifi->network != network)
2371 wifi->network = NULL;
2373 #if defined TIZEN_EXT
2374 wifi->disconnecting = false;
2376 if (wifi->pending_network == network)
2377 wifi->pending_network = NULL;
2379 if (wifi->scan_pending_network == network)
2380 wifi->scan_pending_network = NULL;
2384 static void connect_callback(int result, GSupplicantInterface *interface,
2387 #if defined TIZEN_EXT
2389 struct wifi_data *wifi;
2391 struct connman_network *network = user_data;
2393 DBG("network %p result %d", network, result);
2395 #if defined TIZEN_EXT
2396 set_connman_bssid(RESET_BSSID, NULL);
2398 for (list = iface_list; list; list = list->next) {
2401 if (wifi && wifi->network == network)
2405 /* wifi_data may be invalid because wifi is already disabled */
2410 if (result == -ENOKEY) {
2411 connman_network_set_error(network,
2412 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2413 } else if (result < 0) {
2414 connman_network_set_error(network,
2415 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2418 connman_network_unref(network);
2421 static GSupplicantSecurity network_security(const char *security)
2423 if (g_str_equal(security, "none"))
2424 return G_SUPPLICANT_SECURITY_NONE;
2425 else if (g_str_equal(security, "wep"))
2426 return G_SUPPLICANT_SECURITY_WEP;
2427 else if (g_str_equal(security, "psk"))
2428 return G_SUPPLICANT_SECURITY_PSK;
2429 else if (g_str_equal(security, "wpa"))
2430 return G_SUPPLICANT_SECURITY_PSK;
2431 else if (g_str_equal(security, "rsn"))
2432 return G_SUPPLICANT_SECURITY_PSK;
2433 else if (g_str_equal(security, "ieee8021x"))
2434 return G_SUPPLICANT_SECURITY_IEEE8021X;
2435 #if defined TIZEN_EXT
2436 else if (g_str_equal(security, "ft_psk") == TRUE)
2437 return G_SUPPLICANT_SECURITY_FT_PSK;
2438 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2439 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2442 return G_SUPPLICANT_SECURITY_UNKNOWN;
2445 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2447 const char *security;
2449 memset(ssid, 0, sizeof(*ssid));
2450 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2451 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2453 ssid->scan_ssid = 1;
2454 security = connman_network_get_string(network, "WiFi.Security");
2455 ssid->security = network_security(security);
2456 ssid->passphrase = connman_network_get_string(network,
2458 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2461 * If our private key password is unset,
2462 * we use the supplied passphrase. That is needed
2463 * for PEAP where 2 passphrases (identity and client
2464 * cert may have to be provided.
2466 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2467 connman_network_set_string(network,
2468 "WiFi.PrivateKeyPassphrase",
2470 /* We must have an identity for both PEAP and TLS */
2471 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2473 /* Use agent provided identity as a fallback */
2474 if (!ssid->identity || strlen(ssid->identity) == 0)
2475 ssid->identity = connman_network_get_string(network,
2476 "WiFi.AgentIdentity");
2478 ssid->anonymous_identity = connman_network_get_string(network,
2479 "WiFi.AnonymousIdentity");
2480 ssid->ca_cert_path = connman_network_get_string(network,
2482 ssid->subject_match = connman_network_get_string(network,
2483 "WiFi.SubjectMatch");
2484 ssid->altsubject_match = connman_network_get_string(network,
2485 "WiFi.AltSubjectMatch");
2486 ssid->domain_suffix_match = connman_network_get_string(network,
2487 "WiFi.DomainSuffixMatch");
2488 ssid->domain_match = connman_network_get_string(network,
2489 "WiFi.DomainMatch");
2490 ssid->client_cert_path = connman_network_get_string(network,
2491 "WiFi.ClientCertFile");
2492 ssid->private_key_path = connman_network_get_string(network,
2493 "WiFi.PrivateKeyFile");
2494 ssid->private_key_passphrase = connman_network_get_string(network,
2495 "WiFi.PrivateKeyPassphrase");
2496 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2498 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2499 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2501 #if defined TIZEN_EXT
2502 ssid->bssid = connman_network_get_bssid(network);
2504 #if defined TIZEN_EXT
2505 if (set_connman_bssid(CHECK_BSSID, NULL) == 6) {
2506 ssid->bssid_for_connect_len = 6;
2507 set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect);
2508 DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
2509 ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
2510 ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
2511 ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
2513 ssid->freq = connman_network_get_frequency(network);
2517 if (connman_setting_get_bool("BackgroundScanning"))
2518 ssid->bgscan = BGSCAN_DEFAULT;
2521 static int network_connect(struct connman_network *network)
2523 struct connman_device *device = connman_network_get_device(network);
2524 struct wifi_data *wifi;
2525 GSupplicantInterface *interface;
2526 GSupplicantSSID *ssid;
2528 DBG("network %p", network);
2533 wifi = connman_device_get_data(device);
2537 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2541 interface = wifi->interface;
2543 ssid_init(ssid, network);
2545 if (wifi->disconnecting) {
2546 wifi->pending_network = network;
2549 wifi->network = connman_network_ref(network);
2551 #if defined TIZEN_EXT
2552 wifi->scan_pending_network = NULL;
2555 return g_supplicant_interface_connect(interface, ssid,
2556 connect_callback, network);
2559 return -EINPROGRESS;
2562 static void disconnect_callback(int result, GSupplicantInterface *interface,
2565 #if defined TIZEN_EXT
2567 struct wifi_data *wifi;
2568 struct connman_network *network = user_data;
2570 DBG("network %p result %d", network, result);
2572 for (list = iface_list; list; list = list->next) {
2575 if (wifi->network == NULL && wifi->disconnecting == true)
2576 wifi->disconnecting = false;
2578 if (wifi->network == network)
2582 /* wifi_data may be invalid because wifi is already disabled */
2587 struct wifi_data *wifi = user_data;
2590 DBG("result %d supplicant interface %p wifi %p",
2591 result, interface, wifi);
2593 if (result == -ECONNABORTED) {
2594 DBG("wifi interface no longer available");
2598 if (wifi->network) {
2599 connman_network_set_connected(wifi->network, false);
2600 wifi->network = NULL;
2603 wifi->disconnecting = false;
2604 wifi->connected = false;
2606 if (wifi->pending_network) {
2607 network_connect(wifi->pending_network);
2608 wifi->pending_network = NULL;
2611 start_autoscan(wifi->device);
2614 static int network_disconnect(struct connman_network *network)
2616 struct connman_device *device = connman_network_get_device(network);
2617 struct wifi_data *wifi;
2619 #if defined TIZEN_EXT
2620 struct connman_service *service;
2623 DBG("network %p", network);
2625 wifi = connman_device_get_data(device);
2626 if (!wifi || !wifi->interface)
2629 #if defined TIZEN_EXT
2630 if (connman_network_get_associating(network) == true) {
2631 connman_network_clear_associating(network);
2632 connman_network_set_bool(network, "WiFi.UseWPS", false);
2634 service = connman_service_lookup_from_network(network);
2636 if (service != NULL &&
2637 (__connman_service_is_connected_state(service,
2638 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2639 __connman_service_is_connected_state(service,
2640 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2641 (connman_service_get_favorite(service) == false))
2642 __connman_service_set_passphrase(service, NULL);
2645 if (wifi->pending_network == network)
2646 wifi->pending_network = NULL;
2648 if (wifi->scan_pending_network == network)
2649 wifi->scan_pending_network = NULL;
2652 connman_network_set_associating(network, false);
2654 if (wifi->disconnecting)
2657 wifi->disconnecting = true;
2659 #if defined TIZEN_EXT
2660 err = g_supplicant_interface_disconnect(wifi->interface,
2661 disconnect_callback, network);
2663 err = g_supplicant_interface_disconnect(wifi->interface,
2664 disconnect_callback, wifi);
2668 wifi->disconnecting = false;
2673 static struct connman_network_driver network_driver = {
2675 .type = CONNMAN_NETWORK_TYPE_WIFI,
2676 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2677 .probe = network_probe,
2678 .remove = network_remove,
2679 .connect = network_connect,
2680 .disconnect = network_disconnect,
2683 static void interface_added(GSupplicantInterface *interface)
2685 const char *ifname = g_supplicant_interface_get_ifname(interface);
2686 const char *driver = g_supplicant_interface_get_driver(interface);
2687 struct wifi_data *wifi;
2689 wifi = g_supplicant_interface_get_data(interface);
2691 wifi = get_pending_wifi_data(ifname);
2695 wifi->interface = interface;
2696 g_supplicant_interface_set_data(interface, wifi);
2697 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2698 wifi->p2p_device = true;
2701 DBG("ifname %s driver %s wifi %p tethering %d",
2702 ifname, driver, wifi, wifi->tethering);
2704 if (!wifi->device) {
2705 connman_error("WiFi device not set");
2709 connman_device_set_powered(wifi->device, true);
2712 static bool is_idle(struct wifi_data *wifi)
2714 DBG("state %d", wifi->state);
2716 switch (wifi->state) {
2717 case G_SUPPLICANT_STATE_UNKNOWN:
2718 case G_SUPPLICANT_STATE_DISABLED:
2719 case G_SUPPLICANT_STATE_DISCONNECTED:
2720 case G_SUPPLICANT_STATE_INACTIVE:
2721 case G_SUPPLICANT_STATE_SCANNING:
2724 case G_SUPPLICANT_STATE_AUTHENTICATING:
2725 case G_SUPPLICANT_STATE_ASSOCIATING:
2726 case G_SUPPLICANT_STATE_ASSOCIATED:
2727 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2728 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2729 case G_SUPPLICANT_STATE_COMPLETED:
2736 static bool is_idle_wps(GSupplicantInterface *interface,
2737 struct wifi_data *wifi)
2739 /* First, let's check if WPS processing did not went wrong */
2740 if (g_supplicant_interface_get_wps_state(interface) ==
2741 G_SUPPLICANT_WPS_STATE_FAIL)
2744 /* Unlike normal connection, being associated while processing wps
2745 * actually means that we are idling. */
2746 switch (wifi->state) {
2747 case G_SUPPLICANT_STATE_UNKNOWN:
2748 case G_SUPPLICANT_STATE_DISABLED:
2749 case G_SUPPLICANT_STATE_DISCONNECTED:
2750 case G_SUPPLICANT_STATE_INACTIVE:
2751 case G_SUPPLICANT_STATE_SCANNING:
2752 case G_SUPPLICANT_STATE_ASSOCIATED:
2754 case G_SUPPLICANT_STATE_AUTHENTICATING:
2755 case G_SUPPLICANT_STATE_ASSOCIATING:
2756 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2757 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2758 case G_SUPPLICANT_STATE_COMPLETED:
2765 static bool handle_wps_completion(GSupplicantInterface *interface,
2766 struct connman_network *network,
2767 struct connman_device *device,
2768 struct wifi_data *wifi)
2772 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2774 const unsigned char *ssid, *wps_ssid;
2775 unsigned int ssid_len, wps_ssid_len;
2776 const char *wps_key;
2778 /* Checking if we got associated with requested
2780 ssid = connman_network_get_blob(network, "WiFi.SSID",
2783 wps_ssid = g_supplicant_interface_get_wps_ssid(
2784 interface, &wps_ssid_len);
2786 if (!wps_ssid || wps_ssid_len != ssid_len ||
2787 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2788 connman_network_set_associating(network, false);
2789 #if defined TIZEN_EXT
2790 g_supplicant_interface_disconnect(wifi->interface,
2791 disconnect_callback, wifi->network);
2793 connman_network_set_bool(network, "WiFi.UseWPS", false);
2794 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2796 g_supplicant_interface_disconnect(wifi->interface,
2797 disconnect_callback, wifi);
2802 wps_key = g_supplicant_interface_get_wps_key(interface);
2803 #if defined TIZEN_EXT
2804 /* Check the passphrase and encrypt it
2807 gchar *passphrase = g_strdup(wps_key);
2809 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2811 if (check_passphrase_ext(network, passphrase) < 0) {
2812 DBG("[WPS] Invalid passphrase");
2817 ret = send_encryption_request(passphrase, network);
2822 DBG("[WPS] Encryption request succeeded");
2824 DBG("[WPS] Encryption request failed %d", ret);
2827 connman_network_set_string(network, "WiFi.Passphrase",
2830 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2837 static bool handle_assoc_status_code(GSupplicantInterface *interface,
2838 struct wifi_data *wifi)
2840 if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
2841 wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
2842 wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
2843 wifi->load_shaping_retries ++;
2846 wifi->load_shaping_retries = 0;
2850 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2851 struct connman_network *network,
2852 struct wifi_data *wifi)
2854 #if defined TIZEN_EXT
2855 const char *security;
2856 struct connman_service *service;
2858 if (wifi->connected)
2861 security = connman_network_get_string(network, "WiFi.Security");
2863 if (security && g_str_equal(security, "ieee8021x") == true &&
2864 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2866 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2871 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2874 struct connman_service *service;
2876 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2879 if (wifi->connected)
2883 service = connman_service_lookup_from_network(network);
2889 if (connman_service_get_favorite(service)) {
2890 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2895 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2900 #if defined TIZEN_EXT
2901 static bool handle_wifi_assoc_retry(struct connman_network *network,
2902 struct wifi_data *wifi)
2904 const char *security;
2906 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2907 connman_network_get_connecting(network) != true) {
2908 wifi->assoc_retry_count = 0;
2912 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2913 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2914 wifi->assoc_retry_count = 0;
2918 security = connman_network_get_string(network, "WiFi.Security");
2919 if (security && g_str_equal(security, "ieee8021x") == true &&
2920 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2921 wifi->assoc_retry_count = 0;
2925 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2926 wifi->assoc_retry_count = 0;
2928 /* Honestly it's not an invalid-key error,
2929 * however QA team recommends that the invalid-key error
2930 * might be better to display for user experience.
2932 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2941 static void interface_state(GSupplicantInterface *interface)
2943 struct connman_network *network;
2944 struct connman_device *device;
2945 struct wifi_data *wifi;
2946 GSupplicantState state = g_supplicant_interface_get_state(interface);
2950 wifi = g_supplicant_interface_get_data(interface);
2952 DBG("wifi %p interface state %d", wifi, state);
2957 if (state == G_SUPPLICANT_STATE_COMPLETED) {
2958 if (wifi->tethering_param) {
2959 g_free(wifi->tethering_param->ssid);
2960 g_free(wifi->tethering_param);
2961 wifi->tethering_param = NULL;
2965 device = wifi->device;
2969 if (g_supplicant_interface_get_ready(interface) &&
2970 !wifi->interface_ready) {
2971 wifi->interface_ready = true;
2972 finalize_interface_creation(wifi);
2975 network = wifi->network;
2980 case G_SUPPLICANT_STATE_SCANNING:
2981 if (wifi->connected)
2982 connman_network_set_connected(network, false);
2986 case G_SUPPLICANT_STATE_AUTHENTICATING:
2987 case G_SUPPLICANT_STATE_ASSOCIATING:
2988 #if defined TIZEN_EXT
2989 reset_autoscan(device);
2991 stop_autoscan(device);
2994 if (!wifi->connected)
2995 connman_network_set_associating(network, true);
2999 case G_SUPPLICANT_STATE_COMPLETED:
3000 #if defined TIZEN_EXT
3001 /* though it should be already reset: */
3002 reset_autoscan(device);
3004 wifi->assoc_retry_count = 0;
3006 wifi->scan_pending_network = NULL;
3008 /* should be cleared scanning flag */
3009 bool scanning = connman_device_get_scanning(device);
3011 connman_device_set_scanning(device,
3012 CONNMAN_SERVICE_TYPE_WIFI, false);
3013 connman_device_unref(device);
3016 /* though it should be already stopped: */
3017 stop_autoscan(device);
3020 if (!handle_wps_completion(interface, network, device, wifi))
3023 connman_network_set_connected(network, true);
3025 wifi->disconnect_code = 0;
3026 wifi->assoc_code = 0;
3027 wifi->load_shaping_retries = 0;
3030 case G_SUPPLICANT_STATE_DISCONNECTED:
3032 * If we're in one of the idle modes, we have
3033 * not started association yet and thus setting
3034 * those ones to FALSE could cancel an association
3037 wps = connman_network_get_bool(network, "WiFi.UseWPS");
3039 if (is_idle_wps(interface, wifi))
3045 if (handle_assoc_status_code(interface, wifi))
3048 /* If previous state was 4way-handshake, then
3049 * it's either: psk was incorrect and thus we retry
3050 * or if we reach the maximum retries we declare the
3052 if (handle_4way_handshake_failure(interface,
3056 /* See table 8-36 Reason codes in IEEE Std 802.11 */
3057 switch (wifi->disconnect_code) {
3058 case 1: /* Unspecified reason */
3059 /* Let's assume it's because we got blocked */
3061 case 6: /* Class 2 frame received from nonauthenticated STA */
3062 connman_network_set_error(network,
3063 CONNMAN_NETWORK_ERROR_BLOCKED);
3070 #if defined TIZEN_EXT
3073 err = g_supplicant_interface_remove_network(wifi->interface);
3075 DBG("Failed to remove network(%d)", err);
3078 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
3079 * Retry association until its retry count is expired */
3080 if (handle_wifi_assoc_retry(network, wifi) == true) {
3081 throw_wifi_scan(wifi->device, scan_callback);
3082 wifi->scan_pending_network = wifi->network;
3086 if(wifi->disconnect_code > 0){
3087 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
3088 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
3091 /* To avoid unnecessary repeated association in wpa_supplicant,
3092 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
3093 if (wps != true && wifi->network && wifi->disconnecting == false) {
3094 wifi->disconnecting = true;
3095 err = g_supplicant_interface_disconnect(wifi->interface,
3096 disconnect_callback, wifi->network);
3098 wifi->disconnecting = false;
3100 connman_network_set_connected(network, false);
3101 connman_network_set_associating(network, false);
3103 start_autoscan(device);
3109 connman_network_set_connected(network, false);
3110 connman_network_set_associating(network, false);
3111 wifi->disconnecting = false;
3113 start_autoscan(device);
3117 case G_SUPPLICANT_STATE_INACTIVE:
3118 #if defined TIZEN_EXT
3119 if (handle_wps_completion(interface, network, device, wifi) == false)
3122 connman_network_set_associating(network, false);
3123 start_autoscan(device);
3127 case G_SUPPLICANT_STATE_UNKNOWN:
3128 case G_SUPPLICANT_STATE_DISABLED:
3129 case G_SUPPLICANT_STATE_ASSOCIATED:
3130 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3131 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3135 old_connected = wifi->connected;
3136 wifi->state = state;
3138 /* Saving wpa_s state policy:
3139 * If connected and if the state changes are roaming related:
3140 * --> We stay connected
3142 * --> We are connected
3144 * --> We are not connected
3147 case G_SUPPLICANT_STATE_AUTHENTICATING:
3148 case G_SUPPLICANT_STATE_ASSOCIATING:
3149 case G_SUPPLICANT_STATE_ASSOCIATED:
3150 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3151 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3152 if (wifi->connected)
3153 connman_warn("Probably roaming right now!"
3154 " Staying connected...");
3156 case G_SUPPLICANT_STATE_SCANNING:
3157 wifi->connected = false;
3160 start_autoscan(device);
3162 case G_SUPPLICANT_STATE_COMPLETED:
3163 wifi->connected = true;
3166 wifi->connected = false;
3173 static void interface_removed(GSupplicantInterface *interface)
3175 const char *ifname = g_supplicant_interface_get_ifname(interface);
3176 struct wifi_data *wifi;
3178 DBG("ifname %s", ifname);
3180 wifi = g_supplicant_interface_get_data(interface);
3183 wifi->interface = NULL;
3185 if (wifi && wifi->tethering)
3188 if (!wifi || !wifi->device) {
3189 DBG("wifi interface already removed");
3193 connman_device_set_powered(wifi->device, false);
3195 check_p2p_technology();
3198 static void set_device_type(const char *type, char dev_type[17])
3200 const char *oui = "0050F204";
3201 const char *category = "0001";
3202 const char *sub_category = "0000";
3204 if (!g_strcmp0(type, "handset")) {
3206 sub_category = "0005";
3207 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3208 sub_category = "0001";
3209 else if (!g_strcmp0(type, "server"))
3210 sub_category = "0002";
3211 else if (!g_strcmp0(type, "laptop"))
3212 sub_category = "0005";
3213 else if (!g_strcmp0(type, "desktop"))
3214 sub_category = "0006";
3215 else if (!g_strcmp0(type, "tablet"))
3216 sub_category = "0009";
3217 else if (!g_strcmp0(type, "watch"))
3220 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3223 static void p2p_support(GSupplicantInterface *interface)
3225 char dev_type[17] = {};
3226 const char *hostname;
3233 if (!g_supplicant_interface_has_p2p(interface))
3236 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3237 DBG("Could not register P2P technology driver");
3241 hostname = connman_utsname_get_hostname();
3243 hostname = "ConnMan";
3245 set_device_type(connman_machine_get_type(), dev_type);
3246 g_supplicant_interface_set_p2p_device_config(interface,
3247 hostname, dev_type);
3248 connman_peer_driver_register(&peer_driver);
3251 static void scan_started(GSupplicantInterface *interface)
3256 static void scan_finished(GSupplicantInterface *interface)
3258 #if defined TIZEN_EXT
3259 struct wifi_data *wifi;
3260 bool is_associating = false;
3261 static bool is_scanning = true;
3266 #if defined TIZEN_EXT
3267 wifi = g_supplicant_interface_get_data(interface);
3268 if (wifi && wifi->scan_pending_network) {
3269 network_connect(wifi->scan_pending_network);
3270 wifi->scan_pending_network = NULL;
3273 //service state - associating
3274 if(!wifi || !wifi->network)
3277 is_associating = connman_network_get_associating(wifi->network);
3278 if(is_associating && is_scanning){
3279 is_scanning = false;
3280 DBG("send scan for connecting");
3281 throw_wifi_scan(wifi->device, scan_callback);
3292 static void ap_create_fail(GSupplicantInterface *interface)
3294 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3297 if ((wifi->tethering) && (wifi->tethering_param)) {
3298 DBG("%s create AP fail \n",
3299 g_supplicant_interface_get_ifname(wifi->interface));
3301 connman_inet_remove_from_bridge(wifi->index, wifi->bridge);
3302 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
3303 wifi->tethering = false;
3305 ret = tech_set_tethering(wifi->tethering_param->technology,
3306 wifi->tethering_param->ssid->ssid,
3307 wifi->tethering_param->ssid->passphrase,
3308 wifi->bridge, true);
3310 if ((ret == -EOPNOTSUPP) && (wifi_technology)) {
3311 connman_technology_tethering_notify(wifi_technology,false);
3314 g_free(wifi->tethering_param->ssid);
3315 g_free(wifi->tethering_param);
3316 wifi->tethering_param = NULL;
3322 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3324 unsigned char strength;
3326 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3328 #if !defined TIZEN_EXT
3335 static void network_added(GSupplicantNetwork *supplicant_network)
3337 struct connman_network *network;
3338 GSupplicantInterface *interface;
3339 struct wifi_data *wifi;
3340 const char *name, *identifier, *security, *group, *mode;
3341 const unsigned char *ssid;
3342 unsigned int ssid_len;
3346 bool wps_advertizing;
3348 #if defined TIZEN_EXT
3349 GSList *vsie_list = NULL;
3352 mode = g_supplicant_network_get_mode(supplicant_network);
3353 identifier = g_supplicant_network_get_identifier(supplicant_network);
3355 DBG("%s", identifier);
3357 if (!g_strcmp0(mode, "adhoc"))
3360 interface = g_supplicant_network_get_interface(supplicant_network);
3361 wifi = g_supplicant_interface_get_data(interface);
3362 name = g_supplicant_network_get_name(supplicant_network);
3363 security = g_supplicant_network_get_security(supplicant_network);
3364 group = g_supplicant_network_get_identifier(supplicant_network);
3365 wps = g_supplicant_network_get_wps(supplicant_network);
3366 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3367 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3368 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3369 supplicant_network);
3374 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3376 network = connman_device_get_network(wifi->device, identifier);
3379 network = connman_network_create(identifier,
3380 CONNMAN_NETWORK_TYPE_WIFI);
3384 connman_network_set_index(network, wifi->index);
3386 if (connman_device_add_network(wifi->device, network) < 0) {
3387 connman_network_unref(network);
3391 wifi->networks = g_slist_prepend(wifi->networks, network);
3394 if (name && name[0] != '\0')
3395 connman_network_set_name(network, name);
3397 connman_network_set_blob(network, "WiFi.SSID",
3399 #if defined TIZEN_EXT
3400 vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
3402 connman_network_set_vsie_list(network, vsie_list);
3404 DBG("vsie_list is NULL");
3406 connman_network_set_string(network, "WiFi.Security", security);
3407 connman_network_set_strength(network,
3408 calculate_strength(supplicant_network));
3409 connman_network_set_bool(network, "WiFi.WPS", wps);
3412 /* Is AP advertizing for WPS association?
3413 * If so, we decide to use WPS by default */
3414 if (wps_ready && wps_pbc &&
3416 #if !defined TIZEN_EXT
3417 connman_network_set_bool(network, "WiFi.UseWPS", true);
3419 DBG("wps is activating by ap but ignore it.");
3424 connman_network_set_frequency(network,
3425 g_supplicant_network_get_frequency(supplicant_network));
3426 #if defined TIZEN_EXT
3427 connman_network_set_bssid(network,
3428 g_supplicant_network_get_bssid(supplicant_network));
3429 connman_network_set_maxrate(network,
3430 g_supplicant_network_get_maxrate(supplicant_network));
3431 connman_network_set_enc_mode(network,
3432 g_supplicant_network_get_enc_mode(supplicant_network));
3433 connman_network_set_rsn_mode(network,
3434 g_supplicant_network_get_rsn_mode(supplicant_network));
3435 connman_network_set_keymgmt(network,
3436 g_supplicant_network_get_keymgmt(supplicant_network));
3437 connman_network_set_bool(network, "WiFi.HS20AP",
3438 g_supplicant_network_is_hs20AP(supplicant_network));
3440 connman_network_set_available(network, true);
3441 connman_network_set_string(network, "WiFi.Mode", mode);
3443 #if defined TIZEN_EXT
3448 connman_network_set_group(network, group);
3450 #if defined TIZEN_EXT
3451 if (wifi_first_scan == true)
3452 found_with_first_scan = true;
3455 if (wifi->hidden && ssid) {
3456 #if defined TIZEN_EXT
3457 if (network_security(wifi->hidden->security) ==
3458 network_security(security) &&
3460 if (!g_strcmp0(wifi->hidden->security, security) &&
3462 wifi->hidden->ssid_len == ssid_len &&
3463 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3464 connman_network_connect_hidden(network,
3465 wifi->hidden->identity,
3466 wifi->hidden->passphrase,
3467 wifi->hidden->user_data);
3468 wifi->hidden->user_data = NULL;
3469 hidden_free(wifi->hidden);
3470 wifi->hidden = NULL;
3475 static void network_removed(GSupplicantNetwork *network)
3477 GSupplicantInterface *interface;
3478 struct wifi_data *wifi;
3479 const char *name, *identifier;
3480 struct connman_network *connman_network;
3482 interface = g_supplicant_network_get_interface(network);
3483 wifi = g_supplicant_interface_get_data(interface);
3484 identifier = g_supplicant_network_get_identifier(network);
3485 name = g_supplicant_network_get_name(network);
3487 DBG("name %s", name);
3492 connman_network = connman_device_get_network(wifi->device, identifier);
3493 if (!connman_network)
3496 #if defined TIZEN_EXT
3497 if (connman_network == wifi->scan_pending_network)
3498 wifi->scan_pending_network = NULL;
3500 if (connman_network == wifi->pending_network)
3501 wifi->pending_network = NULL;
3503 if(connman_network_get_connecting(connman_network) == true){
3504 connman_network_set_connected(connman_network, false);
3508 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3510 connman_device_remove_network(wifi->device, connman_network);
3511 connman_network_unref(connman_network);
3514 static void network_changed(GSupplicantNetwork *network, const char *property)
3516 GSupplicantInterface *interface;
3517 struct wifi_data *wifi;
3518 const char *name, *identifier;
3519 struct connman_network *connman_network;
3521 #if defined TIZEN_EXT
3522 const unsigned char *bssid;
3523 unsigned int maxrate;
3528 interface = g_supplicant_network_get_interface(network);
3529 wifi = g_supplicant_interface_get_data(interface);
3530 identifier = g_supplicant_network_get_identifier(network);
3531 name = g_supplicant_network_get_name(network);
3533 DBG("name %s", name);
3538 connman_network = connman_device_get_network(wifi->device, identifier);
3539 if (!connman_network)
3542 if (g_str_equal(property, "Signal")) {
3543 connman_network_set_strength(connman_network,
3544 calculate_strength(network));
3545 connman_network_update(connman_network);
3548 #if defined TIZEN_EXT
3549 bssid = g_supplicant_network_get_bssid(network);
3550 maxrate = g_supplicant_network_get_maxrate(network);
3551 frequency = g_supplicant_network_get_frequency(network);
3552 wps = g_supplicant_network_get_wps(network);
3554 connman_network_set_bssid(connman_network, bssid);
3555 connman_network_set_maxrate(connman_network, maxrate);
3556 connman_network_set_frequency(connman_network, frequency);
3557 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3561 static void network_associated(GSupplicantNetwork *network)
3563 GSupplicantInterface *interface;
3564 struct wifi_data *wifi;
3565 struct connman_network *connman_network;
3566 const char *identifier;
3570 interface = g_supplicant_network_get_interface(network);
3574 wifi = g_supplicant_interface_get_data(interface);
3578 identifier = g_supplicant_network_get_identifier(network);
3580 connman_network = connman_device_get_network(wifi->device, identifier);
3581 if (!connman_network)
3584 if (wifi->network) {
3585 if (wifi->network == connman_network)
3589 * This should never happen, we got associated with
3590 * a network different than the one we were expecting.
3592 DBG("Associated to %p while expecting %p",
3593 connman_network, wifi->network);
3595 connman_network_set_associating(wifi->network, false);
3598 DBG("Reconnecting to previous network %p from wpa_s", connman_network);
3600 wifi->network = connman_network_ref(connman_network);
3604 * Interface state changes callback (interface_state) is always
3605 * called before network_associated callback thus we need to call
3606 * interface_state again in order to process the new state now that
3607 * we have the network properly set.
3609 interface_state(interface);
3612 static void apply_peer_services(GSupplicantPeer *peer,
3613 struct connman_peer *connman_peer)
3615 const unsigned char *data;
3620 connman_peer_reset_services(connman_peer);
3622 data = g_supplicant_peer_get_widi_ies(peer, &length);
3624 connman_peer_add_service(connman_peer,
3625 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3629 static void add_station(const char *mac)
3631 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3635 static void remove_station(const char *mac)
3637 connman_technology_tethering_remove_station(mac);
3640 static void peer_found(GSupplicantPeer *peer)
3642 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3643 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3644 struct connman_peer *connman_peer;
3645 const char *identifier, *name;
3647 #if defined TIZEN_EXT
3651 identifier = g_supplicant_peer_get_identifier(peer);
3652 name = g_supplicant_peer_get_name(peer);
3654 DBG("ident: %s", identifier);
3656 connman_peer = connman_peer_get(wifi->device, identifier);
3660 connman_peer = connman_peer_create(identifier);
3661 connman_peer_set_name(connman_peer, name);
3662 connman_peer_set_device(connman_peer, wifi->device);
3663 apply_peer_services(peer, connman_peer);
3665 ret = connman_peer_register(connman_peer);
3666 if (ret < 0 && ret != -EALREADY)
3667 connman_peer_unref(connman_peer);
3669 wifi->peers = g_slist_prepend(wifi->peers, connman_peer);
3672 static void peer_lost(GSupplicantPeer *peer)
3674 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3675 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3676 struct connman_peer *connman_peer;
3677 const char *identifier;
3682 identifier = g_supplicant_peer_get_identifier(peer);
3684 DBG("ident: %s", identifier);
3686 connman_peer = connman_peer_get(wifi->device, identifier);
3688 if (wifi->p2p_connecting &&
3689 wifi->pending_peer == connman_peer) {
3690 peer_connect_timeout(wifi);
3692 connman_peer_unregister(connman_peer);
3693 connman_peer_unref(connman_peer);
3696 wifi->peers = g_slist_remove(wifi->peers, connman_peer);
3699 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3701 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3702 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3703 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3704 struct connman_peer *connman_peer;
3705 const char *identifier;
3707 #if defined TIZEN_EXT
3712 identifier = g_supplicant_peer_get_identifier(peer);
3714 DBG("ident: %s", identifier);
3719 connman_peer = connman_peer_get(wifi->device, identifier);
3724 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3725 apply_peer_services(peer, connman_peer);
3726 connman_peer_services_changed(connman_peer);
3728 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3729 if (!g_supplicant_peer_is_in_a_group(peer))
3730 p_state = CONNMAN_PEER_STATE_IDLE;
3732 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3734 case G_SUPPLICANT_PEER_GROUP_STARTED:
3736 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3737 p_state = CONNMAN_PEER_STATE_IDLE;
3739 case G_SUPPLICANT_PEER_GROUP_JOINED:
3740 connman_peer_set_iface_address(connman_peer,
3741 g_supplicant_peer_get_iface_address(peer));
3743 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3744 p_state = CONNMAN_PEER_STATE_IDLE;
3746 case G_SUPPLICANT_PEER_GROUP_FAILED:
3747 if (g_supplicant_peer_has_requested_connection(peer))
3748 p_state = CONNMAN_PEER_STATE_IDLE;
3750 p_state = CONNMAN_PEER_STATE_FAILURE;
3754 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3755 p_state == CONNMAN_PEER_STATE_FAILURE) {
3756 if (wifi->p2p_connecting
3757 && connman_peer == wifi->pending_peer)
3758 peer_cancel_timeout(wifi);
3760 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3763 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3766 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3767 GSupplicantInterface *g_iface;
3768 struct wifi_data *g_wifi;
3770 g_iface = g_supplicant_peer_get_group_interface(peer);
3774 g_wifi = g_supplicant_interface_get_data(g_iface);
3778 connman_peer_set_as_master(connman_peer,
3779 !g_supplicant_peer_is_client(peer));
3780 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3783 * If wpa_supplicant didn't create a dedicated p2p-group
3784 * interface then mark this interface as p2p_device to avoid
3785 * scan and auto-scan are launched on it while P2P is connected.
3787 if (!g_list_find(p2p_iface_list, g_wifi))
3788 wifi->p2p_device = true;
3791 connman_peer_set_state(connman_peer, p_state);
3794 static void peer_request(GSupplicantPeer *peer)
3796 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3797 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3798 struct connman_peer *connman_peer;
3799 const char *identifier;
3801 #if defined TIZEN_EXT
3806 identifier = g_supplicant_peer_get_identifier(peer);
3808 DBG("ident: %s", identifier);
3810 connman_peer = connman_peer_get(wifi->device, identifier);
3814 connman_peer_request_connection(connman_peer);
3817 #if defined TIZEN_EXT
3818 static void system_power_off(void)
3821 struct wifi_data *wifi;
3822 struct connman_service *service;
3823 struct connman_ipconfig *ipconfig_ipv4;
3825 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3826 for (list = iface_list; list; list = list->next) {
3829 if (wifi->network != NULL) {
3830 service = connman_service_lookup_from_network(wifi->network);
3831 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3832 __connman_dhcp_stop(ipconfig_ipv4);
3838 static void network_merged(GSupplicantNetwork *network)
3840 GSupplicantInterface *interface;
3841 GSupplicantState state;
3842 struct wifi_data *wifi;
3843 const char *identifier;
3844 struct connman_network *connman_network;
3848 interface = g_supplicant_network_get_interface(network);
3852 state = g_supplicant_interface_get_state(interface);
3853 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3856 wifi = g_supplicant_interface_get_data(interface);
3860 identifier = g_supplicant_network_get_identifier(network);
3862 connman_network = connman_device_get_network(wifi->device, identifier);
3863 if (!connman_network)
3866 DBG("merged identifier %s", identifier);
3868 if (wifi->connected == FALSE) {
3870 case G_SUPPLICANT_STATE_AUTHENTICATING:
3871 case G_SUPPLICANT_STATE_ASSOCIATING:
3872 case G_SUPPLICANT_STATE_ASSOCIATED:
3873 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3874 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3875 connman_network_set_associating(connman_network, TRUE);
3877 case G_SUPPLICANT_STATE_COMPLETED:
3878 connman_network_set_connected(connman_network, TRUE);
3881 DBG("Not handled the state : %d", state);
3886 ishs20AP = g_supplicant_network_is_hs20AP(network);
3889 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3890 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3891 connman_network_set_string(connman_network, "WiFi.EAP",
3893 connman_network_set_string(connman_network, "WiFi.Identity",
3894 g_supplicant_network_get_identity(network));
3895 connman_network_set_string(connman_network, "WiFi.Phase2",
3896 g_supplicant_network_get_phase2(network));
3901 wifi->network = connman_network;
3904 static void assoc_failed(void *user_data)
3906 struct connman_network *network = user_data;
3907 connman_network_set_associating(network, false);
3911 static void debug(const char *str)
3913 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3914 connman_debug("%s", str);
3917 static void disconnect_reasoncode(GSupplicantInterface *interface,
3920 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3923 wifi->disconnect_code = reasoncode;
3927 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
3929 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3932 wifi->assoc_code = status_code;
3936 static const GSupplicantCallbacks callbacks = {
3937 .system_ready = system_ready,
3938 .system_killed = system_killed,
3939 .interface_added = interface_added,
3940 .interface_state = interface_state,
3941 .interface_removed = interface_removed,
3942 .p2p_support = p2p_support,
3943 .scan_started = scan_started,
3944 .scan_finished = scan_finished,
3945 .ap_create_fail = ap_create_fail,
3946 .network_added = network_added,
3947 .network_removed = network_removed,
3948 .network_changed = network_changed,
3949 .network_associated = network_associated,
3950 .add_station = add_station,
3951 .remove_station = remove_station,
3952 .peer_found = peer_found,
3953 .peer_lost = peer_lost,
3954 .peer_changed = peer_changed,
3955 .peer_request = peer_request,
3956 #if defined TIZEN_EXT
3957 .system_power_off = system_power_off,
3958 .network_merged = network_merged,
3959 .assoc_failed = assoc_failed,
3962 .disconnect_reasoncode = disconnect_reasoncode,
3963 .assoc_status_code = assoc_status_code,
3967 static int tech_probe(struct connman_technology *technology)
3969 wifi_technology = technology;
3974 static void tech_remove(struct connman_technology *technology)
3976 wifi_technology = NULL;
3979 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3980 const char *passphrase)
3982 GSupplicantSSID *ap;
3984 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3988 ap->mode = G_SUPPLICANT_MODE_MASTER;
3990 ap->ssid_len = strlen(ssid);
3994 if (!passphrase || strlen(passphrase) == 0) {
3995 ap->security = G_SUPPLICANT_SECURITY_NONE;
3996 ap->passphrase = NULL;
3998 ap->security = G_SUPPLICANT_SECURITY_PSK;
3999 ap->protocol = G_SUPPLICANT_PROTO_RSN;
4000 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
4001 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
4002 ap->passphrase = passphrase;
4008 static void ap_start_callback(int result, GSupplicantInterface *interface,
4011 struct wifi_tethering_info *info = user_data;
4013 DBG("result %d index %d bridge %s",
4014 result, info->wifi->index, info->wifi->bridge);
4016 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4017 connman_inet_remove_from_bridge(info->wifi->index,
4018 info->wifi->bridge);
4020 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4021 connman_technology_tethering_notify(info->technology, false);
4022 g_free(info->wifi->tethering_param->ssid);
4023 g_free(info->wifi->tethering_param);
4024 info->wifi->tethering_param = NULL;
4028 g_free(info->ifname);
4032 static void ap_create_callback(int result,
4033 GSupplicantInterface *interface,
4036 struct wifi_tethering_info *info = user_data;
4038 DBG("result %d ifname %s", result,
4039 g_supplicant_interface_get_ifname(interface));
4041 if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4042 connman_inet_remove_from_bridge(info->wifi->index,
4043 info->wifi->bridge);
4045 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4046 connman_technology_tethering_notify(info->technology, false);
4047 g_free(info->wifi->tethering_param->ssid);
4048 g_free(info->wifi->tethering_param);
4049 info->wifi->tethering_param = NULL;
4053 g_free(info->ifname);
4059 info->wifi->interface = interface;
4060 g_supplicant_interface_set_data(interface, info->wifi);
4062 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
4063 connman_error("Failed to set interface ap_scan property");
4065 g_supplicant_interface_connect(interface, info->ssid,
4066 ap_start_callback, info);
4069 static void sta_remove_callback(int result,
4070 GSupplicantInterface *interface,
4073 struct wifi_tethering_info *info = user_data;
4074 const char *driver = connman_option_get_string("wifi");
4076 DBG("ifname %s result %d ", info->ifname, result);
4078 if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) {
4079 info->wifi->tethering = false;
4080 connman_technology_tethering_notify(info->technology, false);
4082 g_free(info->ifname);
4086 if (info->wifi->ap_supported == WIFI_AP_SUPPORTED) {
4087 g_free(info->wifi->tethering_param->ssid);
4088 g_free(info->wifi->tethering_param);
4089 info->wifi->tethering_param = NULL;
4094 info->wifi->interface = NULL;
4096 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
4101 static int enable_wifi_tethering(struct connman_technology *technology,
4102 const char *bridge, const char *identifier,
4103 const char *passphrase, bool available)
4106 GSupplicantInterface *interface;
4107 struct wifi_data *wifi;
4108 struct wifi_tethering_info *info;
4113 for (list = iface_list; list; list = list->next) {
4116 DBG("wifi %p network %p pending_network %p", wifi,
4117 wifi->network, wifi->pending_network);
4119 interface = wifi->interface;
4124 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED)
4127 ifname = g_supplicant_interface_get_ifname(wifi->interface);
4129 if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) {
4130 DBG("%s does not support AP mode (detected)", ifname);
4134 mode = g_supplicant_interface_get_mode(interface);
4135 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
4136 wifi->ap_supported = WIFI_AP_NOT_SUPPORTED;
4137 DBG("%s does not support AP mode (capability)", ifname);
4141 if (wifi->network && available)
4144 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
4148 wifi->tethering_param = g_try_malloc0(sizeof(struct wifi_tethering_info));
4149 if (!wifi->tethering_param) {
4155 info->technology = technology;
4156 info->wifi->bridge = bridge;
4157 info->ssid = ssid_ap_init(identifier, passphrase);
4161 info->ifname = g_strdup(ifname);
4165 wifi->tethering_param->technology = technology;
4166 wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase);
4167 if (!wifi->tethering_param->ssid)
4170 info->wifi->tethering = true;
4171 info->wifi->ap_supported = WIFI_AP_SUPPORTED;
4173 berr = connman_technology_tethering_notify(technology, true);
4177 err = g_supplicant_interface_remove(interface,
4178 sta_remove_callback,
4181 DBG("tethering wifi %p ifname %s", wifi, ifname);
4186 g_free(info->ifname);
4189 g_free(wifi->tethering_param);
4190 wifi->tethering_param = NULL;
4193 * Remove bridge if it was correctly created but remove
4194 * operation failed. Instead, if bridge creation failed then
4195 * break out and do not try again on another interface,
4196 * bridge set-up does not depend on it.
4199 connman_technology_tethering_notify(technology, false);
4207 static int tech_set_tethering(struct connman_technology *technology,
4208 const char *identifier, const char *passphrase,
4209 const char *bridge, bool enabled)
4212 struct wifi_data *wifi;
4218 for (list = iface_list; list; list = list->next) {
4221 if (wifi->tethering) {
4222 wifi->tethering = false;
4224 connman_inet_remove_from_bridge(wifi->index,
4226 wifi->bridged = false;
4230 connman_technology_tethering_notify(technology, false);
4235 DBG("trying tethering for available devices");
4236 err = enable_wifi_tethering(technology, bridge, identifier, passphrase,
4240 DBG("trying tethering for any device");
4241 err = enable_wifi_tethering(technology, bridge, identifier,
4248 static void regdom_callback(int result, const char *alpha2, void *user_data)
4252 if (!wifi_technology)
4258 connman_technology_regdom_notify(wifi_technology, alpha2);
4261 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
4263 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
4266 static struct connman_technology_driver tech_driver = {
4268 .type = CONNMAN_SERVICE_TYPE_WIFI,
4269 .probe = tech_probe,
4270 .remove = tech_remove,
4271 .set_tethering = tech_set_tethering,
4272 .set_regdom = tech_set_regdom,
4275 static int wifi_init(void)
4279 err = connman_network_driver_register(&network_driver);
4283 err = g_supplicant_register(&callbacks);
4285 connman_network_driver_unregister(&network_driver);
4289 err = connman_technology_driver_register(&tech_driver);
4291 g_supplicant_unregister(&callbacks);
4292 connman_network_driver_unregister(&network_driver);
4299 static void wifi_exit(void)
4303 connman_technology_driver_unregister(&tech_driver);
4305 g_supplicant_unregister(&callbacks);
4307 connman_network_driver_unregister(&network_driver);
4310 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
4311 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)