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
75 static struct connman_technology *wifi_technology = NULL;
76 static struct connman_technology *p2p_technology = NULL;
78 struct hidden_params {
80 unsigned int ssid_len;
84 GSupplicantScanParams *scan_params;
89 * Used for autoscan "emulation".
90 * Should be removed when wpa_s autoscan support will be by default.
92 struct autoscan_params {
101 struct connman_device *device;
102 struct connman_network *network;
103 struct connman_network *pending_network;
105 GSupplicantInterface *interface;
106 GSupplicantState state;
111 bool interface_ready;
117 struct hidden_params *hidden;
118 bool postpone_hidden;
120 * autoscan "emulation".
122 struct autoscan_params *autoscan;
124 GSupplicantScanParams *scan_params;
125 unsigned int p2p_find_timeout;
126 unsigned int p2p_connection_timeout;
127 struct connman_peer *pending_peer;
128 GSupplicantPeer *peer;
132 #if defined TIZEN_EXT
133 int assoc_retry_count;
134 struct connman_network *scan_pending_network;
135 bool allow_full_scan;
141 #if defined TIZEN_EXT
145 #define TIZEN_ASSOC_RETRY_COUNT 4
147 static gboolean wifi_first_scan = false;
148 static gboolean found_with_first_scan = false;
149 static gboolean is_wifi_notifier_registered = false;
153 static GList *iface_list = NULL;
155 static GList *pending_wifi_device = NULL;
156 static GList *p2p_iface_list = NULL;
157 bool wfd_service_registered = false;
159 static void start_autoscan(struct connman_device *device);
161 #if defined TIZEN_EXT
162 #define NETCONFIG_SERVICE "net.netconfig"
163 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
164 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
166 static gchar* send_cryptographic_request(const char *passphrase, const char *method)
168 DBusConnection *connection = NULL;
169 DBusMessage *msg = NULL, *reply = NULL;
172 const char *out_data;
174 if (!passphrase || !method) {
175 DBG("Invalid parameter");
179 dbus_error_init(&error);
181 connection = connman_dbus_get_connection();
183 DBG("dbus connection does not exist");
187 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
188 NETCONFIG_WIFI_INTERFACE, method);
190 dbus_connection_unref(connection);
194 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
197 reply = dbus_connection_send_with_reply_and_block(connection, msg,
198 DBUS_TIMEOUT_USE_DEFAULT, &error);
200 if (dbus_error_is_set(&error)) {
201 DBG("%s", error.message);
202 dbus_error_free(&error);
204 DBG("Failed to request cryptographic request");
206 dbus_connection_unref(connection);
207 dbus_message_unref(msg);
211 dbus_message_unref(msg);
212 dbus_connection_unref(connection);
214 if (!dbus_message_get_args(reply, NULL,
215 DBUS_TYPE_STRING, &out_data,
216 DBUS_TYPE_INVALID)) {
217 dbus_message_unref(reply);
221 result = g_strdup((const gchar *)out_data);
222 dbus_message_unref(reply);
228 static int p2p_tech_probe(struct connman_technology *technology)
230 p2p_technology = technology;
235 static void p2p_tech_remove(struct connman_technology *technology)
237 p2p_technology = NULL;
240 static struct connman_technology_driver p2p_tech_driver = {
242 .type = CONNMAN_SERVICE_TYPE_P2P,
243 .probe = p2p_tech_probe,
244 .remove = p2p_tech_remove,
247 static bool is_p2p_connecting(void)
251 for (list = iface_list; list; list = list->next) {
252 struct wifi_data *wifi = list->data;
254 if (wifi->p2p_connecting)
261 static void add_pending_wifi_device(struct wifi_data *wifi)
263 if (g_list_find(pending_wifi_device, wifi))
266 pending_wifi_device = g_list_append(pending_wifi_device, wifi);
269 static struct wifi_data *get_pending_wifi_data(const char *ifname)
273 for (list = pending_wifi_device; list; list = list->next) {
274 struct wifi_data *wifi;
275 const char *dev_name;
278 if (!wifi || !wifi->device)
281 dev_name = connman_device_get_string(wifi->device, "Interface");
282 if (!g_strcmp0(ifname, dev_name)) {
283 pending_wifi_device = g_list_delete_link(
284 pending_wifi_device, list);
292 static void remove_pending_wifi_device(struct wifi_data *wifi)
296 link = g_list_find(pending_wifi_device, wifi);
301 pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
304 static void peer_cancel_timeout(struct wifi_data *wifi)
306 if (wifi->p2p_connection_timeout > 0)
307 g_source_remove(wifi->p2p_connection_timeout);
309 wifi->p2p_connection_timeout = 0;
310 wifi->p2p_connecting = false;
312 if (wifi->pending_peer) {
313 connman_peer_unref(wifi->pending_peer);
314 wifi->pending_peer = NULL;
320 static gboolean peer_connect_timeout(gpointer data)
322 struct wifi_data *wifi = data;
326 if (wifi->p2p_connecting) {
327 enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
329 if (g_supplicant_peer_has_requested_connection(wifi->peer))
330 state = CONNMAN_PEER_STATE_IDLE;
332 connman_peer_set_state(wifi->pending_peer, state);
335 peer_cancel_timeout(wifi);
340 static void peer_connect_callback(int result, GSupplicantInterface *interface,
343 struct wifi_data *wifi = user_data;
344 struct connman_peer *peer = wifi->pending_peer;
346 DBG("peer %p - %d", peer, result);
352 peer_connect_timeout(wifi);
356 connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
358 wifi->p2p_connection_timeout = g_timeout_add_seconds(
359 P2P_CONNECTION_TIMEOUT,
360 peer_connect_timeout, wifi);
363 static int peer_connect(struct connman_peer *peer,
364 enum connman_peer_wps_method wps_method,
367 struct connman_device *device = connman_peer_get_device(peer);
368 GSupplicantPeerParams *peer_params;
369 GSupplicantPeer *gs_peer;
370 struct wifi_data *wifi;
374 DBG("peer %p", peer);
379 wifi = connman_device_get_data(device);
383 if (wifi->p2p_connecting)
388 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
389 connman_peer_get_identifier(peer));
393 pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
394 pin = g_supplicant_peer_is_wps_pin(gs_peer);
396 switch (wps_method) {
397 case CONNMAN_PEER_WPS_UNKNOWN:
398 if ((pbc && pin) || pin)
401 case CONNMAN_PEER_WPS_PBC:
406 case CONNMAN_PEER_WPS_PIN:
407 if (!pin || !wps_pin)
412 peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
416 peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
418 peer_params->wps_pin = g_strdup(wps_pin);
420 peer_params->master = connman_peer_service_is_master();
422 ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
423 peer_connect_callback, wifi);
424 if (ret == -EINPROGRESS) {
425 wifi->pending_peer = connman_peer_ref(peer);
426 wifi->peer = gs_peer;
427 wifi->p2p_connecting = true;
434 static int peer_disconnect(struct connman_peer *peer)
436 struct connman_device *device = connman_peer_get_device(peer);
437 GSupplicantPeerParams peer_params = {};
438 GSupplicantPeer *gs_peer;
439 struct wifi_data *wifi;
442 DBG("peer %p", peer);
447 wifi = connman_device_get_data(device);
451 gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
452 connman_peer_get_identifier(peer));
456 peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
458 ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
460 g_free(peer_params.path);
462 if (ret == -EINPROGRESS)
463 peer_cancel_timeout(wifi);
468 struct peer_service_registration {
469 peer_service_registration_cb_t callback;
473 static bool is_service_wfd(const unsigned char *specs, int length)
475 if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
481 static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
483 struct wifi_data *wifi = data;
485 if (!wifi->interface ||
486 !g_supplicant_interface_has_p2p(wifi->interface))
489 if (!wifi->servicing) {
490 g_supplicant_interface_p2p_listen(wifi->interface,
491 P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
497 static void register_wfd_service_cb(int result,
498 GSupplicantInterface *iface, void *user_data)
500 struct peer_service_registration *reg_data = user_data;
505 g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
507 if (reg_data && reg_data->callback) {
508 reg_data->callback(result, reg_data->user_data);
513 static GSupplicantP2PServiceParams *fill_in_peer_service_params(
514 const unsigned char *spec,
515 int spec_length, const unsigned char *query,
516 int query_length, int version)
518 GSupplicantP2PServiceParams *params;
520 params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
525 params->version = version;
526 params->service = g_memdup(spec, spec_length);
527 } else if (query_length > 0 && spec_length > 0) {
528 params->query = g_memdup(query, query_length);
529 params->query_length = query_length;
531 params->response = g_memdup(spec, spec_length);
532 params->response_length = spec_length;
534 params->wfd_ies = g_memdup(spec, spec_length);
535 params->wfd_ies_length = spec_length;
541 static void free_peer_service_params(GSupplicantP2PServiceParams *params)
546 g_free(params->service);
547 g_free(params->query);
548 g_free(params->response);
549 g_free(params->wfd_ies);
554 static int peer_register_wfd_service(const unsigned char *specification,
555 int specification_length,
556 peer_service_registration_cb_t callback,
559 struct peer_service_registration *reg_data = NULL;
560 static GSupplicantP2PServiceParams *params;
565 if (wfd_service_registered)
568 params = fill_in_peer_service_params(specification,
569 specification_length, NULL, 0, 0);
573 reg_data = g_try_malloc0(sizeof(*reg_data));
579 reg_data->callback = callback;
580 reg_data->user_data = user_data;
582 ret = g_supplicant_set_widi_ies(params,
583 register_wfd_service_cb, reg_data);
584 if (ret < 0 && ret != -EINPROGRESS)
587 wfd_service_registered = true;
591 free_peer_service_params(params);
597 static void register_peer_service_cb(int result,
598 GSupplicantInterface *iface, void *user_data)
600 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
601 struct peer_service_registration *reg_data = user_data;
603 #if defined TIZEN_EXT
611 apply_p2p_listen_on_iface(wifi, NULL);
613 if (reg_data->callback)
614 reg_data->callback(result, reg_data->user_data);
619 static int peer_register_service(const unsigned char *specification,
620 int specification_length,
621 const unsigned char *query,
622 int query_length, int version,
623 peer_service_registration_cb_t callback,
626 struct peer_service_registration *reg_data;
627 GSupplicantP2PServiceParams *params;
634 if (specification && !version && !query &&
635 is_service_wfd(specification, specification_length)) {
636 return peer_register_wfd_service(specification,
637 specification_length, callback, user_data);
640 reg_data = g_try_malloc0(sizeof(*reg_data));
644 reg_data->callback = callback;
645 reg_data->user_data = user_data;
649 for (list = iface_list; list; list = list->next) {
650 struct wifi_data *wifi = list->data;
651 GSupplicantInterface *iface = wifi->interface;
653 if (!g_supplicant_interface_has_p2p(iface))
656 params = fill_in_peer_service_params(specification,
657 specification_length, query,
658 query_length, version);
665 ret_f = g_supplicant_interface_p2p_add_service(iface,
666 register_peer_service_cb, params, reg_data);
667 if (ret_f == 0 || ret_f == -EINPROGRESS)
671 ret = g_supplicant_interface_p2p_add_service(iface,
672 register_peer_service_cb, params, NULL);
673 if (ret != 0 && ret != -EINPROGRESS)
674 free_peer_service_params(params);
677 if (ret_f != 0 && ret_f != -EINPROGRESS)
683 static int peer_unregister_wfd_service(void)
685 GSupplicantP2PServiceParams *params;
688 if (!wfd_service_registered)
691 params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
695 wfd_service_registered = false;
697 g_supplicant_set_widi_ies(params, NULL, NULL);
699 for (list = iface_list; list; list = list->next) {
700 struct wifi_data *wifi = list->data;
702 if (!g_supplicant_interface_has_p2p(wifi->interface))
706 if (!wifi->servicing || wifi->servicing < 0) {
707 g_supplicant_interface_p2p_listen(wifi->interface,
716 static int peer_unregister_service(const unsigned char *specification,
717 int specification_length,
718 const unsigned char *query,
719 int query_length, int version)
721 GSupplicantP2PServiceParams *params;
726 if (specification && !version && !query &&
727 is_service_wfd(specification, specification_length)) {
728 ret = peer_unregister_wfd_service();
729 if (ret != 0 && ret != -EINPROGRESS)
734 for (list = iface_list; list; list = list->next) {
735 struct wifi_data *wifi = list->data;
736 GSupplicantInterface *iface = wifi->interface;
741 if (!g_supplicant_interface_has_p2p(iface))
744 params = fill_in_peer_service_params(specification,
745 specification_length, query,
746 query_length, version);
752 ret = g_supplicant_interface_p2p_del_service(iface, params);
753 if (ret != 0 && ret != -EINPROGRESS)
754 free_peer_service_params(params);
757 if (!wifi->servicing || wifi->servicing < 0) {
758 g_supplicant_interface_p2p_listen(iface, 0, 0);
766 static struct connman_peer_driver peer_driver = {
767 .connect = peer_connect,
768 .disconnect = peer_disconnect,
769 .register_service = peer_register_service,
770 .unregister_service = peer_unregister_service,
773 static void handle_tethering(struct wifi_data *wifi)
775 if (!wifi->tethering)
784 DBG("index %d bridge %s", wifi->index, wifi->bridge);
786 if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
789 wifi->bridged = true;
792 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
794 struct connman_device *device = user_data;
795 struct wifi_data *wifi = connman_device_get_data(device);
800 DBG("index %d flags %d change %d", wifi->index, flags, change);
802 if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
806 DBG("interface down");
809 if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
810 if (flags & IFF_LOWER_UP) {
813 handle_tethering(wifi);
821 static int wifi_probe(struct connman_device *device)
823 struct wifi_data *wifi;
825 DBG("device %p", device);
827 wifi = g_try_new0(struct wifi_data, 1);
831 wifi->state = G_SUPPLICANT_STATE_INACTIVE;
833 connman_device_set_data(device, wifi);
834 wifi->device = connman_device_ref(device);
836 wifi->index = connman_device_get_index(device);
839 wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
840 wifi_newlink, device);
841 if (is_p2p_connecting())
842 add_pending_wifi_device(wifi);
844 iface_list = g_list_append(iface_list, wifi);
849 static void remove_networks(struct connman_device *device,
850 struct wifi_data *wifi)
854 for (list = wifi->networks; list; list = list->next) {
855 struct connman_network *network = list->data;
857 connman_device_remove_network(device, network);
858 connman_network_unref(network);
861 g_slist_free(wifi->networks);
862 wifi->networks = NULL;
865 static void reset_autoscan(struct connman_device *device)
867 struct wifi_data *wifi = connman_device_get_data(device);
868 struct autoscan_params *autoscan;
872 if (!wifi || !wifi->autoscan)
875 autoscan = wifi->autoscan;
877 if (autoscan->timeout == 0 && autoscan->interval == 0)
880 g_source_remove(autoscan->timeout);
882 autoscan->timeout = 0;
883 autoscan->interval = 0;
885 connman_device_unref(device);
888 static void stop_autoscan(struct connman_device *device)
890 const struct wifi_data *wifi = connman_device_get_data(device);
892 if (!wifi || !wifi->autoscan)
895 reset_autoscan(device);
897 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
900 static void check_p2p_technology(void)
902 bool p2p_exists = false;
905 for (list = iface_list; list; list = list->next) {
906 struct wifi_data *w = list->data;
909 g_supplicant_interface_has_p2p(w->interface))
914 connman_technology_driver_unregister(&p2p_tech_driver);
915 connman_peer_driver_unregister(&peer_driver);
919 static void wifi_remove(struct connman_device *device)
921 struct wifi_data *wifi = connman_device_get_data(device);
923 DBG("device %p wifi %p", device, wifi);
928 stop_autoscan(device);
930 if (wifi->p2p_device)
931 p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
933 iface_list = g_list_remove(iface_list, wifi);
935 check_p2p_technology();
937 remove_pending_wifi_device(wifi);
939 if (wifi->p2p_find_timeout) {
940 g_source_remove(wifi->p2p_find_timeout);
941 connman_device_unref(wifi->device);
944 if (wifi->p2p_connection_timeout)
945 g_source_remove(wifi->p2p_connection_timeout);
947 remove_networks(device, wifi);
949 connman_device_set_powered(device, false);
950 connman_device_set_data(device, NULL);
951 connman_device_unref(wifi->device);
952 connman_rtnl_remove_watch(wifi->watch);
954 g_supplicant_interface_set_data(wifi->interface, NULL);
956 g_supplicant_interface_cancel(wifi->interface);
958 if (wifi->scan_params)
959 g_supplicant_free_scan_params(wifi->scan_params);
961 g_free(wifi->autoscan);
962 g_free(wifi->identifier);
966 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
970 for (iter = list; iter; iter = g_slist_next(iter)) {
971 struct scan_ssid *scan_ssid = iter->data;
973 if (ssid_len == scan_ssid->ssid_len &&
974 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
981 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
982 int freq, GSupplicantScanParams *scan_data,
983 int driver_max_scan_ssids, char *ssid_name)
986 struct scan_ssid *scan_ssid;
988 if ((driver_max_scan_ssids == 0 ||
989 driver_max_scan_ssids > scan_data->num_ssids) &&
990 (hex_ssid || raw_ssid)) {
992 unsigned int j = 0, hex;
995 size_t hex_ssid_len = strlen(hex_ssid);
997 ssid = g_try_malloc0(hex_ssid_len / 2);
1001 for (i = 0; i < hex_ssid_len; i += 2) {
1002 sscanf(hex_ssid + i, "%02x", &hex);
1011 * If we have already added hidden AP to the list,
1012 * then do not do it again. This might happen if you have
1013 * used or are using multiple wifi cards, so in that case
1014 * you might have multiple service files for same AP.
1016 if (is_duplicate(scan_data->ssids, ssid, j)) {
1022 scan_ssid = g_try_new(struct scan_ssid, 1);
1029 memcpy(scan_ssid->ssid, ssid, j);
1030 scan_ssid->ssid_len = j;
1031 scan_data->ssids = g_slist_prepend(scan_data->ssids,
1034 scan_data->num_ssids++;
1036 DBG("SSID %s added to scanned list of %d entries", ssid_name,
1037 scan_data->num_ssids);
1044 scan_data->ssids = g_slist_reverse(scan_data->ssids);
1046 if (!scan_data->freqs) {
1047 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
1048 if (!scan_data->freqs) {
1049 g_slist_free_full(scan_data->ssids, g_free);
1053 scan_data->num_freqs = 1;
1054 scan_data->freqs[0] = freq;
1056 bool duplicate = false;
1058 /* Don't add duplicate entries */
1059 for (i = 0; i < scan_data->num_freqs; i++) {
1060 if (scan_data->freqs[i] == freq) {
1067 scan_data->num_freqs++;
1068 scan_data->freqs = g_try_realloc(scan_data->freqs,
1069 sizeof(uint16_t) * scan_data->num_freqs);
1070 if (!scan_data->freqs) {
1071 g_slist_free_full(scan_data->ssids, g_free);
1074 scan_data->freqs[scan_data->num_freqs - 1] = freq;
1081 static int get_hidden_connections(GSupplicantScanParams *scan_data)
1083 struct connman_config_entry **entries;
1089 int num_ssids = 0, add_param_failed = 0;
1091 services = connman_storage_get_services();
1092 for (i = 0; services && services[i]; i++) {
1093 if (strncmp(services[i], "wifi_", 5) != 0)
1096 keyfile = connman_storage_load_service(services[i]);
1100 value = g_key_file_get_boolean(keyfile,
1101 services[i], "Hidden", NULL);
1103 g_key_file_free(keyfile);
1107 value = g_key_file_get_boolean(keyfile,
1108 services[i], "Favorite", NULL);
1110 g_key_file_free(keyfile);
1114 #if defined TIZEN_EXT
1115 value = g_key_file_get_boolean(keyfile,
1116 services[i], "AutoConnect", NULL);
1118 g_key_file_free(keyfile);
1123 ssid = g_key_file_get_string(keyfile,
1124 services[i], "SSID", NULL);
1126 name = g_key_file_get_string(keyfile, services[i], "Name",
1129 ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
1137 g_key_file_free(keyfile);
1141 * Check if there are any hidden AP that needs to be provisioned.
1143 entries = connman_config_get_entries("wifi");
1144 for (i = 0; entries && entries[i]; i++) {
1147 if (!entries[i]->hidden)
1150 if (!entries[i]->ssid) {
1151 ssid = entries[i]->name;
1154 ssid = entries[i]->ssid;
1155 len = entries[i]->ssid_len;
1161 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
1168 connman_config_free_entries(entries);
1170 if (add_param_failed > 0)
1171 DBG("Unable to scan %d out of %d SSIDs",
1172 add_param_failed, num_ssids);
1174 g_strfreev(services);
1179 static int get_hidden_connections_params(struct wifi_data *wifi,
1180 GSupplicantScanParams *scan_params)
1182 int driver_max_ssids, i;
1183 GSupplicantScanParams *orig_params;
1186 * Scan hidden networks so that we can autoconnect to them.
1187 * We will assume 1 as a default number of ssid to scan.
1189 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1191 if (driver_max_ssids == 0)
1192 driver_max_ssids = 1;
1194 DBG("max ssids %d", driver_max_ssids);
1196 if (!wifi->scan_params) {
1197 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1198 if (!wifi->scan_params)
1201 if (get_hidden_connections(wifi->scan_params) == 0) {
1202 g_supplicant_free_scan_params(wifi->scan_params);
1203 wifi->scan_params = NULL;
1209 orig_params = wifi->scan_params;
1211 /* Let's transfer driver_max_ssids params */
1212 for (i = 0; i < driver_max_ssids; i++) {
1213 struct scan_ssid *ssid;
1215 if (!wifi->scan_params->ssids)
1218 ssid = orig_params->ssids->data;
1219 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
1220 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
1224 scan_params->num_ssids = i;
1225 scan_params->ssids = g_slist_reverse(scan_params->ssids);
1227 scan_params->freqs = g_memdup(orig_params->freqs,
1228 sizeof(uint16_t) * orig_params->num_freqs);
1229 if (!scan_params->freqs)
1232 scan_params->num_freqs = orig_params->num_freqs;
1237 orig_params->num_ssids -= scan_params->num_ssids;
1239 return scan_params->num_ssids;
1242 g_slist_free_full(scan_params->ssids, g_free);
1243 g_supplicant_free_scan_params(wifi->scan_params);
1244 wifi->scan_params = NULL;
1249 static int throw_wifi_scan(struct connman_device *device,
1250 GSupplicantInterfaceCallback callback)
1252 struct wifi_data *wifi = connman_device_get_data(device);
1258 DBG("device %p %p", device, wifi->interface);
1260 if (wifi->tethering)
1262 #if defined TIZEN_EXT
1263 if (connman_device_get_scanning(device) && !wifi->allow_full_scan)
1265 if (connman_device_get_scanning(device))
1269 connman_device_ref(device);
1271 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1274 connman_device_set_scanning(device,
1275 CONNMAN_SERVICE_TYPE_WIFI, true);
1277 connman_device_unref(device);
1282 static void hidden_free(struct hidden_params *hidden)
1287 if (hidden->scan_params)
1288 g_supplicant_free_scan_params(hidden->scan_params);
1289 g_free(hidden->identity);
1290 g_free(hidden->passphrase);
1291 g_free(hidden->security);
1295 #if defined TIZEN_EXT
1296 static void service_state_changed(struct connman_service *service,
1297 enum connman_service_state state);
1299 static int network_connect(struct connman_network *network);
1301 static struct connman_notifier notifier = {
1303 .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
1304 .service_state_changed = service_state_changed,
1307 static void service_state_changed(struct connman_service *service,
1308 enum connman_service_state state)
1310 enum connman_service_type type;
1312 type = connman_service_get_type(service);
1313 if (type != CONNMAN_SERVICE_TYPE_WIFI)
1316 DBG("service %p state %d", service, state);
1319 case CONNMAN_SERVICE_STATE_READY:
1320 case CONNMAN_SERVICE_STATE_ONLINE:
1321 case CONNMAN_SERVICE_STATE_FAILURE:
1322 connman_notifier_unregister(¬ifier);
1323 is_wifi_notifier_registered = FALSE;
1325 __connman_device_request_scan(type);
1334 static void scan_callback(int result, GSupplicantInterface *interface,
1337 struct connman_device *device = user_data;
1338 struct wifi_data *wifi = connman_device_get_data(device);
1341 DBG("result %d wifi %p", result, wifi);
1344 if (wifi->hidden && !wifi->postpone_hidden) {
1345 connman_network_clear_hidden(wifi->hidden->user_data);
1346 hidden_free(wifi->hidden);
1347 wifi->hidden = NULL;
1350 if (wifi->scan_params) {
1351 g_supplicant_free_scan_params(wifi->scan_params);
1352 wifi->scan_params = NULL;
1357 connman_device_reset_scanning(device);
1359 /* User is connecting to a hidden AP, let's wait for finished event */
1360 if (wifi && wifi->hidden && wifi->postpone_hidden) {
1361 GSupplicantScanParams *scan_params;
1364 wifi->postpone_hidden = false;
1365 scan_params = wifi->hidden->scan_params;
1366 wifi->hidden->scan_params = NULL;
1368 reset_autoscan(device);
1370 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1371 scan_callback, device);
1375 /* On error, let's recall scan_callback, which will cleanup */
1376 return scan_callback(ret, interface, user_data);
1379 #if defined TIZEN_EXT
1380 if (wifi && wifi->allow_full_scan) {
1382 DBG("Trigger Full Channel Scan");
1383 wifi->allow_full_scan = FALSE;
1385 ret = g_supplicant_interface_scan(wifi->interface, NULL,
1386 scan_callback, device);
1390 /* On error, let's recall scan_callback, which will cleanup */
1391 return scan_callback(ret, interface, user_data);
1395 scanning = connman_device_get_scanning(device);
1397 connman_device_set_scanning(device,
1398 CONNMAN_SERVICE_TYPE_WIFI, false);
1400 if (result != -ENOLINK)
1401 #if defined TIZEN_EXT
1404 start_autoscan(device);
1407 * If we are here then we were scanning; however, if we are
1408 * also mid-flight disabling the interface, then wifi_disable
1409 * has already cleared the device scanning state and
1410 * unreferenced the device, obviating the need to do it here.
1414 connman_device_unref(device);
1416 #if defined TIZEN_EXT
1417 if (wifi && wifi->scan_pending_network && result != -EIO) {
1418 network_connect(wifi->scan_pending_network);
1419 wifi->scan_pending_network = NULL;
1420 connman_network_set_connecting(wifi->network);
1423 if (is_wifi_notifier_registered != true &&
1424 wifi_first_scan == true && found_with_first_scan == true) {
1425 wifi_first_scan = false;
1426 found_with_first_scan = false;
1428 connman_notifier_register(¬ifier);
1429 is_wifi_notifier_registered = true;
1434 static void scan_callback_hidden(int result,
1435 GSupplicantInterface *interface, void *user_data)
1437 struct connman_device *device = user_data;
1438 struct wifi_data *wifi = connman_device_get_data(device);
1439 GSupplicantScanParams *scan_params;
1442 DBG("result %d wifi %p", result, wifi);
1447 /* User is trying to connect to a hidden AP */
1448 if (wifi->hidden && wifi->postpone_hidden)
1451 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1455 if (get_hidden_connections_params(wifi, scan_params) > 0) {
1456 ret = g_supplicant_interface_scan(wifi->interface,
1458 scan_callback_hidden,
1464 g_supplicant_free_scan_params(scan_params);
1467 scan_callback(result, interface, user_data);
1470 static gboolean autoscan_timeout(gpointer data)
1472 struct connman_device *device = data;
1473 struct wifi_data *wifi = connman_device_get_data(device);
1474 struct autoscan_params *autoscan;
1480 autoscan = wifi->autoscan;
1482 if (autoscan->interval <= 0) {
1483 interval = autoscan->base;
1486 interval = autoscan->interval * autoscan->base;
1488 #if defined TIZEN_EXT
1489 if (autoscan->interval >= autoscan->limit)
1491 if (interval > autoscan->limit)
1493 interval = autoscan->limit;
1495 throw_wifi_scan(wifi->device, scan_callback_hidden);
1498 DBG("interval %d", interval);
1500 autoscan->interval = interval;
1502 autoscan->timeout = g_timeout_add_seconds(interval,
1503 autoscan_timeout, device);
1508 static void start_autoscan(struct connman_device *device)
1510 struct wifi_data *wifi = connman_device_get_data(device);
1511 struct autoscan_params *autoscan;
1518 if (wifi->p2p_device)
1521 if (wifi->connected)
1524 autoscan = wifi->autoscan;
1528 if (autoscan->timeout > 0 || autoscan->interval > 0)
1531 connman_device_ref(device);
1533 autoscan_timeout(device);
1536 static struct autoscan_params *parse_autoscan_params(const char *params)
1538 struct autoscan_params *autoscan;
1543 DBG("Emulating autoscan");
1545 list_params = g_strsplit(params, ":", 0);
1546 if (list_params == 0)
1549 if (g_strv_length(list_params) < 3) {
1550 g_strfreev(list_params);
1554 base = atoi(list_params[1]);
1555 limit = atoi(list_params[2]);
1557 g_strfreev(list_params);
1559 autoscan = g_try_malloc0(sizeof(struct autoscan_params));
1561 DBG("Could not allocate memory for autoscan");
1565 DBG("base %d - limit %d", base, limit);
1566 autoscan->base = base;
1567 autoscan->limit = limit;
1572 static void setup_autoscan(struct wifi_data *wifi)
1574 if (!wifi->autoscan)
1575 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
1577 start_autoscan(wifi->device);
1580 static void finalize_interface_creation(struct wifi_data *wifi)
1582 DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
1584 if (!wifi->device) {
1585 connman_error("WiFi device not set");
1589 connman_device_set_powered(wifi->device, true);
1591 if (!connman_setting_get_bool("BackgroundScanning"))
1594 if (wifi->p2p_device)
1597 setup_autoscan(wifi);
1600 static void interface_create_callback(int result,
1601 GSupplicantInterface *interface,
1604 struct wifi_data *wifi = user_data;
1606 DBG("result %d ifname %s, wifi %p", result,
1607 g_supplicant_interface_get_ifname(interface),
1610 if (result < 0 || !wifi)
1613 wifi->interface = interface;
1614 g_supplicant_interface_set_data(interface, wifi);
1616 if (g_supplicant_interface_get_ready(interface)) {
1617 wifi->interface_ready = true;
1618 finalize_interface_creation(wifi);
1622 static int wifi_enable(struct connman_device *device)
1624 struct wifi_data *wifi = connman_device_get_data(device);
1627 const char *driver = connman_option_get_string("wifi");
1630 DBG("device %p %p", device, wifi);
1632 index = connman_device_get_index(device);
1633 if (!wifi || index < 0)
1636 if (is_p2p_connecting())
1637 return -EINPROGRESS;
1639 interface = connman_inet_ifname(index);
1640 ret = g_supplicant_interface_create(interface, driver, NULL,
1641 interface_create_callback,
1648 return -EINPROGRESS;
1651 static int wifi_disable(struct connman_device *device)
1653 struct wifi_data *wifi = connman_device_get_data(device);
1656 DBG("device %p wifi %p", device, wifi);
1661 wifi->connected = false;
1662 wifi->disconnecting = false;
1664 if (wifi->pending_network)
1665 wifi->pending_network = NULL;
1667 stop_autoscan(device);
1669 if (wifi->p2p_find_timeout) {
1670 g_source_remove(wifi->p2p_find_timeout);
1671 wifi->p2p_find_timeout = 0;
1672 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1673 connman_device_unref(wifi->device);
1676 /* In case of a user scan, device is still referenced */
1677 if (connman_device_get_scanning(device)) {
1678 connman_device_set_scanning(device,
1679 CONNMAN_SERVICE_TYPE_WIFI, false);
1680 connman_device_unref(wifi->device);
1683 remove_networks(device, wifi);
1685 #if defined TIZEN_EXT
1686 wifi->scan_pending_network = NULL;
1688 if (is_wifi_notifier_registered == true) {
1689 connman_notifier_unregister(¬ifier);
1690 is_wifi_notifier_registered = false;
1694 ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
1698 return -EINPROGRESS;
1701 struct last_connected {
1707 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
1709 GTimeVal *aval = (GTimeVal *)a;
1710 GTimeVal *bval = (GTimeVal *)b;
1712 /* Note that the sort order is descending */
1713 if (aval->tv_sec < bval->tv_sec)
1716 if (aval->tv_sec > bval->tv_sec)
1722 static void free_entry(gpointer data)
1724 struct last_connected *entry = data;
1726 g_free(entry->ssid);
1730 static int get_latest_connections(int max_ssids,
1731 GSupplicantScanParams *scan_data)
1733 GSequenceIter *iter;
1734 GSequence *latest_list;
1735 struct last_connected *entry;
1744 latest_list = g_sequence_new(free_entry);
1748 services = connman_storage_get_services();
1749 for (i = 0; services && services[i]; i++) {
1750 if (strncmp(services[i], "wifi_", 5) != 0)
1753 keyfile = connman_storage_load_service(services[i]);
1757 str = g_key_file_get_string(keyfile,
1758 services[i], "Favorite", NULL);
1759 if (!str || g_strcmp0(str, "true")) {
1761 g_key_file_free(keyfile);
1766 str = g_key_file_get_string(keyfile,
1767 services[i], "AutoConnect", NULL);
1768 if (!str || g_strcmp0(str, "true")) {
1770 g_key_file_free(keyfile);
1775 str = g_key_file_get_string(keyfile,
1776 services[i], "Modified", NULL);
1778 g_key_file_free(keyfile);
1781 g_time_val_from_iso8601(str, &modified);
1784 ssid = g_key_file_get_string(keyfile,
1785 services[i], "SSID", NULL);
1787 freq = g_key_file_get_integer(keyfile, services[i],
1790 entry = g_try_new(struct last_connected, 1);
1792 g_sequence_free(latest_list);
1793 g_key_file_free(keyfile);
1799 entry->modified = modified;
1802 g_sequence_insert_sorted(latest_list, entry,
1808 g_key_file_free(keyfile);
1811 g_strfreev(services);
1813 num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1815 iter = g_sequence_get_begin_iter(latest_list);
1817 for (i = 0; i < num_ssids; i++) {
1818 entry = g_sequence_get(iter);
1820 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1821 entry->modified.tv_sec);
1823 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1824 max_ssids, entry->ssid);
1826 iter = g_sequence_iter_next(iter);
1829 g_sequence_free(latest_list);
1833 static int wifi_scan_simple(struct connman_device *device)
1835 reset_autoscan(device);
1837 return throw_wifi_scan(device, scan_callback_hidden);
1840 static gboolean p2p_find_stop(gpointer data)
1842 struct connman_device *device = data;
1843 struct wifi_data *wifi = connman_device_get_data(device);
1847 wifi->p2p_find_timeout = 0;
1849 connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1851 g_supplicant_interface_p2p_stop_find(wifi->interface);
1853 connman_device_unref(device);
1854 reset_autoscan(device);
1859 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1862 struct connman_device *device = user_data;
1863 struct wifi_data *wifi = connman_device_get_data(device);
1865 DBG("result %d wifi %p", result, wifi);
1867 if (wifi->p2p_find_timeout) {
1868 g_source_remove(wifi->p2p_find_timeout);
1869 wifi->p2p_find_timeout = 0;
1875 wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1876 p2p_find_stop, device);
1877 if (!wifi->p2p_find_timeout)
1882 p2p_find_stop(device);
1885 static int p2p_find(struct connman_device *device)
1887 struct wifi_data *wifi;
1892 if (!p2p_technology)
1895 wifi = connman_device_get_data(device);
1897 if (g_supplicant_interface_is_p2p_finding(wifi->interface))
1900 reset_autoscan(device);
1901 connman_device_ref(device);
1903 ret = g_supplicant_interface_p2p_find(wifi->interface,
1904 p2p_find_callback, device);
1906 connman_device_unref(device);
1907 start_autoscan(device);
1909 connman_device_set_scanning(device,
1910 CONNMAN_SERVICE_TYPE_P2P, true);
1916 #if defined TIZEN_EXT
1917 static void specific_scan_callback(int result, GSupplicantInterface *interface,
1920 struct connman_device *device = user_data;
1921 struct wifi_data *wifi = connman_device_get_data(device);
1924 DBG("result %d wifi %p", result, wifi);
1926 if (wifi && wifi->scan_params) {
1927 g_supplicant_free_scan_params(wifi->scan_params);
1928 wifi->scan_params = NULL;
1931 scanning = connman_device_get_scanning(device);
1933 connman_device_set_scanning(device,
1934 CONNMAN_SERVICE_TYPE_WIFI, false);
1935 connman_device_unref(device);
1939 static int wifi_specific_scan(enum connman_service_type type,
1940 struct connman_device *device, int scan_type,
1941 GSList *specific_scan_list, void *user_data)
1943 GSList *list = NULL;
1945 struct wifi_data *wifi = connman_device_get_data(device);
1946 GSupplicantScanParams *scan_params = NULL;
1947 struct scan_ssid *scan_ssid = NULL;
1956 if (wifi->p2p_device)
1959 if (type == CONNMAN_SERVICE_TYPE_P2P)
1960 return p2p_find(device);
1962 if (wifi->tethering)
1965 scanning = connman_device_get_scanning(device);
1969 DBG("scan_type: %d", scan_type);
1970 if (scan_type == 1) { /* ssid based scan */
1971 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1973 DBG("Failed to allocate memory.");
1977 for (list = specific_scan_list; list; list = list->next) {
1978 ssid = (char *)list->data;
1979 int ssid_len = strlen(ssid);
1981 scan_ssid = g_try_new0(struct scan_ssid, 1);
1983 DBG("Failed to allocate memory.");
1984 g_supplicant_free_scan_params(scan_params);
1988 memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
1989 DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len);
1990 scan_ssid->ssid_len = ssid_len;
1991 scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
1994 scan_params->num_ssids = count;
1996 } else if (scan_type == 2) { /* frequency based scan */
1998 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2000 DBG("Failed to allocate memory.");
2004 guint num_freqs = g_slist_length(specific_scan_list);
2005 DBG("num_freqs: %d", num_freqs);
2007 scan_params->freqs = g_try_new0(uint16_t, num_freqs);
2008 if (!scan_params->freqs) {
2009 DBG("Failed to allocate memory.");
2010 g_free(scan_params);
2015 for (list = specific_scan_list; list; list = list->next) {
2016 freq = (int)list->data;
2018 scan_params->freqs[count] = freq;
2019 DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
2022 scan_params->num_freqs = count;
2025 DBG("Invalid scan");
2029 reset_autoscan(device);
2030 connman_device_ref(device);
2032 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2033 specific_scan_callback, device);
2036 connman_device_set_scanning(device,
2037 CONNMAN_SERVICE_TYPE_WIFI, true);
2039 g_supplicant_free_scan_params(scan_params);
2040 connman_device_unref(device);
2048 * Note that the hidden scan is only used when connecting to this specific
2049 * hidden AP first time. It is not used when system autoconnects to hidden AP.
2051 static int wifi_scan(enum connman_service_type type,
2052 struct connman_device *device,
2053 const char *ssid, unsigned int ssid_len,
2054 const char *identity, const char* passphrase,
2055 const char *security, void *user_data)
2057 struct wifi_data *wifi = connman_device_get_data(device);
2058 GSupplicantScanParams *scan_params = NULL;
2059 struct scan_ssid *scan_ssid;
2060 struct hidden_params *hidden;
2062 int driver_max_ssids = 0;
2069 if (wifi->p2p_device)
2072 if (type == CONNMAN_SERVICE_TYPE_P2P)
2073 return p2p_find(device);
2075 DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
2077 if (wifi->tethering)
2080 scanning = connman_device_get_scanning(device);
2082 if (!ssid || ssid_len == 0 || ssid_len > 32) {
2086 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
2088 DBG("max ssids %d", driver_max_ssids);
2089 if (driver_max_ssids == 0)
2090 return wifi_scan_simple(device);
2094 if (scanning && wifi->hidden && wifi->postpone_hidden)
2100 scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
2105 scan_ssid = g_try_new(struct scan_ssid, 1);
2107 g_free(scan_params);
2111 memcpy(scan_ssid->ssid, ssid, ssid_len);
2112 scan_ssid->ssid_len = ssid_len;
2113 scan_params->ssids = g_slist_prepend(scan_params->ssids,
2115 scan_params->num_ssids = 1;
2117 hidden = g_try_new0(struct hidden_params, 1);
2119 g_supplicant_free_scan_params(scan_params);
2124 hidden_free(wifi->hidden);
2125 wifi->hidden = NULL;
2128 memcpy(hidden->ssid, ssid, ssid_len);
2129 hidden->ssid_len = ssid_len;
2130 hidden->identity = g_strdup(identity);
2131 hidden->passphrase = g_strdup(passphrase);
2132 hidden->security = g_strdup(security);
2133 hidden->user_data = user_data;
2134 wifi->hidden = hidden;
2137 /* Let's keep this active scan for later,
2138 * when current scan will be over. */
2139 wifi->postpone_hidden = TRUE;
2140 hidden->scan_params = scan_params;
2144 } else if (wifi->connected) {
2145 g_supplicant_free_scan_params(scan_params);
2146 return wifi_scan_simple(device);
2148 ret = get_latest_connections(driver_max_ssids, scan_params);
2150 g_supplicant_free_scan_params(scan_params);
2151 return wifi_scan_simple(device);
2155 connman_device_ref(device);
2157 reset_autoscan(device);
2159 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
2160 scan_callback, device);
2163 connman_device_set_scanning(device,
2164 CONNMAN_SERVICE_TYPE_WIFI, true);
2165 #if defined TIZEN_EXT
2166 /*To allow the Full Scan after ssid based scan, set the flag here
2167 It is required because Tizen does not use the ConnMan specific
2168 backgroung Scan feature.Tizen has added the BG Scan feature in
2169 net-config. To sync with up ConnMan, we need to issue the Full Scan
2170 after SSID specific scan.*/
2171 wifi->allow_full_scan = TRUE;
2174 g_supplicant_free_scan_params(scan_params);
2175 connman_device_unref(device);
2178 hidden_free(wifi->hidden);
2179 wifi->hidden = NULL;
2186 static void wifi_regdom_callback(int result,
2190 struct connman_device *device = user_data;
2192 connman_device_regdom_notify(device, result, alpha2);
2194 connman_device_unref(device);
2197 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
2199 struct wifi_data *wifi = connman_device_get_data(device);
2205 connman_device_ref(device);
2207 ret = g_supplicant_interface_set_country(wifi->interface,
2208 wifi_regdom_callback,
2211 connman_device_unref(device);
2216 static struct connman_device_driver wifi_ng_driver = {
2218 .type = CONNMAN_DEVICE_TYPE_WIFI,
2219 .priority = CONNMAN_DEVICE_PRIORITY_LOW,
2220 .probe = wifi_probe,
2221 .remove = wifi_remove,
2222 .enable = wifi_enable,
2223 .disable = wifi_disable,
2225 .set_regdom = wifi_set_regdom,
2226 #if defined TIZEN_EXT
2227 .specific_scan = wifi_specific_scan,
2231 static void system_ready(void)
2235 if (connman_device_driver_register(&wifi_ng_driver) < 0)
2236 connman_error("Failed to register WiFi driver");
2239 static void system_killed(void)
2243 connman_device_driver_unregister(&wifi_ng_driver);
2246 static int network_probe(struct connman_network *network)
2248 DBG("network %p", network);
2253 static void network_remove(struct connman_network *network)
2255 struct connman_device *device = connman_network_get_device(network);
2256 struct wifi_data *wifi;
2258 DBG("network %p", network);
2260 wifi = connman_device_get_data(device);
2264 if (wifi->network != network)
2267 wifi->network = NULL;
2269 #if defined TIZEN_EXT
2270 wifi->disconnecting = false;
2272 if (wifi->pending_network == network)
2273 wifi->pending_network = NULL;
2275 if (wifi->scan_pending_network == network)
2276 wifi->scan_pending_network = NULL;
2280 static void connect_callback(int result, GSupplicantInterface *interface,
2283 #if defined TIZEN_EXT
2285 struct wifi_data *wifi;
2287 struct connman_network *network = user_data;
2289 DBG("network %p result %d", network, result);
2291 #if defined TIZEN_EXT
2292 for (list = iface_list; list; list = list->next) {
2295 if (wifi && wifi->network == network)
2299 /* wifi_data may be invalid because wifi is already disabled */
2304 if (result == -ENOKEY) {
2305 connman_network_set_error(network,
2306 CONNMAN_NETWORK_ERROR_INVALID_KEY);
2307 } else if (result < 0) {
2308 connman_network_set_error(network,
2309 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
2312 connman_network_unref(network);
2315 static GSupplicantSecurity network_security(const char *security)
2317 if (g_str_equal(security, "none"))
2318 return G_SUPPLICANT_SECURITY_NONE;
2319 else if (g_str_equal(security, "wep"))
2320 return G_SUPPLICANT_SECURITY_WEP;
2321 else if (g_str_equal(security, "psk"))
2322 return G_SUPPLICANT_SECURITY_PSK;
2323 else if (g_str_equal(security, "wpa"))
2324 return G_SUPPLICANT_SECURITY_PSK;
2325 else if (g_str_equal(security, "rsn"))
2326 return G_SUPPLICANT_SECURITY_PSK;
2327 else if (g_str_equal(security, "ieee8021x"))
2328 return G_SUPPLICANT_SECURITY_IEEE8021X;
2329 #if defined TIZEN_EXT
2330 else if (g_str_equal(security, "ft_psk") == TRUE)
2331 return G_SUPPLICANT_SECURITY_FT_PSK;
2332 else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
2333 return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
2336 return G_SUPPLICANT_SECURITY_UNKNOWN;
2339 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
2341 const char *security;
2343 memset(ssid, 0, sizeof(*ssid));
2344 ssid->mode = G_SUPPLICANT_MODE_INFRA;
2345 ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
2347 ssid->scan_ssid = 1;
2348 security = connman_network_get_string(network, "WiFi.Security");
2349 ssid->security = network_security(security);
2350 ssid->passphrase = connman_network_get_string(network,
2352 #if defined TIZEN_EXT
2353 /* Decrypt the passphrase
2355 static gchar* origin_value = NULL;
2356 gchar *passphrase = g_strdup(ssid->passphrase);
2357 g_free(origin_value);
2358 origin_value = NULL;
2360 if (passphrase && g_strcmp0(passphrase, "") != 0) {
2361 origin_value = send_cryptographic_request(passphrase,
2362 "DecryptPassphrase");
2364 if (!origin_value) {
2365 DBG("Decryption failed");
2367 DBG("Decryption succeeded");
2368 ssid->passphrase = origin_value;
2374 ssid->eap = connman_network_get_string(network, "WiFi.EAP");
2377 * If our private key password is unset,
2378 * we use the supplied passphrase. That is needed
2379 * for PEAP where 2 passphrases (identity and client
2380 * cert may have to be provided.
2382 if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
2383 connman_network_set_string(network,
2384 "WiFi.PrivateKeyPassphrase",
2386 /* We must have an identity for both PEAP and TLS */
2387 ssid->identity = connman_network_get_string(network, "WiFi.Identity");
2389 /* Use agent provided identity as a fallback */
2390 if (!ssid->identity || strlen(ssid->identity) == 0)
2391 ssid->identity = connman_network_get_string(network,
2392 "WiFi.AgentIdentity");
2394 ssid->ca_cert_path = connman_network_get_string(network,
2396 ssid->client_cert_path = connman_network_get_string(network,
2397 "WiFi.ClientCertFile");
2398 ssid->private_key_path = connman_network_get_string(network,
2399 "WiFi.PrivateKeyFile");
2400 ssid->private_key_passphrase = connman_network_get_string(network,
2401 "WiFi.PrivateKeyPassphrase");
2402 ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
2404 ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
2405 ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
2407 #if defined TIZEN_EXT
2408 ssid->bssid = connman_network_get_bssid(network);
2410 #if defined TIZEN_EXT
2411 ssid->freq = connman_network_get_frequency(network);
2414 if (connman_setting_get_bool("BackgroundScanning"))
2415 ssid->bgscan = BGSCAN_DEFAULT;
2418 static int network_connect(struct connman_network *network)
2420 struct connman_device *device = connman_network_get_device(network);
2421 struct wifi_data *wifi;
2422 GSupplicantInterface *interface;
2423 GSupplicantSSID *ssid;
2425 DBG("network %p", network);
2430 wifi = connman_device_get_data(device);
2434 ssid = g_try_malloc0(sizeof(GSupplicantSSID));
2438 interface = wifi->interface;
2440 ssid_init(ssid, network);
2442 if (wifi->disconnecting) {
2443 wifi->pending_network = network;
2446 wifi->network = connman_network_ref(network);
2448 #if defined TIZEN_EXT
2449 wifi->scan_pending_network = NULL;
2452 return g_supplicant_interface_connect(interface, ssid,
2453 connect_callback, network);
2456 return -EINPROGRESS;
2459 static void disconnect_callback(int result, GSupplicantInterface *interface,
2462 #if defined TIZEN_EXT
2464 struct wifi_data *wifi;
2465 struct connman_network *network = user_data;
2467 DBG("network %p result %d", network, result);
2469 for (list = iface_list; list; list = list->next) {
2472 if (wifi->network == NULL && wifi->disconnecting == true)
2473 wifi->disconnecting = false;
2475 if (wifi->network == network)
2479 /* wifi_data may be invalid because wifi is already disabled */
2484 struct wifi_data *wifi = user_data;
2487 DBG("result %d supplicant interface %p wifi %p",
2488 result, interface, wifi);
2490 if (result == -ECONNABORTED) {
2491 DBG("wifi interface no longer available");
2495 if (wifi->network) {
2497 * if result < 0 supplican return an error because
2498 * the network is not current.
2499 * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
2500 * failed, call connman_network_set_connected to report
2501 * disconnect is completed.
2504 connman_network_set_connected(wifi->network, false);
2507 wifi->network = NULL;
2509 wifi->disconnecting = false;
2511 if (wifi->pending_network) {
2512 network_connect(wifi->pending_network);
2513 wifi->pending_network = NULL;
2516 start_autoscan(wifi->device);
2519 static int network_disconnect(struct connman_network *network)
2521 struct connman_device *device = connman_network_get_device(network);
2522 struct wifi_data *wifi;
2524 #if defined TIZEN_EXT
2525 struct connman_service *service;
2528 DBG("network %p", network);
2530 wifi = connman_device_get_data(device);
2531 if (!wifi || !wifi->interface)
2534 #if defined TIZEN_EXT
2535 if (connman_network_get_associating(network) == true) {
2536 connman_network_clear_associating(network);
2537 connman_network_set_bool(network, "WiFi.UseWPS", false);
2539 service = connman_service_lookup_from_network(network);
2541 if (service != NULL &&
2542 (__connman_service_is_connected_state(service,
2543 CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
2544 __connman_service_is_connected_state(service,
2545 CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
2546 (connman_service_get_favorite(service) == false))
2547 __connman_service_set_passphrase(service, NULL);
2550 if (wifi->pending_network == network)
2551 wifi->pending_network = NULL;
2553 if (wifi->scan_pending_network == network)
2554 wifi->scan_pending_network = NULL;
2557 connman_network_set_associating(network, false);
2559 if (wifi->disconnecting)
2562 wifi->disconnecting = true;
2564 #if defined TIZEN_EXT
2565 err = g_supplicant_interface_disconnect(wifi->interface,
2566 disconnect_callback, network);
2568 err = g_supplicant_interface_disconnect(wifi->interface,
2569 disconnect_callback, wifi);
2573 wifi->disconnecting = false;
2578 static struct connman_network_driver network_driver = {
2580 .type = CONNMAN_NETWORK_TYPE_WIFI,
2581 .priority = CONNMAN_NETWORK_PRIORITY_LOW,
2582 .probe = network_probe,
2583 .remove = network_remove,
2584 .connect = network_connect,
2585 .disconnect = network_disconnect,
2588 static void interface_added(GSupplicantInterface *interface)
2590 const char *ifname = g_supplicant_interface_get_ifname(interface);
2591 const char *driver = g_supplicant_interface_get_driver(interface);
2592 struct wifi_data *wifi;
2594 wifi = g_supplicant_interface_get_data(interface);
2596 wifi = get_pending_wifi_data(ifname);
2600 g_supplicant_interface_set_data(interface, wifi);
2601 p2p_iface_list = g_list_append(p2p_iface_list, wifi);
2602 wifi->p2p_device = true;
2605 DBG("ifname %s driver %s wifi %p tethering %d",
2606 ifname, driver, wifi, wifi->tethering);
2608 if (!wifi->device) {
2609 connman_error("WiFi device not set");
2613 connman_device_set_powered(wifi->device, true);
2616 static bool is_idle(struct wifi_data *wifi)
2618 DBG("state %d", wifi->state);
2620 switch (wifi->state) {
2621 case G_SUPPLICANT_STATE_UNKNOWN:
2622 case G_SUPPLICANT_STATE_DISABLED:
2623 case G_SUPPLICANT_STATE_DISCONNECTED:
2624 case G_SUPPLICANT_STATE_INACTIVE:
2625 case G_SUPPLICANT_STATE_SCANNING:
2628 case G_SUPPLICANT_STATE_AUTHENTICATING:
2629 case G_SUPPLICANT_STATE_ASSOCIATING:
2630 case G_SUPPLICANT_STATE_ASSOCIATED:
2631 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2632 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2633 case G_SUPPLICANT_STATE_COMPLETED:
2640 static bool is_idle_wps(GSupplicantInterface *interface,
2641 struct wifi_data *wifi)
2643 /* First, let's check if WPS processing did not went wrong */
2644 if (g_supplicant_interface_get_wps_state(interface) ==
2645 G_SUPPLICANT_WPS_STATE_FAIL)
2648 /* Unlike normal connection, being associated while processing wps
2649 * actually means that we are idling. */
2650 switch (wifi->state) {
2651 case G_SUPPLICANT_STATE_UNKNOWN:
2652 case G_SUPPLICANT_STATE_DISABLED:
2653 case G_SUPPLICANT_STATE_DISCONNECTED:
2654 case G_SUPPLICANT_STATE_INACTIVE:
2655 case G_SUPPLICANT_STATE_SCANNING:
2656 case G_SUPPLICANT_STATE_ASSOCIATED:
2658 case G_SUPPLICANT_STATE_AUTHENTICATING:
2659 case G_SUPPLICANT_STATE_ASSOCIATING:
2660 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2661 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2662 case G_SUPPLICANT_STATE_COMPLETED:
2669 static bool handle_wps_completion(GSupplicantInterface *interface,
2670 struct connman_network *network,
2671 struct connman_device *device,
2672 struct wifi_data *wifi)
2676 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2678 const unsigned char *ssid, *wps_ssid;
2679 unsigned int ssid_len, wps_ssid_len;
2680 const char *wps_key;
2682 /* Checking if we got associated with requested
2684 ssid = connman_network_get_blob(network, "WiFi.SSID",
2687 wps_ssid = g_supplicant_interface_get_wps_ssid(
2688 interface, &wps_ssid_len);
2690 if (!wps_ssid || wps_ssid_len != ssid_len ||
2691 memcmp(ssid, wps_ssid, ssid_len) != 0) {
2692 connman_network_set_associating(network, false);
2693 #if defined TIZEN_EXT
2694 g_supplicant_interface_disconnect(wifi->interface,
2695 disconnect_callback, wifi->network);
2697 connman_network_set_bool(network, "WiFi.UseWPS", false);
2698 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2700 g_supplicant_interface_disconnect(wifi->interface,
2701 disconnect_callback, wifi);
2706 wps_key = g_supplicant_interface_get_wps_key(interface);
2707 #if defined TIZEN_EXT
2708 /* Check the passphrase and encrypt it
2710 gchar *encrypted_value = NULL;
2711 gchar *passphrase = g_strdup(wps_key);
2713 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2715 if (check_passphrase_ext(network, passphrase) < 0) {
2716 DBG("[WPS] Invalid passphrase");
2721 encrypted_value = send_cryptographic_request(passphrase, "EncryptPassphrase");
2725 if (!encrypted_value) {
2726 DBG("[WPS] Encryption failed");
2729 DBG("[WPS] Encryption succeeded");
2730 connman_network_set_string(network, "WiFi.Passphrase",
2732 g_free(encrypted_value);
2735 connman_network_set_string(network, "WiFi.Passphrase",
2738 connman_network_set_string(network, "WiFi.PinWPS", NULL);
2745 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
2746 struct connman_network *network,
2747 struct wifi_data *wifi)
2749 #if defined TIZEN_EXT
2750 const char *security;
2751 struct connman_service *service;
2753 if (wifi->connected)
2756 security = connman_network_get_string(network, "WiFi.Security");
2758 if (security && g_str_equal(security, "ieee8021x") == true &&
2759 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2761 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2766 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2769 struct connman_service *service;
2771 if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
2774 if (wifi->connected)
2778 service = connman_service_lookup_from_network(network);
2784 if (connman_service_get_favorite(service)) {
2785 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
2790 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
2795 #if defined TIZEN_EXT
2796 static bool handle_wifi_assoc_retry(struct connman_network *network,
2797 struct wifi_data *wifi)
2799 const char *security;
2801 if (!wifi->network || wifi->connected || wifi->disconnecting ||
2802 connman_network_get_connecting(network) != true) {
2803 wifi->assoc_retry_count = 0;
2807 if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
2808 wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
2809 wifi->assoc_retry_count = 0;
2813 security = connman_network_get_string(network, "WiFi.Security");
2814 if (security && g_str_equal(security, "ieee8021x") == true &&
2815 wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
2816 wifi->assoc_retry_count = 0;
2820 if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
2821 wifi->assoc_retry_count = 0;
2823 /* Honestly it's not an invalid-key error,
2824 * however QA team recommends that the invalid-key error
2825 * might be better to display for user experience.
2827 connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
2836 static void interface_state(GSupplicantInterface *interface)
2838 struct connman_network *network;
2839 struct connman_device *device;
2840 struct wifi_data *wifi;
2841 GSupplicantState state = g_supplicant_interface_get_state(interface);
2844 wifi = g_supplicant_interface_get_data(interface);
2846 DBG("wifi %p interface state %d", wifi, state);
2851 device = wifi->device;
2855 if (g_supplicant_interface_get_ready(interface) &&
2856 !wifi->interface_ready) {
2857 wifi->interface_ready = true;
2858 finalize_interface_creation(wifi);
2861 network = wifi->network;
2866 case G_SUPPLICANT_STATE_SCANNING:
2869 case G_SUPPLICANT_STATE_AUTHENTICATING:
2870 case G_SUPPLICANT_STATE_ASSOCIATING:
2871 #if defined TIZEN_EXT
2872 reset_autoscan(device);
2874 stop_autoscan(device);
2877 if (!wifi->connected)
2878 connman_network_set_associating(network, true);
2882 case G_SUPPLICANT_STATE_COMPLETED:
2883 #if defined TIZEN_EXT
2884 /* though it should be already reset: */
2885 reset_autoscan(device);
2887 wifi->assoc_retry_count = 0;
2889 wifi->scan_pending_network = NULL;
2891 /* should be cleared scanning flag */
2892 bool scanning = connman_device_get_scanning(device);
2894 connman_device_set_scanning(device,
2895 CONNMAN_SERVICE_TYPE_WIFI, false);
2896 connman_device_unref(device);
2899 /* though it should be already stopped: */
2900 stop_autoscan(device);
2903 if (!handle_wps_completion(interface, network, device, wifi))
2906 connman_network_set_connected(network, true);
2907 wifi->disconnect_code = 0;
2908 wifi->assoc_code = 0;
2911 case G_SUPPLICANT_STATE_DISCONNECTED:
2913 * If we're in one of the idle modes, we have
2914 * not started association yet and thus setting
2915 * those ones to FALSE could cancel an association
2918 wps = connman_network_get_bool(network, "WiFi.UseWPS");
2920 if (is_idle_wps(interface, wifi))
2926 /* If previous state was 4way-handshake, then
2927 * it's either: psk was incorrect and thus we retry
2928 * or if we reach the maximum retries we declare the
2930 if (handle_4way_handshake_failure(interface,
2934 /* See table 8-36 Reason codes in IEEE Std 802.11 */
2935 switch (wifi->disconnect_code) {
2936 case 1: /* Unspecified reason */
2937 /* Let's assume it's because we got blocked */
2939 case 6: /* Class 2 frame received from nonauthenticated STA */
2940 connman_network_set_error(network,
2941 CONNMAN_NETWORK_ERROR_BLOCKED);
2949 /* We disable the selected network, if not then
2950 * wpa_supplicant will loop retrying */
2951 if (g_supplicant_interface_enable_selected_network(interface,
2953 DBG("Could not disables selected network");
2955 #if defined TIZEN_EXT
2958 err = g_supplicant_interface_remove_network(wifi->interface);
2960 DBG("Failed to remove network(%d)", err);
2963 /* Some of Wi-Fi networks are not comply Wi-Fi specification.
2964 * Retry association until its retry count is expired */
2965 if (handle_wifi_assoc_retry(network, wifi) == true) {
2966 throw_wifi_scan(wifi->device, scan_callback);
2967 wifi->scan_pending_network = wifi->network;
2971 if(wifi->disconnect_code > 0){
2972 DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
2973 connman_network_set_disconnect_reason(network, wifi->disconnect_code);
2976 /* To avoid unnecessary repeated association in wpa_supplicant,
2977 * "RemoveNetwork" should be made when Wi-Fi is disconnected */
2978 if (wps != true && wifi->network && wifi->disconnecting == false) {
2979 wifi->disconnecting = true;
2980 err = g_supplicant_interface_disconnect(wifi->interface,
2981 disconnect_callback, wifi->network);
2983 wifi->disconnecting = false;
2985 connman_network_set_connected(network, false);
2986 connman_network_set_associating(network, false);
2988 start_autoscan(device);
2994 connman_network_set_connected(network, false);
2995 connman_network_set_associating(network, false);
2996 wifi->disconnecting = false;
2998 start_autoscan(device);
3002 case G_SUPPLICANT_STATE_INACTIVE:
3003 #if defined TIZEN_EXT
3004 if (handle_wps_completion(interface, network, device, wifi) == false)
3007 connman_network_set_associating(network, false);
3008 start_autoscan(device);
3012 case G_SUPPLICANT_STATE_UNKNOWN:
3013 case G_SUPPLICANT_STATE_DISABLED:
3014 case G_SUPPLICANT_STATE_ASSOCIATED:
3015 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3016 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3020 wifi->state = state;
3022 /* Saving wpa_s state policy:
3023 * If connected and if the state changes are roaming related:
3024 * --> We stay connected
3026 * --> We are connected
3028 * --> We are not connected
3031 #if defined TIZEN_EXT
3032 case G_SUPPLICANT_STATE_SCANNING:
3035 case G_SUPPLICANT_STATE_AUTHENTICATING:
3036 case G_SUPPLICANT_STATE_ASSOCIATING:
3037 case G_SUPPLICANT_STATE_ASSOCIATED:
3038 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3039 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3040 if (wifi->connected)
3041 connman_warn("Probably roaming right now!"
3042 " Staying connected...");
3044 wifi->connected = false;
3046 case G_SUPPLICANT_STATE_COMPLETED:
3047 wifi->connected = true;
3050 wifi->connected = false;
3057 static void interface_removed(GSupplicantInterface *interface)
3059 const char *ifname = g_supplicant_interface_get_ifname(interface);
3060 struct wifi_data *wifi;
3062 DBG("ifname %s", ifname);
3064 wifi = g_supplicant_interface_get_data(interface);
3067 wifi->interface = NULL;
3069 if (wifi && wifi->tethering)
3072 if (!wifi || !wifi->device) {
3073 DBG("wifi interface already removed");
3077 connman_device_set_powered(wifi->device, false);
3079 check_p2p_technology();
3082 static void set_device_type(const char *type, char dev_type[17])
3084 const char *oui = "0050F204";
3085 const char *category = "0100";
3086 const char *sub_category = "0000";
3088 if (!g_strcmp0(type, "handset")) {
3090 sub_category = "0500";
3091 } else if (!g_strcmp0(type, "vm") || !g_strcmp0(type, "container"))
3092 sub_category = "0100";
3093 else if (!g_strcmp0(type, "server"))
3094 sub_category = "0200";
3095 else if (!g_strcmp0(type, "laptop"))
3096 sub_category = "0500";
3097 else if (!g_strcmp0(type, "desktop"))
3098 sub_category = "0600";
3099 else if (!g_strcmp0(type, "tablet"))
3100 sub_category = "0900";
3101 else if (!g_strcmp0(type, "watch"))
3104 snprintf(dev_type, 17, "%s%s%s", category, oui, sub_category);
3107 static void p2p_support(GSupplicantInterface *interface)
3109 char dev_type[17] = {};
3110 const char *hostname;
3114 if (!g_supplicant_interface_has_p2p(interface))
3117 if (connman_technology_driver_register(&p2p_tech_driver) < 0) {
3118 DBG("Could not register P2P technology driver");
3122 hostname = connman_utsname_get_hostname();
3124 hostname = "ConnMan";
3126 set_device_type(connman_machine_get_type(), dev_type);
3127 g_supplicant_interface_set_p2p_device_config(interface,
3128 hostname, dev_type);
3129 connman_peer_driver_register(&peer_driver);
3132 static void scan_started(GSupplicantInterface *interface)
3137 static void scan_finished(GSupplicantInterface *interface)
3139 #if defined TIZEN_EXT
3140 struct wifi_data *wifi;
3141 bool is_associating = false;
3142 static bool is_scanning = true;
3147 #if defined TIZEN_EXT
3148 wifi = g_supplicant_interface_get_data(interface);
3149 if (wifi && wifi->scan_pending_network) {
3150 network_connect(wifi->scan_pending_network);
3151 wifi->scan_pending_network = NULL;
3154 //service state - associating
3155 if(!wifi || !wifi->network)
3158 is_associating = connman_network_get_associating(wifi->network);
3159 if(is_associating && is_scanning){
3160 is_scanning = false;
3161 DBG("send scan for connecting");
3162 throw_wifi_scan(wifi->device, scan_callback);
3173 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
3175 unsigned char strength;
3177 strength = 120 + g_supplicant_network_get_signal(supplicant_network);
3179 #if !defined TIZEN_EXT
3186 static void network_added(GSupplicantNetwork *supplicant_network)
3188 struct connman_network *network;
3189 GSupplicantInterface *interface;
3190 struct wifi_data *wifi;
3191 const char *name, *identifier, *security, *group, *mode;
3192 const unsigned char *ssid;
3193 unsigned int ssid_len;
3197 bool wps_advertizing;
3199 #if defined TIZEN_EXT
3200 const char *wifi_vsie;
3201 unsigned int wifi_vsie_len;
3204 mode = g_supplicant_network_get_mode(supplicant_network);
3205 identifier = g_supplicant_network_get_identifier(supplicant_network);
3207 DBG("%s", identifier);
3209 if (!g_strcmp0(mode, "adhoc"))
3212 interface = g_supplicant_network_get_interface(supplicant_network);
3213 wifi = g_supplicant_interface_get_data(interface);
3214 name = g_supplicant_network_get_name(supplicant_network);
3215 security = g_supplicant_network_get_security(supplicant_network);
3216 group = g_supplicant_network_get_identifier(supplicant_network);
3217 wps = g_supplicant_network_get_wps(supplicant_network);
3218 wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
3219 wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
3220 wps_advertizing = g_supplicant_network_is_wps_advertizing(
3221 supplicant_network);
3226 ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
3228 #if defined TIZEN_EXT
3229 wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len);
3231 network = connman_device_get_network(wifi->device, identifier);
3234 network = connman_network_create(identifier,
3235 CONNMAN_NETWORK_TYPE_WIFI);
3239 connman_network_set_index(network, wifi->index);
3241 if (connman_device_add_network(wifi->device, network) < 0) {
3242 connman_network_unref(network);
3246 wifi->networks = g_slist_prepend(wifi->networks, network);
3249 if (name && name[0] != '\0')
3250 connman_network_set_name(network, name);
3252 connman_network_set_blob(network, "WiFi.SSID",
3254 #if defined TIZEN_EXT
3255 if(wifi_vsie_len > 0 && wifi_vsie)
3256 connman_network_set_blob(network, "WiFi.Vsie",
3257 wifi_vsie, wifi_vsie_len);
3259 connman_network_set_string(network, "WiFi.Security", security);
3260 connman_network_set_strength(network,
3261 calculate_strength(supplicant_network));
3262 connman_network_set_bool(network, "WiFi.WPS", wps);
3265 /* Is AP advertizing for WPS association?
3266 * If so, we decide to use WPS by default */
3267 if (wps_ready && wps_pbc &&
3269 #if !defined TIZEN_EXT
3270 connman_network_set_bool(network, "WiFi.UseWPS", true);
3272 DBG("wps is activating by ap but ignore it.");
3277 connman_network_set_frequency(network,
3278 g_supplicant_network_get_frequency(supplicant_network));
3279 #if defined TIZEN_EXT
3280 connman_network_set_bssid(network,
3281 g_supplicant_network_get_bssid(supplicant_network));
3282 connman_network_set_maxrate(network,
3283 g_supplicant_network_get_maxrate(supplicant_network));
3284 connman_network_set_enc_mode(network,
3285 g_supplicant_network_get_enc_mode(supplicant_network));
3286 connman_network_set_rsn_mode(network,
3287 g_supplicant_network_get_rsn_mode(supplicant_network));
3288 connman_network_set_keymgmt(network,
3289 g_supplicant_network_get_keymgmt(supplicant_network));
3290 connman_network_set_bool(network, "WiFi.HS20AP",
3291 g_supplicant_network_is_hs20AP(supplicant_network));
3293 connman_network_set_available(network, true);
3294 connman_network_set_string(network, "WiFi.Mode", mode);
3296 #if defined TIZEN_EXT
3301 connman_network_set_group(network, group);
3303 #if defined TIZEN_EXT
3304 if (wifi_first_scan == true)
3305 found_with_first_scan = true;
3308 if (wifi->hidden && ssid) {
3309 #if defined TIZEN_EXT
3310 if (network_security(wifi->hidden->security) ==
3311 network_security(security) &&
3313 if (!g_strcmp0(wifi->hidden->security, security) &&
3315 wifi->hidden->ssid_len == ssid_len &&
3316 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
3317 connman_network_connect_hidden(network,
3318 wifi->hidden->identity,
3319 wifi->hidden->passphrase,
3320 wifi->hidden->user_data);
3321 wifi->hidden->user_data = NULL;
3322 hidden_free(wifi->hidden);
3323 wifi->hidden = NULL;
3328 static void network_removed(GSupplicantNetwork *network)
3330 GSupplicantInterface *interface;
3331 struct wifi_data *wifi;
3332 const char *name, *identifier;
3333 struct connman_network *connman_network;
3335 interface = g_supplicant_network_get_interface(network);
3336 wifi = g_supplicant_interface_get_data(interface);
3337 identifier = g_supplicant_network_get_identifier(network);
3338 name = g_supplicant_network_get_name(network);
3340 DBG("name %s", name);
3345 connman_network = connman_device_get_network(wifi->device, identifier);
3346 if (!connman_network)
3349 #if defined TIZEN_EXT
3350 if (connman_network == wifi->scan_pending_network)
3351 wifi->scan_pending_network = NULL;
3353 if (connman_network == wifi->pending_network)
3354 wifi->pending_network = NULL;
3356 if(connman_network_get_connecting(connman_network) == true){
3357 connman_network_set_connected(connman_network, false);
3361 wifi->networks = g_slist_remove(wifi->networks, connman_network);
3363 connman_device_remove_network(wifi->device, connman_network);
3364 connman_network_unref(connman_network);
3367 static void network_changed(GSupplicantNetwork *network, const char *property)
3369 GSupplicantInterface *interface;
3370 struct wifi_data *wifi;
3371 const char *name, *identifier;
3372 struct connman_network *connman_network;
3374 #if defined TIZEN_EXT
3375 const unsigned char *bssid;
3376 unsigned int maxrate;
3381 interface = g_supplicant_network_get_interface(network);
3382 wifi = g_supplicant_interface_get_data(interface);
3383 identifier = g_supplicant_network_get_identifier(network);
3384 name = g_supplicant_network_get_name(network);
3386 DBG("name %s", name);
3391 connman_network = connman_device_get_network(wifi->device, identifier);
3392 if (!connman_network)
3395 if (g_str_equal(property, "Signal")) {
3396 connman_network_set_strength(connman_network,
3397 calculate_strength(network));
3398 connman_network_update(connman_network);
3401 #if defined TIZEN_EXT
3402 bssid = g_supplicant_network_get_bssid(network);
3403 maxrate = g_supplicant_network_get_maxrate(network);
3404 frequency = g_supplicant_network_get_frequency(network);
3405 wps = g_supplicant_network_get_wps(network);
3407 connman_network_set_bssid(connman_network, bssid);
3408 connman_network_set_maxrate(connman_network, maxrate);
3409 connman_network_set_frequency(connman_network, frequency);
3410 connman_network_set_bool(connman_network, "WiFi.WPS", wps);
3414 static void apply_peer_services(GSupplicantPeer *peer,
3415 struct connman_peer *connman_peer)
3417 const unsigned char *data;
3422 connman_peer_reset_services(connman_peer);
3424 data = g_supplicant_peer_get_widi_ies(peer, &length);
3426 connman_peer_add_service(connman_peer,
3427 CONNMAN_PEER_SERVICE_WIFI_DISPLAY, data, length);
3431 static void add_station(const char *mac)
3433 connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI,
3437 static void remove_station(const char *mac)
3439 connman_technology_tethering_remove_station(mac);
3442 static void peer_found(GSupplicantPeer *peer)
3444 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3445 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3446 struct connman_peer *connman_peer;
3447 const char *identifier, *name;
3449 #if defined TIZEN_EXT
3453 identifier = g_supplicant_peer_get_identifier(peer);
3454 name = g_supplicant_peer_get_name(peer);
3456 DBG("ident: %s", identifier);
3458 connman_peer = connman_peer_get(wifi->device, identifier);
3462 connman_peer = connman_peer_create(identifier);
3463 connman_peer_set_name(connman_peer, name);
3464 connman_peer_set_device(connman_peer, wifi->device);
3465 apply_peer_services(peer, connman_peer);
3467 ret = connman_peer_register(connman_peer);
3468 if (ret < 0 && ret != -EALREADY)
3469 connman_peer_unref(connman_peer);
3472 static void peer_lost(GSupplicantPeer *peer)
3474 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3475 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3476 struct connman_peer *connman_peer;
3477 const char *identifier;
3482 identifier = g_supplicant_peer_get_identifier(peer);
3484 DBG("ident: %s", identifier);
3486 connman_peer = connman_peer_get(wifi->device, identifier);
3488 if (wifi->p2p_connecting &&
3489 wifi->pending_peer == connman_peer) {
3490 peer_connect_timeout(wifi);
3492 connman_peer_unregister(connman_peer);
3493 connman_peer_unref(connman_peer);
3497 static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state)
3499 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3500 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3501 enum connman_peer_state p_state = CONNMAN_PEER_STATE_UNKNOWN;
3502 struct connman_peer *connman_peer;
3503 const char *identifier;
3505 #if defined TIZEN_EXT
3510 identifier = g_supplicant_peer_get_identifier(peer);
3512 DBG("ident: %s", identifier);
3514 connman_peer = connman_peer_get(wifi->device, identifier);
3519 case G_SUPPLICANT_PEER_SERVICES_CHANGED:
3520 apply_peer_services(peer, connman_peer);
3521 connman_peer_services_changed(connman_peer);
3523 case G_SUPPLICANT_PEER_GROUP_CHANGED:
3524 if (!g_supplicant_peer_is_in_a_group(peer))
3525 p_state = CONNMAN_PEER_STATE_IDLE;
3527 p_state = CONNMAN_PEER_STATE_CONFIGURATION;
3529 case G_SUPPLICANT_PEER_GROUP_STARTED:
3531 case G_SUPPLICANT_PEER_GROUP_FINISHED:
3532 p_state = CONNMAN_PEER_STATE_IDLE;
3534 case G_SUPPLICANT_PEER_GROUP_JOINED:
3535 connman_peer_set_iface_address(connman_peer,
3536 g_supplicant_peer_get_iface_address(peer));
3538 case G_SUPPLICANT_PEER_GROUP_DISCONNECTED:
3539 p_state = CONNMAN_PEER_STATE_IDLE;
3541 case G_SUPPLICANT_PEER_GROUP_FAILED:
3542 if (g_supplicant_peer_has_requested_connection(peer))
3543 p_state = CONNMAN_PEER_STATE_IDLE;
3545 p_state = CONNMAN_PEER_STATE_FAILURE;
3549 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION ||
3550 p_state == CONNMAN_PEER_STATE_FAILURE) {
3551 if (wifi->p2p_connecting
3552 && connman_peer == wifi->pending_peer)
3553 peer_cancel_timeout(wifi);
3555 p_state = CONNMAN_PEER_STATE_UNKNOWN;
3558 if (p_state == CONNMAN_PEER_STATE_UNKNOWN)
3561 if (p_state == CONNMAN_PEER_STATE_CONFIGURATION) {
3562 GSupplicantInterface *g_iface;
3563 struct wifi_data *g_wifi;
3565 g_iface = g_supplicant_peer_get_group_interface(peer);
3569 g_wifi = g_supplicant_interface_get_data(g_iface);
3573 connman_peer_set_as_master(connman_peer,
3574 !g_supplicant_peer_is_client(peer));
3575 connman_peer_set_sub_device(connman_peer, g_wifi->device);
3578 connman_peer_set_state(connman_peer, p_state);
3581 static void peer_request(GSupplicantPeer *peer)
3583 GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer);
3584 struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
3585 struct connman_peer *connman_peer;
3586 const char *identifier;
3588 #if defined TIZEN_EXT
3593 identifier = g_supplicant_peer_get_identifier(peer);
3595 DBG("ident: %s", identifier);
3597 connman_peer = connman_peer_get(wifi->device, identifier);
3601 connman_peer_request_connection(connman_peer);
3604 #if defined TIZEN_EXT
3605 static void system_power_off(void)
3608 struct wifi_data *wifi;
3609 struct connman_service *service;
3610 struct connman_ipconfig *ipconfig_ipv4;
3612 if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
3613 for (list = iface_list; list; list = list->next) {
3616 if (wifi->network != NULL) {
3617 service = connman_service_lookup_from_network(wifi->network);
3618 ipconfig_ipv4 = __connman_service_get_ip4config(service);
3619 __connman_dhcp_stop(ipconfig_ipv4);
3625 static void network_merged(GSupplicantNetwork *network)
3627 GSupplicantInterface *interface;
3628 GSupplicantState state;
3629 struct wifi_data *wifi;
3630 const char *identifier;
3631 struct connman_network *connman_network;
3635 interface = g_supplicant_network_get_interface(network);
3639 state = g_supplicant_interface_get_state(interface);
3640 if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
3643 wifi = g_supplicant_interface_get_data(interface);
3647 identifier = g_supplicant_network_get_identifier(network);
3649 connman_network = connman_device_get_network(wifi->device, identifier);
3650 if (!connman_network)
3653 DBG("merged identifier %s", identifier);
3655 if (wifi->connected == FALSE) {
3657 case G_SUPPLICANT_STATE_AUTHENTICATING:
3658 case G_SUPPLICANT_STATE_ASSOCIATING:
3659 case G_SUPPLICANT_STATE_ASSOCIATED:
3660 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3661 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3662 connman_network_set_associating(connman_network, TRUE);
3664 case G_SUPPLICANT_STATE_COMPLETED:
3665 connman_network_set_connected(connman_network, TRUE);
3668 DBG("Not handled the state : %d", state);
3673 ishs20AP = g_supplicant_network_is_hs20AP(network);
3676 g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
3677 temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
3678 connman_network_set_string(connman_network, "WiFi.EAP",
3680 connman_network_set_string(connman_network, "WiFi.Identity",
3681 g_supplicant_network_get_identity(network));
3682 connman_network_set_string(connman_network, "WiFi.Phase2",
3683 g_supplicant_network_get_phase2(network));
3688 wifi->network = connman_network;
3692 static void debug(const char *str)
3694 if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
3695 connman_debug("%s", str);
3698 static void disconnect_reasoncode(GSupplicantInterface *interface,
3701 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3703 wifi->disconnect_code = reasoncode;
3707 static void assoc_status_code(GSupplicantInterface *interface, int status_code)
3709 struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
3711 #if defined TIZEN_EXT
3712 struct connman_network *network;
3716 wifi->assoc_code = status_code;
3718 #if defined TIZEN_EXT
3719 network = wifi->network;
3720 connman_network_set_assoc_status_code(network,status_code);
3726 static const GSupplicantCallbacks callbacks = {
3727 .system_ready = system_ready,
3728 .system_killed = system_killed,
3729 .interface_added = interface_added,
3730 .interface_state = interface_state,
3731 .interface_removed = interface_removed,
3732 .p2p_support = p2p_support,
3733 .scan_started = scan_started,
3734 .scan_finished = scan_finished,
3735 .network_added = network_added,
3736 .network_removed = network_removed,
3737 .network_changed = network_changed,
3738 .add_station = add_station,
3739 .remove_station = remove_station,
3740 .peer_found = peer_found,
3741 .peer_lost = peer_lost,
3742 .peer_changed = peer_changed,
3743 .peer_request = peer_request,
3744 #if defined TIZEN_EXT
3745 .system_power_off = system_power_off,
3746 .network_merged = network_merged,
3748 .disconnect_reasoncode = disconnect_reasoncode,
3749 .assoc_status_code = assoc_status_code,
3754 static int tech_probe(struct connman_technology *technology)
3756 wifi_technology = technology;
3761 static void tech_remove(struct connman_technology *technology)
3763 wifi_technology = NULL;
3766 struct wifi_tethering_info {
3767 struct wifi_data *wifi;
3768 struct connman_technology *technology;
3770 GSupplicantSSID *ssid;
3773 static GSupplicantSSID *ssid_ap_init(const char *ssid,
3774 const char *passphrase, bool hidden)
3776 GSupplicantSSID *ap;
3778 ap = g_try_malloc0(sizeof(GSupplicantSSID));
3782 ap->mode = G_SUPPLICANT_MODE_MASTER;
3784 ap->ssid_len = strlen(ssid);
3788 if (!passphrase || strlen(passphrase) == 0) {
3789 ap->security = G_SUPPLICANT_SECURITY_NONE;
3790 ap->passphrase = NULL;
3792 ap->security = G_SUPPLICANT_SECURITY_PSK;
3793 ap->protocol = G_SUPPLICANT_PROTO_RSN;
3794 ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
3795 ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
3796 ap->passphrase = passphrase;
3800 ap->ignore_broadcast_ssid =
3801 G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS;
3803 ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING;
3808 static void ap_start_callback(int result, GSupplicantInterface *interface,
3811 struct wifi_tethering_info *info = user_data;
3813 DBG("result %d index %d bridge %s",
3814 result, info->wifi->index, info->wifi->bridge);
3817 connman_inet_remove_from_bridge(info->wifi->index,
3818 info->wifi->bridge);
3819 connman_technology_tethering_notify(info->technology, false);
3822 g_free(info->ifname);
3826 static void ap_create_callback(int result,
3827 GSupplicantInterface *interface,
3830 struct wifi_tethering_info *info = user_data;
3832 DBG("result %d ifname %s", result,
3833 g_supplicant_interface_get_ifname(interface));
3836 connman_inet_remove_from_bridge(info->wifi->index,
3837 info->wifi->bridge);
3838 connman_technology_tethering_notify(info->technology, false);
3840 g_free(info->ifname);
3846 info->wifi->interface = interface;
3847 g_supplicant_interface_set_data(interface, info->wifi);
3849 if (g_supplicant_interface_set_apscan(interface, 2) < 0)
3850 connman_error("Failed to set interface ap_scan property");
3852 g_supplicant_interface_connect(interface, info->ssid,
3853 ap_start_callback, info);
3856 static void sta_remove_callback(int result,
3857 GSupplicantInterface *interface,
3860 struct wifi_tethering_info *info = user_data;
3861 const char *driver = connman_option_get_string("wifi");
3863 DBG("ifname %s result %d ", info->ifname, result);
3866 info->wifi->tethering = true;
3868 g_free(info->ifname);
3874 info->wifi->interface = NULL;
3876 connman_technology_tethering_notify(info->technology, true);
3878 g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
3883 static int tech_set_tethering(struct connman_technology *technology,
3884 const char *identifier, const char *passphrase,
3885 const char *bridge, bool enabled, bool hidden)
3888 GSupplicantInterface *interface;
3889 struct wifi_data *wifi;
3890 struct wifi_tethering_info *info;
3898 for (list = iface_list; list; list = list->next) {
3901 if (wifi->tethering) {
3902 wifi->tethering = false;
3904 connman_inet_remove_from_bridge(wifi->index,
3906 wifi->bridged = false;
3910 connman_technology_tethering_notify(technology, false);
3915 for (list = iface_list; list; list = list->next) {
3918 interface = wifi->interface;
3923 ifname = g_supplicant_interface_get_ifname(wifi->interface);
3925 mode = g_supplicant_interface_get_mode(interface);
3926 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
3927 DBG("%s does not support AP mode", ifname);
3931 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
3936 info->technology = technology;
3937 info->wifi->bridge = bridge;
3938 info->ssid = ssid_ap_init(identifier, passphrase, hidden);
3943 info->ifname = g_strdup(ifname);
3944 if (!info->ifname) {
3950 info->wifi->tethering = true;
3952 err = g_supplicant_interface_remove(interface,
3953 sta_remove_callback,
3962 static void regdom_callback(int result, const char *alpha2, void *user_data)
3966 if (!wifi_technology)
3972 connman_technology_regdom_notify(wifi_technology, alpha2);
3975 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
3977 return g_supplicant_set_country(alpha2, regdom_callback, NULL);
3980 static struct connman_technology_driver tech_driver = {
3982 .type = CONNMAN_SERVICE_TYPE_WIFI,
3983 .probe = tech_probe,
3984 .remove = tech_remove,
3985 .set_tethering = tech_set_tethering,
3986 .set_regdom = tech_set_regdom,
3989 static int wifi_init(void)
3993 err = connman_network_driver_register(&network_driver);
3997 err = g_supplicant_register(&callbacks);
3999 connman_network_driver_unregister(&network_driver);
4003 err = connman_technology_driver_register(&tech_driver);
4005 g_supplicant_unregister(&callbacks);
4006 connman_network_driver_unregister(&network_driver);
4013 static void wifi_exit(void)
4017 connman_technology_driver_unregister(&tech_driver);
4019 g_supplicant_unregister(&callbacks);
4021 connman_network_driver_unregister(&network_driver);
4024 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
4025 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)