3 * WPA supplicant library with GLib integration
5 * Copyright (C) 2012-2013 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
34 #include <netinet/if_ether.h>
35 #include <netinet/in.h>
41 #include "gsupplicant.h"
43 #define IEEE80211_CAP_ESS 0x0001
44 #define IEEE80211_CAP_IBSS 0x0002
45 #define IEEE80211_CAP_PRIVACY 0x0010
47 #define BSS_UNKNOWN_STRENGTH -90
49 static DBusConnection *connection;
51 static const GSupplicantCallbacks *callbacks_pointer;
53 static dbus_bool_t system_available = FALSE;
54 static dbus_bool_t system_ready = FALSE;
56 static dbus_int32_t debug_level;
57 static dbus_bool_t debug_timestamp = FALSE;
58 static dbus_bool_t debug_showkeys = FALSE;
60 static const char *debug_strings[] = {
61 "msgdump", "debug", "info", "warning", "error", NULL
64 static unsigned int eap_methods;
71 static struct strvalmap eap_method_map[] = {
72 { "MD5", G_SUPPLICANT_EAP_METHOD_MD5 },
73 { "TLS", G_SUPPLICANT_EAP_METHOD_TLS },
74 { "MSCHAPV2", G_SUPPLICANT_EAP_METHOD_MSCHAPV2 },
75 { "PEAP", G_SUPPLICANT_EAP_METHOD_PEAP },
76 { "TTLS", G_SUPPLICANT_EAP_METHOD_TTLS },
77 { "GTC", G_SUPPLICANT_EAP_METHOD_GTC },
78 { "OTP", G_SUPPLICANT_EAP_METHOD_OTP },
79 { "LEAP", G_SUPPLICANT_EAP_METHOD_LEAP },
80 { "WSC", G_SUPPLICANT_EAP_METHOD_WSC },
84 static struct strvalmap keymgmt_map[] = {
85 { "none", G_SUPPLICANT_KEYMGMT_NONE },
86 { "ieee8021x", G_SUPPLICANT_KEYMGMT_IEEE8021X },
87 { "wpa-none", G_SUPPLICANT_KEYMGMT_WPA_NONE },
88 { "wpa-psk", G_SUPPLICANT_KEYMGMT_WPA_PSK },
89 { "wpa-psk-sha256", G_SUPPLICANT_KEYMGMT_WPA_PSK_256 },
90 { "wpa-ft-psk", G_SUPPLICANT_KEYMGMT_WPA_FT_PSK },
91 { "wpa-ft-eap", G_SUPPLICANT_KEYMGMT_WPA_FT_EAP },
92 { "wpa-eap", G_SUPPLICANT_KEYMGMT_WPA_EAP },
93 { "wpa-eap-sha256", G_SUPPLICANT_KEYMGMT_WPA_EAP_256 },
94 { "wps", G_SUPPLICANT_KEYMGMT_WPS },
98 static struct strvalmap authalg_capa_map[] = {
99 { "open", G_SUPPLICANT_CAPABILITY_AUTHALG_OPEN },
100 { "shared", G_SUPPLICANT_CAPABILITY_AUTHALG_SHARED },
101 { "leap", G_SUPPLICANT_CAPABILITY_AUTHALG_LEAP },
105 static struct strvalmap proto_capa_map[] = {
106 { "wpa", G_SUPPLICANT_CAPABILITY_PROTO_WPA },
107 { "rsn", G_SUPPLICANT_CAPABILITY_PROTO_RSN },
111 static struct strvalmap group_map[] = {
112 { "wep40", G_SUPPLICANT_GROUP_WEP40 },
113 { "wep104", G_SUPPLICANT_GROUP_WEP104 },
114 { "tkip", G_SUPPLICANT_GROUP_TKIP },
115 { "ccmp", G_SUPPLICANT_GROUP_CCMP },
119 static struct strvalmap pairwise_map[] = {
120 { "none", G_SUPPLICANT_PAIRWISE_NONE },
121 { "tkip", G_SUPPLICANT_PAIRWISE_TKIP },
122 { "ccmp", G_SUPPLICANT_PAIRWISE_CCMP },
126 static struct strvalmap scan_capa_map[] = {
127 { "active", G_SUPPLICANT_CAPABILITY_SCAN_ACTIVE },
128 { "passive", G_SUPPLICANT_CAPABILITY_SCAN_PASSIVE },
129 { "ssid", G_SUPPLICANT_CAPABILITY_SCAN_SSID },
133 static struct strvalmap mode_capa_map[] = {
134 { "infrastructure", G_SUPPLICANT_CAPABILITY_MODE_INFRA },
135 { "ad-hoc", G_SUPPLICANT_CAPABILITY_MODE_IBSS },
136 { "ap", G_SUPPLICANT_CAPABILITY_MODE_AP },
137 { "p2p", G_SUPPLICANT_CAPABILITY_MODE_P2P },
141 static GHashTable *interface_table;
142 static GHashTable *bss_mapping;
143 static GHashTable *peer_mapping;
144 static GHashTable *group_mapping;
145 static GHashTable *pending_peer_connection;
146 static GHashTable *config_file_table;
148 struct _GSupplicantWpsCredentials {
149 unsigned char ssid[32];
150 unsigned int ssid_len;
154 struct added_network_information {
156 GSupplicantSecurity security;
158 char * private_passphrase;
161 struct _GSupplicantInterface {
164 unsigned int keymgmt_capa;
165 unsigned int authalg_capa;
166 unsigned int proto_capa;
167 unsigned int group_capa;
168 unsigned int pairwise_capa;
169 unsigned int scan_capa;
170 unsigned int mode_capa;
171 unsigned int max_scan_ssids;
174 bool ap_create_in_progress;
176 GSupplicantState state;
177 dbus_bool_t scanning;
178 GSupplicantInterfaceCallback scan_callback;
184 struct _GSupplicantWpsCredentials wps_cred;
185 GSupplicantWpsState wps_state;
186 GHashTable *network_table;
187 GHashTable *peer_table;
188 GHashTable *group_table;
189 GHashTable *bss_mapping;
191 const char *pending_peer_path;
192 GSupplicantNetwork *current_network;
193 struct added_network_information network_info;
194 #if defined TIZEN_EXT
195 int disconnect_reason;
199 struct g_supplicant_bss {
200 GSupplicantInterface *interface;
202 unsigned char bssid[6];
203 unsigned char ssid[32];
204 unsigned int ssid_len;
205 dbus_uint16_t frequency;
206 dbus_uint32_t maxrate;
208 GSupplicantMode mode;
209 GSupplicantSecurity security;
210 dbus_bool_t rsn_selected;
211 unsigned int wpa_keymgmt;
212 unsigned int wpa_pairwise;
213 unsigned int wpa_group;
214 unsigned int rsn_keymgmt;
215 unsigned int rsn_pairwise;
216 unsigned int rsn_group;
217 unsigned int keymgmt;
220 dbus_bool_t ieee8021x;
221 #if defined TIZEN_EXT
223 dbus_bool_t ft_ieee8021x;
225 unsigned int wifi_vsie_len;
228 unsigned int wps_capabilities;
231 struct _GSupplicantNetwork {
232 GSupplicantInterface *interface;
236 unsigned char ssid[32];
237 unsigned int ssid_len;
239 dbus_uint16_t frequency;
240 struct g_supplicant_bss *best_bss;
241 GSupplicantMode mode;
242 GSupplicantSecurity security;
244 unsigned int wps_capabilities;
245 GHashTable *bss_table;
246 GHashTable *config_table;
247 #if defined TIZEN_EXT
252 unsigned int keymgmt;
254 unsigned int wifi_vsie_len;
258 struct _GSupplicantPeer {
259 GSupplicantInterface *interface;
261 unsigned char device_address[ETH_ALEN];
262 unsigned char iface_address[ETH_ALEN];
264 unsigned char *widi_ies;
267 unsigned int wps_capabilities;
269 const GSupplicantInterface *current_group_iface;
270 bool connection_requested;
273 struct _GSupplicantGroup {
274 GSupplicantInterface *interface;
275 GSupplicantInterface *orig_interface;
281 struct interface_data {
282 GSupplicantInterface *interface;
283 char *path; /* Interface path cannot be taken from interface (above) as
284 * it might have been freed already.
286 GSupplicantInterfaceCallback callback;
288 bool network_remove_in_progress;
289 GSupplicantSSID *ssid;
292 struct interface_create_data {
296 GSupplicantInterface *interface;
297 GSupplicantInterfaceCallback callback;
301 struct interface_connect_data {
302 GSupplicantInterface *interface;
304 GSupplicantInterfaceCallback callback;
307 GSupplicantSSID *ssid;
308 GSupplicantPeerParams *peer;
312 struct interface_scan_data {
313 GSupplicantInterface *interface;
315 GSupplicantInterfaceCallback callback;
316 GSupplicantScanParams *scan_params;
320 static int network_remove(struct interface_data *data);
322 static inline void debug(const char *format, ...)
327 if (!callbacks_pointer || !callbacks_pointer->debug)
330 va_start(ap, format);
332 if (vsnprintf(str, sizeof(str), format, ap) > 0)
333 callbacks_pointer->debug(str);
338 #define SUPPLICANT_DBG(fmt, arg...) \
339 debug("%s:%s() " fmt, __FILE__, __FUNCTION__ , ## arg);
341 static GSupplicantMode string2mode(const char *mode)
344 return G_SUPPLICANT_MODE_UNKNOWN;
346 if (g_str_equal(mode, "infrastructure"))
347 return G_SUPPLICANT_MODE_INFRA;
348 else if (g_str_equal(mode, "ad-hoc"))
349 return G_SUPPLICANT_MODE_IBSS;
351 return G_SUPPLICANT_MODE_UNKNOWN;
354 static const char *mode2string(GSupplicantMode mode)
357 case G_SUPPLICANT_MODE_UNKNOWN:
359 case G_SUPPLICANT_MODE_INFRA:
361 case G_SUPPLICANT_MODE_IBSS:
363 case G_SUPPLICANT_MODE_MASTER:
370 static const char *security2string(GSupplicantSecurity security)
373 case G_SUPPLICANT_SECURITY_UNKNOWN:
375 case G_SUPPLICANT_SECURITY_NONE:
377 case G_SUPPLICANT_SECURITY_WEP:
379 case G_SUPPLICANT_SECURITY_PSK:
381 case G_SUPPLICANT_SECURITY_IEEE8021X:
383 #if defined TIZEN_EXT
384 case G_SUPPLICANT_SECURITY_FT_PSK:
386 case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
387 return "ft_ieee8021x";
394 static GSupplicantState string2state(const char *state)
397 return G_SUPPLICANT_STATE_UNKNOWN;
399 if (g_str_equal(state, "unknown"))
400 return G_SUPPLICANT_STATE_UNKNOWN;
401 else if (g_str_equal(state, "interface_disabled"))
402 return G_SUPPLICANT_STATE_DISABLED;
403 else if (g_str_equal(state, "disconnected"))
404 return G_SUPPLICANT_STATE_DISCONNECTED;
405 else if (g_str_equal(state, "inactive"))
406 return G_SUPPLICANT_STATE_INACTIVE;
407 else if (g_str_equal(state, "scanning"))
408 return G_SUPPLICANT_STATE_SCANNING;
409 else if (g_str_equal(state, "authenticating"))
410 return G_SUPPLICANT_STATE_AUTHENTICATING;
411 else if (g_str_equal(state, "associating"))
412 return G_SUPPLICANT_STATE_ASSOCIATING;
413 else if (g_str_equal(state, "associated"))
414 return G_SUPPLICANT_STATE_ASSOCIATED;
415 else if (g_str_equal(state, "group_handshake"))
416 return G_SUPPLICANT_STATE_GROUP_HANDSHAKE;
417 else if (g_str_equal(state, "4way_handshake"))
418 return G_SUPPLICANT_STATE_4WAY_HANDSHAKE;
419 else if (g_str_equal(state, "completed"))
420 return G_SUPPLICANT_STATE_COMPLETED;
422 return G_SUPPLICANT_STATE_UNKNOWN;
425 static bool compare_network_parameters(GSupplicantInterface *interface,
426 GSupplicantSSID *ssid)
428 if (memcmp(interface->network_info.ssid, ssid->ssid, ssid->ssid_len))
431 if (interface->network_info.security != ssid->security)
434 if (interface->network_info.passphrase &&
435 g_strcmp0(interface->network_info.passphrase,
436 ssid->passphrase) != 0) {
440 if (interface->network_info.private_passphrase &&
441 g_strcmp0(interface->network_info.private_passphrase,
442 ssid->private_key_passphrase) != 0) {
449 static void remove_network_information(GSupplicantInterface * interface)
451 g_free(interface->network_info.ssid);
452 g_free(interface->network_info.passphrase);
453 g_free(interface->network_info.private_passphrase);
454 interface->network_info.ssid = NULL;
455 interface->network_info.passphrase = NULL;
456 interface->network_info.private_passphrase = NULL;
459 static int store_network_information(GSupplicantInterface * interface,
460 GSupplicantSSID *ssid)
462 interface->network_info.ssid = g_malloc(ssid->ssid_len + 1);
463 if (interface->network_info.ssid != NULL) {
464 memcpy(interface->network_info.ssid, ssid->ssid,
466 interface->network_info.ssid[ssid->ssid_len] = '\0';
471 interface->network_info.security = ssid->security;
473 if ((ssid->security == G_SUPPLICANT_SECURITY_WEP ||
474 ssid->security == G_SUPPLICANT_SECURITY_PSK ||
475 ssid->security == G_SUPPLICANT_SECURITY_NONE) &&
477 interface->network_info.passphrase = g_strdup(ssid->passphrase);
480 if (ssid->security == G_SUPPLICANT_SECURITY_IEEE8021X &&
481 ssid->private_key_passphrase) {
482 interface->network_info.private_passphrase =
483 g_strdup(ssid->private_key_passphrase);
489 static void callback_system_ready(void)
496 if (!callbacks_pointer)
499 if (!callbacks_pointer->system_ready)
502 callbacks_pointer->system_ready();
505 static void callback_system_killed(void)
507 system_ready = FALSE;
509 if (!callbacks_pointer)
512 if (!callbacks_pointer->system_killed)
515 callbacks_pointer->system_killed();
518 static void callback_interface_added(GSupplicantInterface *interface)
522 if (!callbacks_pointer)
525 if (!callbacks_pointer->interface_added)
528 callbacks_pointer->interface_added(interface);
531 static void callback_interface_state(GSupplicantInterface *interface)
533 if (!callbacks_pointer)
536 if (!callbacks_pointer->interface_state)
539 callbacks_pointer->interface_state(interface);
542 static void callback_interface_removed(GSupplicantInterface *interface)
544 if (!callbacks_pointer)
547 if (!callbacks_pointer->interface_removed)
550 callbacks_pointer->interface_removed(interface);
553 #if !defined TIZEN_EXT
554 static void callback_p2p_support(GSupplicantInterface *interface)
558 if (!interface->p2p_support)
561 if (callbacks_pointer && callbacks_pointer->p2p_support)
562 callbacks_pointer->p2p_support(interface);
566 static void callback_scan_started(GSupplicantInterface *interface)
568 if (!callbacks_pointer)
571 if (!callbacks_pointer->scan_started)
574 callbacks_pointer->scan_started(interface);
577 static void callback_ap_create_fail(GSupplicantInterface *interface)
579 if (!callbacks_pointer)
582 if (!callbacks_pointer->ap_create_fail)
585 callbacks_pointer->ap_create_fail(interface);
588 static void callback_scan_finished(GSupplicantInterface *interface)
590 if (!callbacks_pointer)
593 if (!callbacks_pointer->scan_finished)
596 callbacks_pointer->scan_finished(interface);
599 static void callback_network_added(GSupplicantNetwork *network)
601 if (!callbacks_pointer)
604 if (!callbacks_pointer->network_added)
607 callbacks_pointer->network_added(network);
610 static void callback_network_removed(GSupplicantNetwork *network)
612 if (!callbacks_pointer)
615 if (!callbacks_pointer->network_removed)
618 callbacks_pointer->network_removed(network);
621 #if defined TIZEN_EXT
622 static void callback_network_merged(GSupplicantNetwork *network)
624 if (!callbacks_pointer)
627 if (!callbacks_pointer->network_merged)
630 callbacks_pointer->network_merged(network);
633 static void callback_assoc_failed(void *user_data)
635 if (!callbacks_pointer)
638 if (!callbacks_pointer->assoc_failed)
641 callbacks_pointer->assoc_failed(user_data);
645 static void callback_network_changed(GSupplicantNetwork *network,
646 const char *property)
648 if (!callbacks_pointer)
651 if (!callbacks_pointer->network_changed)
654 callbacks_pointer->network_changed(network, property);
657 static void callback_network_associated(GSupplicantNetwork *network)
659 if (!callbacks_pointer)
662 if (!callbacks_pointer->network_associated)
665 callbacks_pointer->network_associated(network);
668 static void callback_peer_found(GSupplicantPeer *peer)
670 if (!callbacks_pointer)
673 if (!callbacks_pointer->peer_found)
676 callbacks_pointer->peer_found(peer);
679 static void callback_peer_lost(GSupplicantPeer *peer)
681 if (!callbacks_pointer)
684 if (!callbacks_pointer->peer_lost)
687 callbacks_pointer->peer_lost(peer);
690 static void callback_peer_changed(GSupplicantPeer *peer,
691 GSupplicantPeerState state)
693 if (!callbacks_pointer)
696 if (!callbacks_pointer->peer_changed)
699 callbacks_pointer->peer_changed(peer, state);
702 static void callback_peer_request(GSupplicantPeer *peer)
704 if (!callbacks_pointer)
707 if (!callbacks_pointer->peer_request)
710 peer->connection_requested = true;
712 callbacks_pointer->peer_request(peer);
715 static void callback_disconnect_reason_code(GSupplicantInterface *interface,
718 if (!callbacks_pointer)
721 if (!callbacks_pointer->disconnect_reasoncode)
724 if (reason_code != 0)
725 callbacks_pointer->disconnect_reasoncode(interface,
729 static void callback_assoc_status_code(GSupplicantInterface *interface,
732 if (!callbacks_pointer)
735 if (!callbacks_pointer->assoc_status_code)
738 callbacks_pointer->assoc_status_code(interface, status_code);
742 static void remove_group(gpointer data)
744 GSupplicantGroup *group = data;
747 g_slist_free_full(group->members, g_free);
753 static void remove_interface(gpointer data)
755 GSupplicantInterface *interface = data;
757 g_hash_table_destroy(interface->bss_mapping);
758 g_hash_table_destroy(interface->network_table);
759 g_hash_table_destroy(interface->peer_table);
760 g_hash_table_destroy(interface->group_table);
762 if (interface->scan_callback) {
763 SUPPLICANT_DBG("call interface %p callback %p scanning %d",
764 interface, interface->scan_callback,
765 interface->scanning);
767 interface->scan_callback(-EIO, interface, interface->scan_data);
768 interface->scan_callback = NULL;
769 interface->scan_data = NULL;
771 if (interface->scanning) {
772 interface->scanning = FALSE;
773 callback_scan_finished(interface);
777 callback_interface_removed(interface);
779 g_free(interface->wps_cred.key);
780 g_free(interface->path);
781 g_free(interface->network_path);
782 #if defined TIZEN_EXT
783 interface->network_path = NULL;
785 g_free(interface->ifname);
786 g_free(interface->driver);
787 g_free(interface->bridge);
788 remove_network_information(interface);
792 static void remove_network(gpointer data)
794 GSupplicantNetwork *network = data;
796 g_hash_table_destroy(network->bss_table);
798 callback_network_removed(network);
800 g_hash_table_destroy(network->config_table);
802 g_free(network->path);
803 g_free(network->group);
804 g_free(network->name);
805 #if defined TIZEN_EXT
806 g_free(network->eap);
807 g_free(network->identity);
808 g_free(network->phase2);
810 #if defined TIZEN_EXT
811 g_free(network->wifi_vsie);
817 static void remove_bss(gpointer data)
819 struct g_supplicant_bss *bss = data;
822 #if defined TIZEN_EXT
823 g_free(bss->wifi_vsie);
828 static void remove_peer(gpointer data)
830 GSupplicantPeer *peer = data;
832 callback_peer_lost(peer);
835 g_slist_free_full(peer->groups, g_free);
838 g_hash_table_remove(peer_mapping, peer->path);
840 if (pending_peer_connection)
841 g_hash_table_remove(pending_peer_connection, peer->path);
845 g_free(peer->identifier);
846 g_free(peer->widi_ies);
851 static void debug_strvalmap(const char *label, struct strvalmap *map,
856 for (i = 0; map[i].str; i++) {
857 if (val & map[i].val)
858 SUPPLICANT_DBG("%s: %s", label, map[i].str);
862 static void interface_capability_keymgmt(DBusMessageIter *iter, void *user_data)
864 GSupplicantInterface *interface = user_data;
865 const char *str = NULL;
868 dbus_message_iter_get_basic(iter, &str);
872 for (i = 0; keymgmt_map[i].str; i++)
873 if (strcmp(str, keymgmt_map[i].str) == 0) {
874 interface->keymgmt_capa |= keymgmt_map[i].val;
879 static void interface_capability_authalg(DBusMessageIter *iter, void *user_data)
881 GSupplicantInterface *interface = user_data;
882 const char *str = NULL;
885 dbus_message_iter_get_basic(iter, &str);
889 for (i = 0; authalg_capa_map[i].str; i++)
890 if (strcmp(str, authalg_capa_map[i].str) == 0) {
891 interface->authalg_capa |= authalg_capa_map[i].val;
896 static void interface_capability_proto(DBusMessageIter *iter, void *user_data)
898 GSupplicantInterface *interface = user_data;
899 const char *str = NULL;
902 dbus_message_iter_get_basic(iter, &str);
906 for (i = 0; proto_capa_map[i].str; i++)
907 if (strcmp(str, proto_capa_map[i].str) == 0) {
908 interface->proto_capa |= proto_capa_map[i].val;
913 static void interface_capability_pairwise(DBusMessageIter *iter,
916 GSupplicantInterface *interface = user_data;
917 const char *str = NULL;
920 dbus_message_iter_get_basic(iter, &str);
924 for (i = 0; pairwise_map[i].str; i++)
925 if (strcmp(str, pairwise_map[i].str) == 0) {
926 interface->pairwise_capa |= pairwise_map[i].val;
931 static void interface_capability_group(DBusMessageIter *iter, void *user_data)
933 GSupplicantInterface *interface = user_data;
934 const char *str = NULL;
937 dbus_message_iter_get_basic(iter, &str);
941 for (i = 0; group_map[i].str; i++)
942 if (strcmp(str, group_map[i].str) == 0) {
943 interface->group_capa |= group_map[i].val;
948 static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
950 GSupplicantInterface *interface = user_data;
951 const char *str = NULL;
954 dbus_message_iter_get_basic(iter, &str);
958 for (i = 0; scan_capa_map[i].str; i++)
959 if (strcmp(str, scan_capa_map[i].str) == 0) {
960 interface->scan_capa |= scan_capa_map[i].val;
965 static void interface_capability_mode(DBusMessageIter *iter, void *user_data)
967 GSupplicantInterface *interface = user_data;
968 const char *str = NULL;
971 dbus_message_iter_get_basic(iter, &str);
975 for (i = 0; mode_capa_map[i].str; i++)
976 if (strcmp(str, mode_capa_map[i].str) == 0) {
977 interface->mode_capa |= mode_capa_map[i].val;
982 static void interface_capability(const char *key, DBusMessageIter *iter,
985 GSupplicantInterface *interface = user_data;
990 if (g_strcmp0(key, "KeyMgmt") == 0)
991 supplicant_dbus_array_foreach(iter,
992 interface_capability_keymgmt, interface);
993 else if (g_strcmp0(key, "AuthAlg") == 0)
994 supplicant_dbus_array_foreach(iter,
995 interface_capability_authalg, interface);
996 else if (g_strcmp0(key, "Protocol") == 0)
997 supplicant_dbus_array_foreach(iter,
998 interface_capability_proto, interface);
999 else if (g_strcmp0(key, "Pairwise") == 0)
1000 supplicant_dbus_array_foreach(iter,
1001 interface_capability_pairwise, interface);
1002 else if (g_strcmp0(key, "Group") == 0)
1003 supplicant_dbus_array_foreach(iter,
1004 interface_capability_group, interface);
1005 else if (g_strcmp0(key, "Scan") == 0)
1006 supplicant_dbus_array_foreach(iter,
1007 interface_capability_scan, interface);
1008 else if (g_strcmp0(key, "Modes") == 0)
1009 supplicant_dbus_array_foreach(iter,
1010 interface_capability_mode, interface);
1011 else if (g_strcmp0(key, "MaxScanSSID") == 0) {
1012 dbus_int32_t max_scan_ssid;
1014 dbus_message_iter_get_basic(iter, &max_scan_ssid);
1015 if (max_scan_ssid < 2)
1017 interface->max_scan_ssids = max_scan_ssid;
1020 SUPPLICANT_DBG("key %s type %c",
1021 key, dbus_message_iter_get_arg_type(iter));
1024 struct set_apscan_data
1026 unsigned int ap_scan;
1027 GSupplicantInterface *interface;
1030 static void set_apscan(DBusMessageIter *iter, void *user_data)
1032 struct set_apscan_data *data = user_data;
1033 unsigned int ap_scan = data->ap_scan;
1035 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &ap_scan);
1038 static void set_apscan_complete(const char *error,
1039 DBusMessageIter *iter, void *user_data)
1041 struct set_apscan_data *data = user_data;
1042 GSupplicantInterface *interface = data->interface;
1045 interface->ap_create_in_progress = false;
1046 SUPPLICANT_DBG("Set AP scan error %s", error);
1050 interface->ap_create_in_progress = true;
1055 int g_supplicant_interface_set_apscan(GSupplicantInterface *interface,
1056 unsigned int ap_scan)
1058 struct set_apscan_data *data;
1061 data = dbus_malloc0(sizeof(*data));
1066 data->ap_scan = ap_scan;
1067 data->interface = interface;
1069 ret = supplicant_dbus_property_set(interface->path,
1070 SUPPLICANT_INTERFACE ".Interface",
1071 "ApScan", DBUS_TYPE_UINT32_AS_STRING,
1072 set_apscan, set_apscan_complete, data, NULL);
1079 void g_supplicant_interface_set_data(GSupplicantInterface *interface,
1085 interface->data = data;
1088 interface->scan_callback = NULL;
1091 void *g_supplicant_interface_get_data(GSupplicantInterface *interface)
1096 return interface->data;
1099 const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface)
1104 return interface->ifname;
1107 const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface)
1112 return interface->driver;
1115 GSupplicantState g_supplicant_interface_get_state(
1116 GSupplicantInterface *interface)
1119 return G_SUPPLICANT_STATE_UNKNOWN;
1121 return interface->state;
1124 const char *g_supplicant_interface_get_wps_key(GSupplicantInterface *interface)
1129 return (const char *)interface->wps_cred.key;
1132 const void *g_supplicant_interface_get_wps_ssid(GSupplicantInterface *interface,
1133 unsigned int *ssid_len)
1138 if (!interface || interface->wps_cred.ssid_len == 0) {
1143 *ssid_len = interface->wps_cred.ssid_len;
1144 return interface->wps_cred.ssid;
1147 GSupplicantWpsState g_supplicant_interface_get_wps_state(
1148 GSupplicantInterface *interface)
1151 return G_SUPPLICANT_WPS_STATE_UNKNOWN;
1153 return interface->wps_state;
1156 unsigned int g_supplicant_interface_get_mode(GSupplicantInterface *interface)
1161 return interface->mode_capa;
1164 unsigned int g_supplicant_interface_get_max_scan_ssids(
1165 GSupplicantInterface *interface)
1170 if (interface->max_scan_ssids == 0)
1171 return WPAS_MAX_SCAN_SSIDS;
1173 return interface->max_scan_ssids;
1176 static void set_network_enabled(DBusMessageIter *iter, void *user_data)
1178 dbus_bool_t enable = *(dbus_bool_t *)user_data;
1180 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &enable);
1183 int g_supplicant_interface_enable_selected_network(GSupplicantInterface *interface,
1189 if (!interface->network_path)
1192 SUPPLICANT_DBG(" ");
1193 return supplicant_dbus_property_set(interface->network_path,
1194 SUPPLICANT_INTERFACE ".Network",
1195 "Enabled", DBUS_TYPE_BOOLEAN_AS_STRING,
1196 set_network_enabled, NULL, &enable, NULL);
1199 dbus_bool_t g_supplicant_interface_get_ready(GSupplicantInterface *interface)
1204 return interface->ready;
1207 GSupplicantInterface *g_supplicant_network_get_interface(
1208 GSupplicantNetwork *network)
1213 return network->interface;
1216 const char *g_supplicant_network_get_name(GSupplicantNetwork *network)
1218 if (!network || !network->name)
1221 return network->name;
1224 const char *g_supplicant_network_get_identifier(GSupplicantNetwork *network)
1226 if (!network || !network->group)
1229 return network->group;
1232 const char *g_supplicant_network_get_path(GSupplicantNetwork *network)
1234 if (!network || !network->path)
1237 return network->path;
1240 const char *g_supplicant_network_get_mode(GSupplicantNetwork *network)
1243 return G_SUPPLICANT_MODE_UNKNOWN;
1245 return mode2string(network->mode);
1248 const char *g_supplicant_network_get_security(GSupplicantNetwork *network)
1251 return G_SUPPLICANT_SECURITY_UNKNOWN;
1253 return security2string(network->security);
1256 const void *g_supplicant_network_get_ssid(GSupplicantNetwork *network,
1257 unsigned int *ssid_len)
1264 *ssid_len = network->ssid_len;
1265 return network->ssid;
1268 dbus_int16_t g_supplicant_network_get_signal(GSupplicantNetwork *network)
1273 return network->signal;
1276 dbus_uint16_t g_supplicant_network_get_frequency(GSupplicantNetwork *network)
1281 return network->frequency;
1284 dbus_bool_t g_supplicant_network_get_wps(GSupplicantNetwork *network)
1289 return network->wps;
1292 dbus_bool_t g_supplicant_network_is_wps_active(GSupplicantNetwork *network)
1297 if (network->wps_capabilities & G_SUPPLICANT_WPS_CONFIGURED)
1303 dbus_bool_t g_supplicant_network_is_wps_pbc(GSupplicantNetwork *network)
1308 if (network->wps_capabilities & G_SUPPLICANT_WPS_PBC)
1314 dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
1319 if (network->wps_capabilities & G_SUPPLICANT_WPS_REGISTRAR)
1325 GSupplicantInterface *g_supplicant_peer_get_interface(GSupplicantPeer *peer)
1330 return peer->interface;
1333 const char *g_supplicant_peer_get_path(GSupplicantPeer *peer)
1341 const char *g_supplicant_peer_get_identifier(GSupplicantPeer *peer)
1346 return peer->identifier;
1349 const void *g_supplicant_peer_get_device_address(GSupplicantPeer *peer)
1354 return peer->device_address;
1357 const void *g_supplicant_peer_get_iface_address(GSupplicantPeer *peer)
1362 return peer->iface_address;
1365 const char *g_supplicant_peer_get_name(GSupplicantPeer *peer)
1373 #if defined TIZEN_EXT
1374 bool g_supplicant_network_is_hs20AP(GSupplicantNetwork *network)
1379 return network->isHS20AP;
1382 const char *g_supplicant_network_get_eap(GSupplicantNetwork *network)
1384 if (!network || !network->eap)
1387 return network->eap;
1390 const char *g_supplicant_network_get_identity(GSupplicantNetwork *network)
1392 if (!network || !network->identity)
1395 return network->identity;
1398 const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network)
1400 if (!network || !network->phase2)
1403 return network->phase2;
1406 unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network)
1408 if (network == NULL)
1411 return network->keymgmt;
1415 const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer,
1418 if (!peer || !length)
1421 *length = peer->widi_ies_length;
1422 return peer->widi_ies;
1425 bool g_supplicant_peer_is_wps_pbc(GSupplicantPeer *peer)
1430 if (peer->wps_capabilities & G_SUPPLICANT_WPS_PBC)
1436 bool g_supplicant_peer_is_wps_pin(GSupplicantPeer *peer)
1441 if (peer->wps_capabilities & G_SUPPLICANT_WPS_PIN)
1447 bool g_supplicant_peer_is_in_a_group(GSupplicantPeer *peer)
1449 if (!peer || !peer->groups)
1455 GSupplicantInterface *g_supplicant_peer_get_group_interface(GSupplicantPeer *peer)
1460 return (GSupplicantInterface *) peer->current_group_iface;
1463 bool g_supplicant_peer_is_client(GSupplicantPeer *peer)
1465 GSupplicantGroup *group;
1471 for (list = peer->groups; list; list = list->next) {
1472 const char *path = list->data;
1474 group = g_hash_table_lookup(group_mapping, path);
1478 if (group->role != G_SUPPLICANT_GROUP_ROLE_CLIENT ||
1479 group->orig_interface != peer->interface)
1482 if (group->interface == peer->current_group_iface)
1489 bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer)
1494 return peer->connection_requested;
1497 #if defined TIZEN_EXT
1499 * Description: Network client requires additional wifi specific info
1501 const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
1503 if (network == NULL || network->best_bss == NULL)
1506 return (const unsigned char *)network->best_bss->bssid;
1509 unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
1511 if (network == NULL || network->best_bss == NULL)
1514 return network->best_bss->maxrate;
1517 const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
1519 if (network == NULL || network->best_bss == NULL)
1522 if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
1523 network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
1524 unsigned int pairwise;
1526 pairwise = network->best_bss->rsn_pairwise |
1527 network->best_bss->wpa_pairwise;
1529 if ((pairwise & G_SUPPLICANT_PAIRWISE_CCMP) &&
1530 (pairwise & G_SUPPLICANT_PAIRWISE_TKIP))
1532 else if (pairwise & G_SUPPLICANT_PAIRWISE_CCMP)
1534 else if (pairwise & G_SUPPLICANT_PAIRWISE_TKIP)
1537 } else if (network->best_bss->security == G_SUPPLICANT_SECURITY_WEP)
1539 else if (network->best_bss->security == G_SUPPLICANT_SECURITY_NONE)
1545 bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network)
1547 if (network == NULL || network->best_bss == NULL)
1550 if (network->best_bss->rsn_selected) {
1551 const char *mode = g_supplicant_network_get_enc_mode(network);
1552 if (g_strcmp0(mode, "aes") == 0 ||
1553 g_strcmp0(mode, "mixed") == 0)
1561 const void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network,
1562 unsigned int *wifi_vsie_len)
1569 *wifi_vsie_len = network->wifi_vsie_len;
1570 return network->wifi_vsie;
1574 static void merge_network(GSupplicantNetwork *network)
1577 const char *ssid, *mode, *key_mgmt;
1578 #if defined TIZEN_EXT
1579 GSupplicantInterface *interface;
1580 const char *isHS20AP;
1581 const char *eap, *identity, *phase2;
1583 unsigned int i, ssid_len;
1586 ssid = g_hash_table_lookup(network->config_table, "ssid");
1587 mode = g_hash_table_lookup(network->config_table, "mode");
1588 key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt");
1589 #if defined TIZEN_EXT
1590 isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP");
1591 eap = g_hash_table_lookup(network->config_table, "eap");
1592 identity = g_hash_table_lookup(network->config_table, "identity");
1593 phase2 = g_hash_table_lookup(network->config_table, "phase2");
1594 interface = network->interface;
1597 SUPPLICANT_DBG("ssid %s mode %s", ssid, mode);
1600 ssid_len = strlen(ssid);
1604 str = g_string_sized_new((ssid_len * 2) + 24);
1608 for (i = 0; i < ssid_len; i++)
1609 #if defined TIZEN_EXT
1613 g_string_append_printf(str, "%02x", ssid[i]);
1614 #if defined TIZEN_EXT
1618 if (g_strcmp0(mode, "0") == 0)
1619 g_string_append_printf(str, "_managed");
1620 else if (g_strcmp0(mode, "1") == 0)
1621 g_string_append_printf(str, "_adhoc");
1623 if (g_strcmp0(key_mgmt, "WPA-PSK") == 0)
1624 g_string_append_printf(str, "_psk");
1625 #if defined TIZEN_EXT
1626 else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0)
1627 g_string_append_printf(str, "_ieee8021x");
1629 g_string_append_printf(str, "_none");
1632 group = g_string_free(str, FALSE);
1634 SUPPLICANT_DBG("%s", group);
1636 #if defined TIZEN_EXT
1637 if (g_strcmp0(isHS20AP, "1") == 0) {
1638 network->isHS20AP = 1;
1640 g_free(network->eap);
1641 network->eap = g_strdup(eap);
1643 if (network->identity)
1644 g_free(network->identity);
1645 network->identity = g_strdup(identity);
1647 if (network->phase2)
1648 g_free(network->phase2);
1649 network->phase2 = g_strdup(phase2);
1651 network->isHS20AP = 0;
1654 interface->network_path = g_strdup(network->path);
1656 network->group = g_strdup(group);
1657 callback_network_merged(network);
1662 g_hash_table_destroy(network->config_table);
1664 g_free(network->path);
1668 static void network_property(const char *key, DBusMessageIter *iter,
1671 GSupplicantNetwork *network = user_data;
1673 if (!network->interface)
1677 merge_network(network);
1681 if (g_strcmp0(key, "Enabled") == 0) {
1682 dbus_bool_t enabled = FALSE;
1684 dbus_message_iter_get_basic(iter, &enabled);
1685 } else if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
1686 const char *str = NULL;
1688 dbus_message_iter_get_basic(iter, &str);
1690 g_hash_table_replace(network->config_table,
1691 g_strdup(key), g_strdup(str));
1694 SUPPLICANT_DBG("key %s type %c",
1695 key, dbus_message_iter_get_arg_type(iter));
1698 static void interface_network_added(DBusMessageIter *iter, void *user_data)
1700 GSupplicantInterface *interface = user_data;
1701 GSupplicantNetwork *network;
1702 const char *path = NULL;
1706 dbus_message_iter_get_basic(iter, &path);
1710 if (g_strcmp0(path, "/") == 0)
1713 network = g_try_new0(GSupplicantNetwork, 1);
1717 network->interface = interface;
1718 network->path = g_strdup(path);
1720 network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1723 dbus_message_iter_next(iter);
1724 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
1725 supplicant_dbus_property_foreach(iter, network_property,
1727 network_property(NULL, NULL, network);
1731 supplicant_dbus_property_get_all(path,
1732 SUPPLICANT_INTERFACE ".Network",
1733 network_property, network, NULL);
1736 static void interface_network_removed(DBusMessageIter *iter, void *user_data)
1742 static char *create_name(unsigned char *ssid, int ssid_len)
1745 const gchar *remainder, *invalid;
1746 int valid_bytes, remaining_bytes;
1748 if (ssid_len < 1 || ssid[0] == '\0')
1749 return g_strdup("");
1752 remainder = (const gchar *)ssid;
1753 remaining_bytes = ssid_len;
1755 while (remaining_bytes != 0) {
1756 if (g_utf8_validate(remainder, remaining_bytes,
1761 valid_bytes = invalid - remainder;
1764 string = g_string_sized_new(remaining_bytes);
1766 g_string_append_len(string, remainder, valid_bytes);
1768 /* append U+FFFD REPLACEMENT CHARACTER */
1769 g_string_append(string, "\357\277\275");
1771 remaining_bytes -= valid_bytes + 1;
1772 remainder = invalid + 1;
1776 return g_strndup((const gchar *)ssid, ssid_len + 1);
1778 g_string_append(string, remainder);
1780 return g_string_free(string, FALSE);
1783 static char *create_group(struct g_supplicant_bss *bss)
1787 const char *mode, *security;
1789 str = g_string_sized_new((bss->ssid_len * 2) + 24);
1793 if (bss->ssid_len > 0 && bss->ssid[0] != '\0') {
1794 for (i = 0; i < bss->ssid_len; i++)
1795 g_string_append_printf(str, "%02x", bss->ssid[i]);
1797 g_string_append_printf(str, "hidden");
1799 mode = mode2string(bss->mode);
1801 g_string_append_printf(str, "_%s", mode);
1803 security = security2string(bss->security);
1805 g_string_append_printf(str, "_%s", security);
1807 return g_string_free(str, FALSE);
1810 static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
1812 GSupplicantInterface *interface = bss->interface;
1813 GSupplicantNetwork *network;
1816 group = create_group(bss);
1817 SUPPLICANT_DBG("New group created: %s", group);
1822 network = g_hash_table_lookup(interface->network_table, group);
1825 SUPPLICANT_DBG("Network %s already exist", network->name);
1830 network = g_try_new0(GSupplicantNetwork, 1);
1836 network->interface = interface;
1838 network->path = g_strdup(bss->path);
1839 network->group = group;
1840 network->name = create_name(bss->ssid, bss->ssid_len);
1841 network->mode = bss->mode;
1842 network->security = bss->security;
1843 network->ssid_len = bss->ssid_len;
1844 memcpy(network->ssid, bss->ssid, bss->ssid_len);
1845 network->signal = bss->signal;
1846 network->frequency = bss->frequency;
1847 network->best_bss = bss;
1849 #if defined TIZEN_EXT
1850 network->keymgmt = bss->keymgmt;
1852 if (bss->wifi_vsie_len > 0) {
1853 SUPPLICANT_DBG("vsie len: %d", bss->wifi_vsie_len);
1854 network->wifi_vsie = (char *)g_try_malloc0(bss->wifi_vsie_len);
1855 if(network->wifi_vsie) {
1856 network->wifi_vsie_len = bss->wifi_vsie_len;
1857 memcpy(network->wifi_vsie, bss->wifi_vsie, network->wifi_vsie_len);
1859 SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie");
1863 network->isHS20AP = bss->hs20;
1866 SUPPLICANT_DBG("New network %s created", network->name);
1868 network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1871 network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
1874 g_hash_table_replace(interface->network_table,
1875 network->group, network);
1877 callback_network_added(network);
1880 /* We update network's WPS properties if only bss provides WPS. */
1881 if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
1882 network->wps = TRUE;
1883 network->wps_capabilities |= bss->wps_capabilities;
1887 * Do not change best BSS if we are connected. It will be done through
1888 * CurrentBSS property in case of misalignment with wpa_s or roaming.
1890 if (network != interface->current_network &&
1891 bss->signal > network->signal) {
1892 network->signal = bss->signal;
1893 network->best_bss = bss;
1894 callback_network_changed(network, "Signal");
1897 g_hash_table_replace(interface->bss_mapping, bss->path, network);
1898 g_hash_table_replace(network->bss_table, bss->path, bss);
1900 g_hash_table_replace(bss_mapping, bss->path, interface);
1905 static void bss_rates(DBusMessageIter *iter, void *user_data)
1907 struct g_supplicant_bss *bss = user_data;
1908 dbus_uint32_t rate = 0;
1910 dbus_message_iter_get_basic(iter, &rate);
1914 if (rate > bss->maxrate)
1915 bss->maxrate = rate;
1918 static void bss_keymgmt(DBusMessageIter *iter, void *user_data)
1920 unsigned int *keymgmt = user_data;
1921 const char *str = NULL;
1924 dbus_message_iter_get_basic(iter, &str);
1928 for (i = 0; keymgmt_map[i].str; i++)
1929 if (strcmp(str, keymgmt_map[i].str) == 0) {
1930 SUPPLICANT_DBG("Keymgmt: %s", str);
1931 *keymgmt |= keymgmt_map[i].val;
1936 static void bss_group(DBusMessageIter *iter, void *user_data)
1938 unsigned int *group = user_data;
1939 const char *str = NULL;
1942 dbus_message_iter_get_basic(iter, &str);
1946 for (i = 0; group_map[i].str; i++)
1947 if (strcmp(str, group_map[i].str) == 0) {
1948 SUPPLICANT_DBG("Group: %s", str);
1949 *group |= group_map[i].val;
1954 static void bss_pairwise(DBusMessageIter *iter, void *user_data)
1956 unsigned int *pairwise = user_data;
1957 const char *str = NULL;
1960 dbus_message_iter_get_basic(iter, &str);
1964 for (i = 0; pairwise_map[i].str; i++)
1965 if (strcmp(str, pairwise_map[i].str) == 0) {
1966 SUPPLICANT_DBG("Pairwise: %s", str);
1967 *pairwise |= pairwise_map[i].val;
1972 static void bss_wpa(const char *key, DBusMessageIter *iter,
1975 struct g_supplicant_bss *bss = user_data;
1976 unsigned int value = 0;
1978 SUPPLICANT_DBG("Key: %s", key);
1980 if (g_strcmp0(key, "KeyMgmt") == 0) {
1981 supplicant_dbus_array_foreach(iter, bss_keymgmt, &value);
1983 if (bss->rsn_selected)
1984 bss->rsn_keymgmt = value;
1986 bss->wpa_keymgmt = value;
1987 } else if (g_strcmp0(key, "Group") == 0) {
1988 supplicant_dbus_array_foreach(iter, bss_group, &value);
1990 if (bss->rsn_selected)
1991 bss->rsn_group = value;
1993 bss->wpa_group = value;
1994 } else if (g_strcmp0(key, "Pairwise") == 0) {
1995 supplicant_dbus_array_foreach(iter, bss_pairwise, &value);
1997 if (bss->rsn_selected)
1998 bss->rsn_pairwise = value;
2000 bss->wpa_pairwise = value;
2004 static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size,
2007 unsigned int len = 0;
2009 while (len + 4 < ie_size) {
2010 unsigned int hi = ie[len];
2011 unsigned int lo = ie[len + 1];
2012 unsigned int tmp_type = (hi << 8) + lo;
2013 unsigned int v_len = 0;
2015 /* hi and lo are used to recreate an unsigned int
2016 * based on 2 8bits length unsigned int. */
2020 v_len = (hi << 8) + lo;
2022 if (tmp_type == type) {
2023 unsigned int ret_value = 0;
2024 unsigned char *value = (unsigned char *)&ret_value;
2026 SUPPLICANT_DBG("IE: match type 0x%x", type);
2028 /* Verifying length relevance */
2029 if (v_len > sizeof(unsigned int) ||
2030 len + 4 + v_len > ie_size)
2033 memcpy(value, ie + len + 4, v_len);
2035 SUPPLICANT_DBG("returning 0x%x", ret_value);
2042 SUPPLICANT_DBG("returning 0");
2046 static void bss_process_ies(DBusMessageIter *iter, void *user_data)
2048 struct g_supplicant_bss *bss = user_data;
2049 const unsigned char WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
2050 #if defined TIZEN_EXT
2051 const unsigned char WIFI_OUI[] = {0x00, 0x16, 0x32};
2053 unsigned char *ie, *ie_end;
2054 DBusMessageIter array;
2058 #define WMM_WPA1_WPS_INFO 221
2059 #define WPS_INFO_MIN_LEN 6
2060 #define WPS_VERSION_TLV 0x104A
2061 #define WPS_STATE_TLV 0x1044
2062 #define WPS_METHODS_TLV 0x1012
2063 #define WPS_REGISTRAR_TLV 0x1041
2064 #define WPS_VERSION 0x10
2065 #define WPS_PBC 0x04
2066 #define WPS_PIN 0x00
2067 #define WPS_CONFIGURED 0x02
2068 #if defined TIZEN_EXT
2069 #define VENDOR_SPECIFIC_INFO 0xDD
2072 dbus_message_iter_recurse(iter, &array);
2073 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
2075 if (!ie || ie_len < 2)
2078 bss->wps_capabilities = 0;
2081 for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
2083 #if defined TIZEN_EXT
2084 if((ie[0] == VENDOR_SPECIFIC_INFO) && (memcmp(ie+2, WIFI_OUI, sizeof(WIFI_OUI)) == 0)) {
2085 SUPPLICANT_DBG("IE: match WIFI_OUI");
2086 bss->wifi_vsie = (char *)g_try_malloc0(ie[1] + 2); // tag number size(1), tag length size(1)
2087 if (bss->wifi_vsie) {
2088 bss->wifi_vsie_len = ie[1] + 2;
2089 memcpy(bss->wifi_vsie, ie, bss->wifi_vsie_len);
2091 SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie");
2096 if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
2097 memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
2100 SUPPLICANT_DBG("IE: match WPS_OUI");
2102 value = get_tlv(&ie[6], ie[1], WPS_STATE_TLV);
2103 if (get_tlv(&ie[6], ie[1], WPS_VERSION_TLV) == WPS_VERSION &&
2105 bss->keymgmt |= G_SUPPLICANT_KEYMGMT_WPS;
2107 if (value == WPS_CONFIGURED)
2108 bss->wps_capabilities |=
2109 G_SUPPLICANT_WPS_CONFIGURED;
2112 value = get_tlv(&ie[6], ie[1], WPS_METHODS_TLV);
2114 if (GUINT16_FROM_BE(value) == WPS_PBC)
2115 bss->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
2116 if (GUINT16_FROM_BE(value) == WPS_PIN)
2117 bss->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
2119 bss->wps_capabilities |=
2120 G_SUPPLICANT_WPS_PBC | G_SUPPLICANT_WPS_PIN;
2122 /* If the AP sends this it means it's advertizing
2123 * as a registrar and the WPS process is launched
2125 if (get_tlv(&ie[6], ie[1], WPS_REGISTRAR_TLV) != 0)
2126 bss->wps_capabilities |= G_SUPPLICANT_WPS_REGISTRAR;
2128 SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
2132 static void bss_compute_security(struct g_supplicant_bss *bss)
2135 * Combining RSN and WPA keymgmt
2136 * We combine it since parsing IEs might have set something for WPS. */
2137 bss->keymgmt |= bss->rsn_keymgmt | bss->wpa_keymgmt;
2139 bss->ieee8021x = FALSE;
2141 #if defined TIZEN_EXT
2142 bss->ft_ieee8021x = FALSE;
2143 bss->ft_psk = FALSE;
2146 #if defined TIZEN_EXT
2148 (G_SUPPLICANT_KEYMGMT_WPA_EAP |
2149 G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
2150 bss->ieee8021x = TRUE;
2151 else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
2152 bss->ft_ieee8021x = TRUE;
2155 (G_SUPPLICANT_KEYMGMT_WPA_EAP |
2156 G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
2157 G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
2158 bss->ieee8021x = TRUE;
2161 #if defined TIZEN_EXT
2163 (G_SUPPLICANT_KEYMGMT_WPA_PSK |
2164 G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
2166 else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
2170 (G_SUPPLICANT_KEYMGMT_WPA_PSK |
2171 G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
2172 G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
2177 bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
2179 bss->security = G_SUPPLICANT_SECURITY_PSK;
2180 #if defined TIZEN_EXT
2181 else if (bss->ft_psk)
2182 bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
2183 else if (bss->ft_ieee8021x == TRUE)
2184 bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
2186 else if (bss->privacy)
2187 bss->security = G_SUPPLICANT_SECURITY_WEP;
2189 bss->security = G_SUPPLICANT_SECURITY_NONE;
2193 static void bss_property(const char *key, DBusMessageIter *iter,
2196 struct g_supplicant_bss *bss = user_data;
2198 if (!bss->interface)
2201 SUPPLICANT_DBG("key %s", key);
2206 if (g_strcmp0(key, "BSSID") == 0) {
2207 DBusMessageIter array;
2208 unsigned char *addr;
2211 dbus_message_iter_recurse(iter, &array);
2212 dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
2215 memcpy(bss->bssid, addr, addr_len);
2216 } else if (g_strcmp0(key, "SSID") == 0) {
2217 DBusMessageIter array;
2218 unsigned char *ssid;
2221 dbus_message_iter_recurse(iter, &array);
2222 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
2224 if (ssid_len > 0 && ssid_len < 33) {
2225 memcpy(bss->ssid, ssid, ssid_len);
2226 bss->ssid_len = ssid_len;
2228 memset(bss->ssid, 0, sizeof(bss->ssid));
2231 } else if (g_strcmp0(key, "Capabilities") == 0) {
2232 dbus_uint16_t capabilities = 0x0000;
2234 dbus_message_iter_get_basic(iter, &capabilities);
2236 if (capabilities & IEEE80211_CAP_ESS)
2237 bss->mode = G_SUPPLICANT_MODE_INFRA;
2238 else if (capabilities & IEEE80211_CAP_IBSS)
2239 bss->mode = G_SUPPLICANT_MODE_IBSS;
2241 if (capabilities & IEEE80211_CAP_PRIVACY)
2242 bss->privacy = TRUE;
2243 } else if (g_strcmp0(key, "Mode") == 0) {
2244 const char *mode = NULL;
2246 dbus_message_iter_get_basic(iter, &mode);
2247 bss->mode = string2mode(mode);
2248 } else if (g_strcmp0(key, "Frequency") == 0) {
2249 dbus_uint16_t frequency = 0;
2251 dbus_message_iter_get_basic(iter, &frequency);
2252 bss->frequency = frequency;
2253 } else if (g_strcmp0(key, "Signal") == 0) {
2254 dbus_int16_t signal = 0;
2256 dbus_message_iter_get_basic(iter, &signal);
2258 bss->signal = signal;
2260 bss->signal = BSS_UNKNOWN_STRENGTH;
2262 } else if (g_strcmp0(key, "Level") == 0) {
2263 dbus_int32_t level = 0;
2265 dbus_message_iter_get_basic(iter, &level);
2266 } else if (g_strcmp0(key, "Rates") == 0) {
2267 supplicant_dbus_array_foreach(iter, bss_rates, bss);
2268 } else if (g_strcmp0(key, "MaxRate") == 0) {
2269 dbus_uint32_t maxrate = 0;
2271 dbus_message_iter_get_basic(iter, &maxrate);
2273 bss->maxrate = maxrate;
2274 } else if (g_strcmp0(key, "Privacy") == 0) {
2275 dbus_bool_t privacy = FALSE;
2277 dbus_message_iter_get_basic(iter, &privacy);
2278 bss->privacy = privacy;
2279 } else if (g_strcmp0(key, "RSN") == 0) {
2280 bss->rsn_selected = TRUE;
2282 supplicant_dbus_property_foreach(iter, bss_wpa, bss);
2283 } else if (g_strcmp0(key, "WPA") == 0) {
2284 bss->rsn_selected = FALSE;
2286 supplicant_dbus_property_foreach(iter, bss_wpa, bss);
2287 #if defined TIZEN_EXT
2288 } else if (g_strcmp0(key, "HS20") == 0) {
2289 dbus_bool_t hs20 = FALSE;
2290 dbus_message_iter_get_basic(iter, &hs20);
2293 } else if (g_strcmp0(key, "IEs") == 0)
2294 bss_process_ies(iter, bss);
2296 SUPPLICANT_DBG("key %s type %c",
2297 key, dbus_message_iter_get_arg_type(iter));
2300 static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
2303 GSupplicantInterface *interface = user_data;
2304 GSupplicantNetwork *network;
2305 struct g_supplicant_bss *bss;
2306 const char *path = NULL;
2310 dbus_message_iter_get_basic(iter, &path);
2314 if (g_strcmp0(path, "/") == 0)
2317 SUPPLICANT_DBG("%s", path);
2319 network = g_hash_table_lookup(interface->bss_mapping, path);
2321 bss = g_hash_table_lookup(network->bss_table, path);
2326 bss = g_try_new0(struct g_supplicant_bss, 1);
2330 bss->interface = interface;
2331 bss->path = g_strdup(path);
2332 bss->signal = BSS_UNKNOWN_STRENGTH;
2337 static void interface_bss_added_with_keys(DBusMessageIter *iter,
2340 struct g_supplicant_bss *bss;
2344 bss = interface_bss_added(iter, user_data);
2348 dbus_message_iter_next(iter);
2350 if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID)
2353 supplicant_dbus_property_foreach(iter, bss_property, bss);
2355 bss_compute_security(bss);
2356 if (add_or_replace_bss_to_network(bss) < 0)
2357 SUPPLICANT_DBG("add_or_replace_bss_to_network failed");
2360 static void interface_bss_added_without_keys(DBusMessageIter *iter,
2363 struct g_supplicant_bss *bss;
2367 bss = interface_bss_added(iter, user_data);
2371 supplicant_dbus_property_get_all(bss->path,
2372 SUPPLICANT_INTERFACE ".BSS",
2373 bss_property, bss, NULL);
2375 bss_compute_security(bss);
2376 if (add_or_replace_bss_to_network(bss) < 0)
2377 SUPPLICANT_DBG("add_or_replace_bss_to_network failed");
2380 static void update_signal(gpointer key, gpointer value,
2383 struct g_supplicant_bss *bss = value;
2384 GSupplicantNetwork *network = user_data;
2386 if (bss->signal > network->signal) {
2387 network->signal = bss->signal;
2388 network->best_bss = bss;
2392 static void update_network_signal(GSupplicantNetwork *network)
2394 if (g_hash_table_size(network->bss_table) <= 1 && network->best_bss)
2397 g_hash_table_foreach(network->bss_table,
2398 update_signal, network);
2400 SUPPLICANT_DBG("New network signal %d", network->signal);
2403 static void interface_current_bss(GSupplicantInterface *interface,
2404 DBusMessageIter *iter)
2406 GSupplicantNetwork *network;
2407 struct g_supplicant_bss *bss;
2410 dbus_message_iter_get_basic(iter, &path);
2411 if (g_strcmp0(path, "/") == 0) {
2412 interface->current_network = NULL;
2416 interface_bss_added_without_keys(iter, interface);
2418 network = g_hash_table_lookup(interface->bss_mapping, path);
2422 bss = g_hash_table_lookup(network->bss_table, path);
2426 interface->current_network = network;
2428 if (bss != network->best_bss) {
2430 * This is the case where either wpa_s got associated
2431 * to a BSS different than the one ConnMan considers
2432 * the best, or we are roaming.
2434 SUPPLICANT_DBG("Update best BSS for %s", network->name);
2436 network->best_bss = bss;
2438 if (network->signal != bss->signal) {
2439 SUPPLICANT_DBG("New network signal %d dBm",
2442 network->signal = bss->signal;
2443 callback_network_changed(network, "Signal");
2448 * wpa_s could notify about CurrentBSS in any state once
2449 * it got associated. It is not sure such notification will
2450 * arrive together with transition to ASSOCIATED state.
2451 * In fact, for networks with security WEP or OPEN, it
2452 * always arrives together with transition to COMPLETED.
2454 switch (interface->state) {
2455 case G_SUPPLICANT_STATE_UNKNOWN:
2456 case G_SUPPLICANT_STATE_DISABLED:
2457 case G_SUPPLICANT_STATE_DISCONNECTED:
2458 case G_SUPPLICANT_STATE_INACTIVE:
2459 case G_SUPPLICANT_STATE_SCANNING:
2460 case G_SUPPLICANT_STATE_AUTHENTICATING:
2461 case G_SUPPLICANT_STATE_ASSOCIATING:
2463 case G_SUPPLICANT_STATE_ASSOCIATED:
2464 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
2465 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
2466 case G_SUPPLICANT_STATE_COMPLETED:
2467 callback_network_associated(network);
2472 static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
2474 GSupplicantInterface *interface = user_data;
2475 GSupplicantNetwork *network;
2476 struct g_supplicant_bss *bss = NULL;
2477 const char *path = NULL;
2479 dbus_message_iter_get_basic(iter, &path);
2483 network = g_hash_table_lookup(interface->bss_mapping, path);
2487 bss = g_hash_table_lookup(network->bss_table, path);
2488 if (network->best_bss == bss) {
2489 network->best_bss = NULL;
2490 network->signal = BSS_UNKNOWN_STRENGTH;
2493 g_hash_table_remove(bss_mapping, path);
2495 g_hash_table_remove(interface->bss_mapping, path);
2496 g_hash_table_remove(network->bss_table, path);
2498 update_network_signal(network);
2500 if (g_hash_table_size(network->bss_table) == 0)
2501 g_hash_table_remove(interface->network_table, network->group);
2504 static void set_config_methods(DBusMessageIter *iter, void *user_data)
2506 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, user_data);
2509 static void wps_property(const char *key, DBusMessageIter *iter,
2512 GSupplicantInterface *interface = user_data;
2517 SUPPLICANT_DBG("key: %s", key);
2519 if (g_strcmp0(key, "ConfigMethods") == 0) {
2520 const char *config_methods = "push_button", *str = NULL;
2522 dbus_message_iter_get_basic(iter, &str);
2523 if (str && strlen(str) > 0) {
2524 /* It was already set at wpa_s level, don't modify it. */
2525 SUPPLICANT_DBG("%s", str);
2529 supplicant_dbus_property_set(interface->path,
2530 SUPPLICANT_INTERFACE ".Interface.WPS",
2531 "ConfigMethods", DBUS_TYPE_STRING_AS_STRING,
2532 set_config_methods, NULL, &config_methods, NULL);
2534 SUPPLICANT_DBG("No value. Set %s", config_methods);
2539 static void interface_property(const char *key, DBusMessageIter *iter,
2542 GSupplicantInterface *interface = user_data;
2547 SUPPLICANT_DBG("%s", key);
2550 debug_strvalmap("KeyMgmt capability", keymgmt_map,
2551 interface->keymgmt_capa);
2552 debug_strvalmap("AuthAlg capability", authalg_capa_map,
2553 interface->authalg_capa);
2554 debug_strvalmap("Protocol capability", proto_capa_map,
2555 interface->proto_capa);
2556 debug_strvalmap("Pairwise capability", pairwise_map,
2557 interface->pairwise_capa);
2558 debug_strvalmap("Group capability", group_map,
2559 interface->group_capa);
2560 debug_strvalmap("Scan capability", scan_capa_map,
2561 interface->scan_capa);
2562 debug_strvalmap("Mode capability", mode_capa_map,
2563 interface->mode_capa);
2565 supplicant_dbus_property_get_all(interface->path,
2566 SUPPLICANT_INTERFACE ".Interface.WPS",
2567 wps_property, interface, interface);
2569 if (interface->ready)
2570 callback_interface_added(interface);
2575 if (g_strcmp0(key, "Capabilities") == 0) {
2576 supplicant_dbus_property_foreach(iter, interface_capability,
2578 #if !defined TIZEN_EXT
2579 if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_P2P)
2580 interface->p2p_support = true;
2582 } else if (g_strcmp0(key, "State") == 0) {
2583 const char *str = NULL;
2585 dbus_message_iter_get_basic(iter, &str);
2587 if (string2state(str) != interface->state) {
2588 interface->state = string2state(str);
2589 callback_interface_state(interface);
2592 if (interface->ap_create_in_progress) {
2593 if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED)
2594 callback_ap_create_fail(interface);
2596 interface->ap_create_in_progress = false;
2599 if (interface->state == G_SUPPLICANT_STATE_DISABLED)
2600 interface->ready = FALSE;
2602 interface->ready = TRUE;
2604 SUPPLICANT_DBG("state %s (%d)", str, interface->state);
2605 } else if (g_strcmp0(key, "Scanning") == 0) {
2606 dbus_bool_t scanning = FALSE;
2608 dbus_message_iter_get_basic(iter, &scanning);
2609 interface->scanning = scanning;
2611 if (interface->ready) {
2612 if (interface->scanning)
2613 callback_scan_started(interface);
2615 callback_scan_finished(interface);
2617 } else if (g_strcmp0(key, "ApScan") == 0) {
2620 dbus_message_iter_get_basic(iter, &apscan);
2621 interface->apscan = apscan;
2622 } else if (g_strcmp0(key, "Ifname") == 0) {
2623 const char *str = NULL;
2625 dbus_message_iter_get_basic(iter, &str);
2627 g_free(interface->ifname);
2628 interface->ifname = g_strdup(str);
2630 } else if (g_strcmp0(key, "Driver") == 0) {
2631 const char *str = NULL;
2633 dbus_message_iter_get_basic(iter, &str);
2635 g_free(interface->driver);
2636 interface->driver = g_strdup(str);
2638 } else if (g_strcmp0(key, "BridgeIfname") == 0) {
2639 const char *str = NULL;
2641 dbus_message_iter_get_basic(iter, &str);
2643 g_free(interface->bridge);
2644 interface->bridge = g_strdup(str);
2646 } else if (g_strcmp0(key, "ConfigFile") == 0) {
2647 const char *str = NULL;
2649 dbus_message_iter_get_basic(iter, &str);
2650 if (str && strlen(str) > 0 && interface->ifname) {
2651 SUPPLICANT_DBG("New {%s, %s}", interface->ifname, str);
2652 g_hash_table_replace(config_file_table,
2653 g_strdup(interface->ifname), g_strdup(str));
2655 } else if (g_strcmp0(key, "CurrentBSS") == 0) {
2656 interface_current_bss(interface, iter);
2657 } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
2658 #if defined TIZEN_EXT
2659 if (interface->state != G_SUPPLICANT_STATE_COMPLETED)
2661 interface_network_added(iter, interface);
2662 } else if (g_strcmp0(key, "BSSs") == 0) {
2663 supplicant_dbus_array_foreach(iter,
2664 interface_bss_added_without_keys,
2666 } else if (g_strcmp0(key, "Blobs") == 0) {
2668 } else if (g_strcmp0(key, "Networks") == 0) {
2669 supplicant_dbus_array_foreach(iter, interface_network_added,
2671 } else if (g_strcmp0(key, "DisconnectReason") == 0) {
2673 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
2674 dbus_message_iter_get_basic(iter, &reason_code);
2675 callback_disconnect_reason_code(interface, reason_code);
2677 } else if (g_strcmp0(key, "AssocStatusCode") == 0) {
2679 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
2680 dbus_message_iter_get_basic(iter, &status_code);
2681 callback_assoc_status_code(interface, status_code);
2684 SUPPLICANT_DBG("key %s type %c",
2685 key, dbus_message_iter_get_arg_type(iter));
2689 static void scan_network_update(DBusMessageIter *iter, void *user_data)
2691 GSupplicantInterface *interface = user_data;
2692 GSupplicantNetwork *network;
2698 dbus_message_iter_get_basic(iter, &path);
2703 if (g_strcmp0(path, "/") == 0)
2706 /* Update the network details based on scan BSS data */
2707 network = g_hash_table_lookup(interface->bss_mapping, path);
2709 callback_network_added(network);
2712 static void scan_bss_data(const char *key, DBusMessageIter *iter,
2715 GSupplicantInterface *interface = user_data;
2717 /*Fixed : stucking in scanning state when scan failed*/
2718 #if defined TIZEN_EXT
2719 GSupplicantInterfaceCallback scan_callback;
2723 supplicant_dbus_array_foreach(iter, scan_network_update,
2726 #if defined TIZEN_EXT
2727 scan_callback = interface->scan_callback;
2730 if (interface->scan_callback)
2731 interface->scan_callback(0, interface, interface->scan_data);
2733 #if defined TIZEN_EXT
2734 if (interface->scan_callback == scan_callback) {
2736 interface->scan_callback = NULL;
2737 interface->scan_data = NULL;
2738 #if defined TIZEN_EXT
2743 static GSupplicantInterface *interface_alloc(const char *path)
2745 GSupplicantInterface *interface;
2747 interface = g_try_new0(GSupplicantInterface, 1);
2751 interface->path = g_strdup(path);
2753 interface->network_table = g_hash_table_new_full(g_str_hash,
2754 g_str_equal, NULL, remove_network);
2755 interface->peer_table = g_hash_table_new_full(g_str_hash,
2756 g_str_equal, NULL, remove_peer);
2757 interface->group_table = g_hash_table_new_full(g_str_hash,
2758 g_str_equal, NULL, remove_group);
2759 interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
2762 g_hash_table_replace(interface_table, interface->path, interface);
2767 static void interface_added(DBusMessageIter *iter, void *user_data)
2769 GSupplicantInterface *interface;
2770 const char *path = NULL;
2771 bool properties_appended = GPOINTER_TO_UINT(user_data);
2775 dbus_message_iter_get_basic(iter, &path);
2779 if (g_strcmp0(path, "/") == 0)
2782 interface = g_hash_table_lookup(interface_table, path);
2786 interface = interface_alloc(path);
2790 if (!properties_appended) {
2791 supplicant_dbus_property_get_all(path,
2792 SUPPLICANT_INTERFACE ".Interface",
2793 interface_property, interface,
2798 dbus_message_iter_next(iter);
2799 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
2800 supplicant_dbus_property_foreach(iter, interface_property,
2802 interface_property(NULL, NULL, interface);
2806 static void interface_removed(DBusMessageIter *iter, void *user_data)
2808 const char *path = NULL;
2809 GSupplicantInterface *interface = user_data;
2811 dbus_message_iter_get_basic(iter, &path);
2815 interface = g_hash_table_lookup(interface_table, path);
2816 g_supplicant_interface_cancel(interface);
2818 g_hash_table_remove(interface_table, path);
2821 static void eap_method(DBusMessageIter *iter, void *user_data)
2823 const char *str = NULL;
2826 dbus_message_iter_get_basic(iter, &str);
2830 for (i = 0; eap_method_map[i].str; i++)
2831 if (strcmp(str, eap_method_map[i].str) == 0) {
2832 eap_methods |= eap_method_map[i].val;
2837 static void service_property(const char *key, DBusMessageIter *iter,
2841 callback_system_ready();
2845 if (g_strcmp0(key, "DebugLevel") == 0) {
2846 const char *str = NULL;
2849 dbus_message_iter_get_basic(iter, &str);
2850 for (i = 0; debug_strings[i]; i++)
2851 if (g_strcmp0(debug_strings[i], str) == 0) {
2855 SUPPLICANT_DBG("Debug level %d", debug_level);
2856 } else if (g_strcmp0(key, "DebugTimestamp") == 0) {
2857 dbus_message_iter_get_basic(iter, &debug_timestamp);
2858 SUPPLICANT_DBG("Debug timestamp %u", debug_timestamp);
2859 } else if (g_strcmp0(key, "DebugShowKeys") == 0) {
2860 dbus_message_iter_get_basic(iter, &debug_showkeys);
2861 SUPPLICANT_DBG("Debug show keys %u", debug_showkeys);
2862 } else if (g_strcmp0(key, "Interfaces") == 0) {
2863 supplicant_dbus_array_foreach(iter, interface_added, NULL);
2864 } else if (g_strcmp0(key, "EapMethods") == 0) {
2865 supplicant_dbus_array_foreach(iter, eap_method, NULL);
2866 debug_strvalmap("EAP method", eap_method_map, eap_methods);
2867 } else if (g_strcmp0(key, "Country") == 0) {
2868 const char *country = NULL;
2870 dbus_message_iter_get_basic(iter, &country);
2871 SUPPLICANT_DBG("Country %s", country);
2873 SUPPLICANT_DBG("key %s type %c",
2874 key, dbus_message_iter_get_arg_type(iter));
2877 static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
2879 const char *name = NULL, *old = NULL, *new = NULL;
2883 if (g_strcmp0(path, DBUS_PATH_DBUS) != 0)
2886 dbus_message_iter_get_basic(iter, &name);
2890 if (g_strcmp0(name, SUPPLICANT_SERVICE) != 0)
2893 dbus_message_iter_next(iter);
2894 dbus_message_iter_get_basic(iter, &old);
2895 dbus_message_iter_next(iter);
2896 dbus_message_iter_get_basic(iter, &new);
2901 if (strlen(old) > 0 && strlen(new) == 0) {
2902 system_available = FALSE;
2903 g_hash_table_remove_all(bss_mapping);
2904 g_hash_table_remove_all(peer_mapping);
2905 g_hash_table_remove_all(group_mapping);
2906 g_hash_table_remove_all(config_file_table);
2907 g_hash_table_remove_all(interface_table);
2908 callback_system_killed();
2911 if (strlen(new) > 0 && strlen(old) == 0) {
2912 system_available = TRUE;
2913 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
2914 SUPPLICANT_INTERFACE,
2915 service_property, NULL, NULL);
2919 static void signal_properties_changed(const char *path, DBusMessageIter *iter)
2923 if (g_strcmp0(path, SUPPLICANT_PATH) != 0)
2926 supplicant_dbus_property_foreach(iter, service_property, NULL);
2929 static void signal_interface_added(const char *path, DBusMessageIter *iter)
2931 SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
2933 if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
2934 interface_added(iter, GUINT_TO_POINTER(true));
2937 static void signal_interface_removed(const char *path, DBusMessageIter *iter)
2941 if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
2942 interface_removed(iter, NULL);
2945 static void signal_interface_changed(const char *path, DBusMessageIter *iter)
2947 GSupplicantInterface *interface;
2951 interface = g_hash_table_lookup(interface_table, path);
2955 supplicant_dbus_property_foreach(iter, interface_property, interface);
2958 static void signal_scan_done(const char *path, DBusMessageIter *iter)
2960 GSupplicantInterface *interface;
2961 dbus_bool_t success = FALSE;
2965 interface = g_hash_table_lookup(interface_table, path);
2969 dbus_message_iter_get_basic(iter, &success);
2971 if (interface->scanning) {
2972 callback_scan_finished(interface);
2973 interface->scanning = FALSE;
2977 * If scan is unsuccessful return -EIO else get the scanned BSSs
2978 * and update the network details accordingly
2981 if (interface->scan_callback)
2982 interface->scan_callback(-EIO, interface,
2983 interface->scan_data);
2985 interface->scan_callback = NULL;
2986 interface->scan_data = NULL;
2991 supplicant_dbus_property_get(path, SUPPLICANT_INTERFACE ".Interface",
2992 "BSSs", scan_bss_data, interface, interface);
2995 static void signal_bss_added(const char *path, DBusMessageIter *iter)
2997 GSupplicantInterface *interface;
3001 interface = g_hash_table_lookup(interface_table, path);
3005 interface_bss_added_with_keys(iter, interface);
3008 static void signal_bss_removed(const char *path, DBusMessageIter *iter)
3010 GSupplicantInterface *interface;
3014 interface = g_hash_table_lookup(interface_table, path);
3018 interface_bss_removed(iter, interface);
3021 static void signal_network_added(const char *path, DBusMessageIter *iter)
3023 GSupplicantInterface *interface;
3027 interface = g_hash_table_lookup(interface_table, path);
3031 interface_network_added(iter, interface);
3034 static void signal_network_removed(const char *path, DBusMessageIter *iter)
3036 GSupplicantInterface *interface;
3040 interface = g_hash_table_lookup(interface_table, path);
3044 interface_network_removed(iter, interface);
3047 static void signal_bss_changed(const char *path, DBusMessageIter *iter)
3049 GSupplicantInterface *interface;
3050 GSupplicantNetwork *network;
3051 GSupplicantSecurity old_security;
3052 struct g_supplicant_bss *bss;
3056 interface = g_hash_table_lookup(bss_mapping, path);
3060 network = g_hash_table_lookup(interface->bss_mapping, path);
3064 bss = g_hash_table_lookup(network->bss_table, path);
3068 supplicant_dbus_property_foreach(iter, bss_property, bss);
3069 #if defined TIZEN_EXT
3070 network->frequency = bss->frequency;
3072 old_security = network->security;
3073 bss_compute_security(bss);
3075 if (old_security != bss->security) {
3076 struct g_supplicant_bss *new_bss;
3078 SUPPLICANT_DBG("New network security for %s", bss->ssid);
3080 /* Security change policy:
3081 * - we first copy the current bss into a new one with
3082 * its own pointer (path)
3083 * - we remove the current bss related network which will
3084 * tell the plugin about such removal. This is done due
3085 * to the fact that a security change means a group change
3086 * so a complete network change.
3087 * (current bss becomes invalid as well)
3088 * - we add the new bss: it adds new network and tell the
3089 * plugin about it. */
3091 new_bss = g_try_new0(struct g_supplicant_bss, 1);
3095 memcpy(new_bss, bss, sizeof(struct g_supplicant_bss));
3096 new_bss->path = g_strdup(bss->path);
3098 g_hash_table_remove(interface->network_table, network->group);
3100 if (add_or_replace_bss_to_network(new_bss) < 0) {
3101 /* Remove entries in hash tables to handle the
3102 * failure in add_or_replace_bss_to_network
3104 g_hash_table_remove(bss_mapping, path);
3105 g_hash_table_remove(interface->bss_mapping, path);
3106 g_hash_table_remove(network->bss_table, path);
3112 #if defined TIZEN_EXT
3113 if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
3114 network->wps = TRUE;
3115 network->wps_capabilities |= bss->wps_capabilities;
3117 network->wps = FALSE;
3120 /* Consider only property changes of the connected BSS */
3121 if (network == interface->current_network && bss != network->best_bss)
3124 if (bss->signal == network->signal)
3129 callback_network_changed(network, "");
3135 * If the new signal is lower than the SSID signal, we need
3136 * to check for the new maximum.
3138 if (bss->signal < network->signal) {
3139 if (bss != network->best_bss)
3144 callback_network_changed(network, "");
3148 network->signal = bss->signal;
3149 update_network_signal(network);
3151 network->signal = bss->signal;
3152 network->best_bss = bss;
3155 SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid,
3158 callback_network_changed(network, "Signal");
3161 static void wps_credentials(const char *key, DBusMessageIter *iter,
3164 GSupplicantInterface *interface = user_data;
3169 SUPPLICANT_DBG("key %s", key);
3171 if (g_strcmp0(key, "Key") == 0) {
3172 DBusMessageIter array;
3173 unsigned char *key_val;
3176 dbus_message_iter_recurse(iter, &array);
3177 dbus_message_iter_get_fixed_array(&array, &key_val, &key_len);
3179 g_free(interface->wps_cred.key);
3180 interface->wps_cred.key = g_try_malloc0(
3181 sizeof(char) * key_len + 1);
3183 if (!interface->wps_cred.key)
3186 memcpy(interface->wps_cred.key, key_val,
3187 sizeof(char) * key_len);
3189 SUPPLICANT_DBG("WPS key present");
3190 } else if (g_strcmp0(key, "SSID") == 0) {
3191 DBusMessageIter array;
3192 unsigned char *ssid;
3195 dbus_message_iter_recurse(iter, &array);
3196 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
3198 if (ssid_len > 0 && ssid_len < 33) {
3199 memcpy(interface->wps_cred.ssid, ssid, ssid_len);
3200 interface->wps_cred.ssid_len = ssid_len;
3202 memset(interface->wps_cred.ssid, 0, 32);
3203 interface->wps_cred.ssid_len = 0;
3208 static void signal_wps_credentials(const char *path, DBusMessageIter *iter)
3210 GSupplicantInterface *interface;
3214 interface = g_hash_table_lookup(interface_table, path);
3218 supplicant_dbus_property_foreach(iter, wps_credentials, interface);
3221 static void wps_event_args(const char *key, DBusMessageIter *iter,
3224 GSupplicantInterface *interface = user_data;
3226 if (!key || !interface)
3229 SUPPLICANT_DBG("Arg Key %s", key);
3232 static void signal_wps_event(const char *path, DBusMessageIter *iter)
3234 GSupplicantInterface *interface;
3235 const char *name = NULL;
3239 interface = g_hash_table_lookup(interface_table, path);
3243 dbus_message_iter_get_basic(iter, &name);
3245 SUPPLICANT_DBG("Name: %s", name);
3247 if (g_strcmp0(name, "success") == 0)
3248 interface->wps_state = G_SUPPLICANT_WPS_STATE_SUCCESS;
3249 else if (g_strcmp0(name, "failed") == 0)
3250 interface->wps_state = G_SUPPLICANT_WPS_STATE_FAIL;
3252 interface->wps_state = G_SUPPLICANT_WPS_STATE_UNKNOWN;
3254 if (!dbus_message_iter_has_next(iter))
3257 dbus_message_iter_next(iter);
3259 supplicant_dbus_property_foreach(iter, wps_event_args, interface);
3262 #if defined TIZEN_EXT
3263 static void signal_power_off(const char *path, DBusMessageIter *iter)
3265 int poweroff_state = 0;
3267 dbus_message_iter_get_basic(iter, &poweroff_state);
3269 SUPPLICANT_DBG("poweroff_state(%d)", poweroff_state);
3271 /* POWER_OFF_DIRECT 2 && POWER_OFF_RESTART 3 */
3272 if (poweroff_state != 2 && poweroff_state != 3)
3275 if (callbacks_pointer == NULL)
3278 if (callbacks_pointer->system_power_off == NULL)
3281 callbacks_pointer->system_power_off();
3285 static void signal_station_connected(const char *path, DBusMessageIter *iter)
3287 GSupplicantInterface *interface;
3288 const char *sta_mac = NULL;
3290 SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
3292 if (callbacks_pointer->add_station == NULL)
3295 if (g_strcmp0(path, "/") == 0)
3298 interface = g_hash_table_lookup(interface_table, path);
3299 if (interface == NULL)
3302 dbus_message_iter_get_basic(iter, &sta_mac);
3303 if (sta_mac == NULL)
3306 SUPPLICANT_DBG("New station %s connected", sta_mac);
3307 callbacks_pointer->add_station(sta_mac);
3310 static void signal_station_disconnected(const char *path, DBusMessageIter *iter)
3312 GSupplicantInterface *interface;
3313 const char *sta_mac = NULL;
3315 SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
3317 if (callbacks_pointer->remove_station == NULL)
3320 if (g_strcmp0(path, "/") == 0)
3323 interface = g_hash_table_lookup(interface_table, path);
3324 if (interface == NULL)
3327 dbus_message_iter_get_basic(iter, &sta_mac);
3328 if (sta_mac == NULL)
3331 SUPPLICANT_DBG("Station %s disconnected", sta_mac);
3332 callbacks_pointer->remove_station(sta_mac);
3335 static void create_peer_identifier(GSupplicantPeer *peer)
3337 const unsigned char test[ETH_ALEN] = {};
3342 if (!memcmp(peer->device_address, test, ETH_ALEN)) {
3343 peer->identifier = g_strdup(peer->name);
3347 peer->identifier = g_malloc0(19);
3348 snprintf(peer->identifier, 19, "%02x%02x%02x%02x%02x%02x",
3349 peer->device_address[0],
3350 peer->device_address[1],
3351 peer->device_address[2],
3352 peer->device_address[3],
3353 peer->device_address[4],
3354 peer->device_address[5]);
3357 struct peer_property_data {
3358 GSupplicantPeer *peer;
3360 bool groups_changed;
3361 bool services_changed;
3364 static void peer_groups_relation(DBusMessageIter *iter, void *user_data)
3366 struct peer_property_data *data = user_data;
3367 GSupplicantPeer *peer = data->peer;
3368 GSupplicantGroup *group;
3369 const char *str = NULL;
3372 dbus_message_iter_get_basic(iter, &str);
3376 group = g_hash_table_lookup(group_mapping, str);
3380 elem = g_slist_find_custom(data->old_groups, str, (GCompareFunc)g_strcmp0);
3382 data->old_groups = g_slist_remove_link(data->old_groups, elem);
3383 peer->groups = g_slist_concat(elem, peer->groups);
3385 peer->groups = g_slist_prepend(peer->groups, g_strdup(str));
3386 data->groups_changed = true;
3390 static void peer_property(const char *key, DBusMessageIter *iter,
3393 GSupplicantPeer *pending_peer;
3394 struct peer_property_data *data = user_data;
3395 GSupplicantPeer *peer = data->peer;
3397 SUPPLICANT_DBG("key: %s", key);
3399 if (!peer->interface)
3404 create_peer_identifier(peer);
3405 callback_peer_found(peer);
3406 pending_peer = g_hash_table_lookup(
3407 pending_peer_connection, peer->path);
3409 if (pending_peer && pending_peer == peer) {
3410 callback_peer_request(peer);
3411 g_hash_table_remove(pending_peer_connection,
3421 if (g_strcmp0(key, "DeviceAddress") == 0) {
3422 unsigned char *dev_addr;
3423 DBusMessageIter array;
3426 dbus_message_iter_recurse(iter, &array);
3427 dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
3429 if (len == ETH_ALEN)
3430 memcpy(peer->device_address, dev_addr, len);
3431 } else if (g_strcmp0(key, "DeviceName") == 0) {
3432 const char *str = NULL;
3434 dbus_message_iter_get_basic(iter, &str);
3436 peer->name = g_strdup(str);
3437 } else if (g_strcmp0(key, "config_method") == 0) {
3438 uint16_t wps_config;
3440 dbus_message_iter_get_basic(iter, &wps_config);
3442 if (wps_config & G_SUPPLICANT_WPS_CONFIG_PBC)
3443 peer->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
3444 if (wps_config & ~G_SUPPLICANT_WPS_CONFIG_PBC)
3445 peer->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
3446 } else if (g_strcmp0(key, "Groups") == 0) {
3447 data->old_groups = peer->groups;
3448 peer->groups = NULL;
3450 supplicant_dbus_array_foreach(iter,
3451 peer_groups_relation, data);
3452 if (g_slist_length(data->old_groups) > 0) {
3453 g_slist_free_full(data->old_groups, g_free);
3454 data->groups_changed = true;
3456 } else if (g_strcmp0(key, "IEs") == 0) {
3457 DBusMessageIter array;
3461 dbus_message_iter_recurse(iter, &array);
3462 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
3464 if (!ie || ie_len < 2)
3467 if (peer->widi_ies) {
3468 if (memcmp(peer->widi_ies, ie, ie_len) == 0)
3471 g_free(peer->widi_ies);
3472 peer->widi_ies_length = 0;
3475 peer->widi_ies = g_malloc0(ie_len * sizeof(unsigned char));
3477 memcpy(peer->widi_ies, ie, ie_len);
3478 peer->widi_ies_length = ie_len;
3479 data->services_changed = true;
3483 static void signal_peer_found(const char *path, DBusMessageIter *iter)
3485 struct peer_property_data *property_data;
3486 GSupplicantInterface *interface;
3487 const char *obj_path = NULL;
3488 GSupplicantPeer *peer;
3492 interface = g_hash_table_lookup(interface_table, path);
3496 dbus_message_iter_get_basic(iter, &obj_path);
3497 if (!obj_path || g_strcmp0(obj_path, "/") == 0)
3500 peer = g_hash_table_lookup(interface->peer_table, obj_path);
3504 peer = g_try_new0(GSupplicantPeer, 1);
3508 peer->interface = interface;
3509 peer->path = g_strdup(obj_path);
3510 g_hash_table_insert(interface->peer_table, peer->path, peer);
3511 g_hash_table_replace(peer_mapping, peer->path, interface);
3513 property_data = dbus_malloc0(sizeof(struct peer_property_data));
3514 property_data->peer = peer;
3516 dbus_message_iter_next(iter);
3517 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
3518 supplicant_dbus_property_foreach(iter, peer_property,
3520 peer_property(NULL, NULL, property_data);
3524 supplicant_dbus_property_get_all(obj_path,
3525 SUPPLICANT_INTERFACE ".Peer",
3526 peer_property, property_data, NULL);
3529 static void signal_peer_lost(const char *path, DBusMessageIter *iter)
3531 GSupplicantInterface *interface;
3532 const char *obj_path = NULL;
3533 GSupplicantPeer *peer;
3537 interface = g_hash_table_lookup(interface_table, path);
3541 dbus_message_iter_get_basic(iter, &obj_path);
3542 if (!obj_path || g_strcmp0(obj_path, "/") == 0)
3545 peer = g_hash_table_lookup(interface->peer_table, obj_path);
3549 g_hash_table_remove(interface->peer_table, obj_path);
3552 static void signal_peer_changed(const char *path, DBusMessageIter *iter)
3554 struct peer_property_data *property_data;
3555 GSupplicantInterface *interface;
3556 GSupplicantPeer *peer;
3560 interface = g_hash_table_lookup(peer_mapping, path);
3564 peer = g_hash_table_lookup(interface->peer_table, path);
3566 g_hash_table_remove(peer_mapping, path);
3570 property_data = dbus_malloc0(sizeof(struct peer_property_data));
3571 property_data->peer = peer;
3573 supplicant_dbus_property_foreach(iter, peer_property, property_data);
3574 if (property_data->services_changed)
3575 callback_peer_changed(peer,
3576 G_SUPPLICANT_PEER_SERVICES_CHANGED);
3578 if (property_data->groups_changed)
3579 callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_CHANGED);
3581 dbus_free(property_data);
3583 if (!g_supplicant_peer_is_in_a_group(peer))
3584 peer->connection_requested = false;
3587 struct group_sig_data {
3588 const char *peer_obj_path;
3589 unsigned char iface_address[ETH_ALEN];
3590 const char *interface_obj_path;
3591 const char *group_obj_path;
3595 static void group_sig_property(const char *key, DBusMessageIter *iter,
3598 struct group_sig_data *data = user_data;
3603 if (g_strcmp0(key, "peer_interface_addr") == 0) {
3604 unsigned char *dev_addr;
3605 DBusMessageIter array;
3608 dbus_message_iter_recurse(iter, &array);
3609 dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
3611 if (len == ETH_ALEN)
3612 memcpy(data->iface_address, dev_addr, len);
3613 } else if (g_strcmp0(key, "role") == 0) {
3614 const char *str = NULL;
3616 dbus_message_iter_get_basic(iter, &str);
3617 if (g_strcmp0(str, "GO") == 0)
3618 data->role = G_SUPPLICANT_GROUP_ROLE_GO;
3620 data->role = G_SUPPLICANT_GROUP_ROLE_CLIENT;
3621 } else if (g_strcmp0(key, "peer_object") == 0)
3622 dbus_message_iter_get_basic(iter, &data->peer_obj_path);
3623 else if (g_strcmp0(key, "interface_object") == 0)
3624 dbus_message_iter_get_basic(iter, &data->interface_obj_path);
3625 else if (g_strcmp0(key, "group_object") == 0)
3626 dbus_message_iter_get_basic(iter, &data->group_obj_path);
3630 static void signal_group_success(const char *path, DBusMessageIter *iter)
3632 GSupplicantInterface *interface;
3633 struct group_sig_data data = {};
3634 GSupplicantPeer *peer;
3638 interface = g_hash_table_lookup(interface_table, path);
3642 supplicant_dbus_property_foreach(iter, group_sig_property, &data);
3643 if (!data.peer_obj_path)
3646 peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
3650 memcpy(peer->iface_address, data.iface_address, ETH_ALEN);
3651 interface->pending_peer_path = peer->path;
3654 static void signal_group_failure(const char *path, DBusMessageIter *iter)
3656 GSupplicantInterface *interface;
3657 struct group_sig_data data = {};
3658 GSupplicantPeer *peer;
3662 interface = g_hash_table_lookup(interface_table, path);
3666 supplicant_dbus_property_foreach(iter, group_sig_property, &data);
3667 if (!data.peer_obj_path)
3670 peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
3674 callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_FAILED);
3675 peer->connection_requested = false;
3678 static void signal_group_started(const char *path, DBusMessageIter *iter)
3680 GSupplicantInterface *interface, *g_interface;
3681 struct group_sig_data data = {};
3682 GSupplicantGroup *group;
3683 GSupplicantPeer *peer;
3687 interface = g_hash_table_lookup(interface_table, path);
3691 supplicant_dbus_property_foreach(iter, group_sig_property, &data);
3692 if (!data.interface_obj_path || !data.group_obj_path)
3695 peer = g_hash_table_lookup(interface->peer_table,
3696 interface->pending_peer_path);
3697 interface->pending_peer_path = NULL;
3701 g_interface = g_hash_table_lookup(interface_table,
3702 data.interface_obj_path);
3706 group = g_hash_table_lookup(interface->group_table,
3707 data.group_obj_path);
3711 group = g_try_new0(GSupplicantGroup, 1);
3715 group->interface = g_interface;
3716 group->orig_interface = interface;
3717 group->path = g_strdup(data.group_obj_path);
3718 group->role = data.role;
3720 g_hash_table_insert(interface->group_table, group->path, group);
3721 g_hash_table_replace(group_mapping, group->path, group);
3723 peer->current_group_iface = g_interface;
3724 callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_STARTED);
3727 static void remove_peer_group_interface(GHashTable *group_table,
3730 GSupplicantGroup *group;
3731 GHashTableIter iter;
3732 gpointer value, key;
3737 group = g_hash_table_lookup(group_table, path);
3739 if (!group || !group->orig_interface)
3742 g_hash_table_iter_init(&iter, group->orig_interface->peer_table);
3744 while (g_hash_table_iter_next(&iter, &key, &value)) {
3745 GSupplicantPeer *peer = value;
3747 if (peer->current_group_iface == group->interface)
3748 peer->current_group_iface = NULL;
3752 static void signal_group_finished(const char *path, DBusMessageIter *iter)
3754 GSupplicantInterface *interface;
3755 struct group_sig_data data = {};
3759 interface = g_hash_table_lookup(interface_table, path);
3763 supplicant_dbus_property_foreach(iter, group_sig_property, &data);
3764 if (!data.interface_obj_path || !data.group_obj_path)
3767 remove_peer_group_interface(interface->group_table, data.group_obj_path);
3769 g_hash_table_remove(group_mapping, data.group_obj_path);
3771 g_hash_table_remove(interface->group_table, data.group_obj_path);
3774 static void signal_group_request(const char *path, DBusMessageIter *iter)
3776 GSupplicantInterface *interface;
3777 GSupplicantPeer *peer;
3778 const char *obj_path;
3782 interface = g_hash_table_lookup(interface_table, path);
3786 dbus_message_iter_get_basic(iter, &obj_path);
3787 if (!obj_path || !g_strcmp0(obj_path, "/"))
3790 peer = g_hash_table_lookup(interface->peer_table, obj_path);
3795 * Peer has been previously found and property set,
3796 * otherwise, defer connection to when peer property
3799 if (peer->identifier)
3800 callback_peer_request(peer);
3802 g_hash_table_replace(pending_peer_connection, peer->path, peer);
3805 static void signal_group_peer_joined(const char *path, DBusMessageIter *iter)
3807 const char *peer_path = NULL;
3808 GSupplicantInterface *interface;
3809 GSupplicantGroup *group;
3810 GSupplicantPeer *peer;
3814 group = g_hash_table_lookup(group_mapping, path);
3818 dbus_message_iter_get_basic(iter, &peer_path);
3822 interface = g_hash_table_lookup(peer_mapping, peer_path);
3826 peer = g_hash_table_lookup(interface->peer_table, peer_path);
3830 group->members = g_slist_prepend(group->members, g_strdup(peer_path));
3832 callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_JOINED);
3835 static void signal_group_peer_disconnected(const char *path, DBusMessageIter *iter)
3837 const char *peer_path = NULL;
3838 GSupplicantInterface *interface;
3839 GSupplicantGroup *group;
3840 GSupplicantPeer *peer;
3845 group = g_hash_table_lookup(group_mapping, path);
3849 dbus_message_iter_get_basic(iter, &peer_path);
3853 for (elem = group->members; elem; elem = elem->next) {
3854 if (!g_strcmp0(elem->data, peer_path))
3862 group->members = g_slist_delete_link(group->members, elem);
3864 interface = g_hash_table_lookup(peer_mapping, peer_path);
3868 peer = g_hash_table_lookup(interface->peer_table, peer_path);
3872 callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_DISCONNECTED);
3873 peer->connection_requested = false;
3877 const char *interface;
3879 void (*function) (const char *path, DBusMessageIter *iter);
3881 { DBUS_INTERFACE_DBUS, "NameOwnerChanged", signal_name_owner_changed },
3883 { SUPPLICANT_INTERFACE, "PropertiesChanged", signal_properties_changed },
3884 { SUPPLICANT_INTERFACE, "InterfaceAdded", signal_interface_added },
3885 { SUPPLICANT_INTERFACE, "InterfaceCreated", signal_interface_added },
3886 { SUPPLICANT_INTERFACE, "InterfaceRemoved", signal_interface_removed },
3888 { SUPPLICANT_INTERFACE ".Interface", "PropertiesChanged", signal_interface_changed },
3889 { SUPPLICANT_INTERFACE ".Interface", "ScanDone", signal_scan_done },
3890 { SUPPLICANT_INTERFACE ".Interface", "BSSAdded", signal_bss_added },
3891 { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed },
3892 { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded", signal_network_added },
3893 { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved", signal_network_removed },
3895 { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed },
3897 { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
3898 { SUPPLICANT_INTERFACE ".Interface.WPS", "Event", signal_wps_event },
3899 #if defined TIZEN_EXT
3900 { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
3903 { SUPPLICANT_INTERFACE".Interface", "StaAuthorized", signal_station_connected },
3904 { SUPPLICANT_INTERFACE".Interface", "StaDeauthorized", signal_station_disconnected },
3906 { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
3907 { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost", signal_peer_lost },
3909 { SUPPLICANT_INTERFACE ".Peer", "PropertiesChanged", signal_peer_changed },
3911 { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationSuccess", signal_group_success },
3912 { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationFailure", signal_group_failure },
3913 { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupStarted", signal_group_started },
3914 { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupFinished", signal_group_finished },
3915 { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationRequest", signal_group_request },
3917 { SUPPLICANT_INTERFACE ".Group", "PeerJoined", signal_group_peer_joined },
3918 { SUPPLICANT_INTERFACE ".Group", "PeerDisconnected", signal_group_peer_disconnected },
3923 static DBusHandlerResult g_supplicant_filter(DBusConnection *conn,
3924 DBusMessage *message, void *data)
3926 DBusMessageIter iter;
3930 path = dbus_message_get_path(message);
3932 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3934 if (!dbus_message_iter_init(message, &iter))
3935 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3937 for (i = 0; signal_map[i].interface; i++) {
3938 if (!dbus_message_has_interface(message, signal_map[i].interface))
3941 if (!dbus_message_has_member(message, signal_map[i].member))
3944 signal_map[i].function(path, &iter);
3948 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3951 void g_supplicant_interface_cancel(GSupplicantInterface *interface)
3953 SUPPLICANT_DBG("Cancelling any pending DBus calls");
3954 supplicant_dbus_method_call_cancel_all(interface);
3955 supplicant_dbus_property_call_cancel_all(interface);
3958 struct supplicant_regdom {
3959 GSupplicantCountryCallback callback;
3961 const void *user_data;
3964 static void country_result(const char *error,
3965 DBusMessageIter *iter, void *user_data)
3967 struct supplicant_regdom *regdom = user_data;
3970 SUPPLICANT_DBG("Country setting result");
3976 SUPPLICANT_DBG("Country setting failure %s", error);
3980 if (regdom->callback)
3981 regdom->callback(result, regdom->alpha2,
3982 (void *) regdom->user_data);
3987 static void country_params(DBusMessageIter *iter, void *user_data)
3989 struct supplicant_regdom *regdom = user_data;
3991 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
3995 int g_supplicant_set_country(const char *alpha2,
3996 GSupplicantCountryCallback callback,
3997 const void *user_data)
3999 struct supplicant_regdom *regdom;
4002 SUPPLICANT_DBG("Country setting %s", alpha2);
4004 if (!system_available)
4007 regdom = dbus_malloc0(sizeof(*regdom));
4011 regdom->callback = callback;
4012 regdom->alpha2 = alpha2;
4013 regdom->user_data = user_data;
4015 ret = supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
4016 "Country", DBUS_TYPE_STRING_AS_STRING,
4017 country_params, country_result,
4021 SUPPLICANT_DBG("Unable to set Country configuration");
4026 int g_supplicant_interface_set_country(GSupplicantInterface *interface,
4027 GSupplicantCountryCallback callback,
4031 struct supplicant_regdom *regdom;
4034 regdom = dbus_malloc0(sizeof(*regdom));
4038 regdom->callback = callback;
4039 regdom->alpha2 = alpha2;
4040 regdom->user_data = user_data;
4042 ret = supplicant_dbus_property_set(interface->path,
4043 SUPPLICANT_INTERFACE ".Interface",
4044 "Country", DBUS_TYPE_STRING_AS_STRING,
4045 country_params, country_result,
4049 SUPPLICANT_DBG("Unable to set Country configuration");
4055 bool g_supplicant_interface_has_p2p(GSupplicantInterface *interface)
4060 return interface->p2p_support;
4063 struct supplicant_p2p_dev_config {
4068 static void p2p_device_config_result(const char *error,
4069 DBusMessageIter *iter, void *user_data)
4071 struct supplicant_p2p_dev_config *config = user_data;
4074 SUPPLICANT_DBG("Unable to set P2P Device configuration: %s",
4077 g_free(config->device_name);
4078 g_free(config->dev_type);
4082 static int dev_type_str2bin(const char *type, unsigned char dev_type[8])
4084 int length, pos, end;
4089 for (length = pos = 0; type[pos] != '\0' && length < 8; length++) {
4096 dev_type[length] = strtol(b, &e, 16);
4097 if (e && *e != '\0')
4106 static void p2p_device_config_params(DBusMessageIter *iter, void *user_data)
4108 struct supplicant_p2p_dev_config *config = user_data;
4109 DBusMessageIter dict;
4111 supplicant_dbus_dict_open(iter, &dict);
4113 supplicant_dbus_dict_append_basic(&dict, "DeviceName",
4114 DBUS_TYPE_STRING, &config->device_name);
4116 if (config->dev_type) {
4117 unsigned char dev_type[8] = {}, *type;
4120 len = dev_type_str2bin(config->dev_type, dev_type);
4123 supplicant_dbus_dict_append_fixed_array(&dict,
4124 "PrimaryDeviceType",
4125 DBUS_TYPE_BYTE, &type, len);
4129 supplicant_dbus_dict_close(iter, &dict);
4132 int g_supplicant_interface_set_p2p_device_config(GSupplicantInterface *interface,
4133 const char *device_name,
4134 const char *primary_dev_type)
4136 struct supplicant_p2p_dev_config *config;
4139 SUPPLICANT_DBG("P2P Device settings %s/%s",
4140 device_name, primary_dev_type);
4142 config = dbus_malloc0(sizeof(*config));
4146 config->device_name = g_strdup(device_name);
4147 config->dev_type = g_strdup(primary_dev_type);
4149 ret = supplicant_dbus_property_set(interface->path,
4150 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
4152 DBUS_TYPE_ARRAY_AS_STRING
4153 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
4154 DBUS_TYPE_STRING_AS_STRING
4155 DBUS_TYPE_VARIANT_AS_STRING
4156 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
4157 p2p_device_config_params,
4158 p2p_device_config_result, config, NULL);
4160 g_free(config->device_name);
4161 g_free(config->dev_type);
4163 SUPPLICANT_DBG("Unable to set P2P Device configuration");
4169 static gboolean peer_lookup_by_identifier(gpointer key, gpointer value,
4172 const GSupplicantPeer *peer = value;
4173 const char *identifier = user_data;
4175 if (!g_strcmp0(identifier, peer->identifier))
4181 GSupplicantPeer *g_supplicant_interface_peer_lookup(GSupplicantInterface *interface,
4182 const char *identifier)
4184 GSupplicantPeer *peer;
4186 peer = g_hash_table_find(interface->peer_table,
4187 peer_lookup_by_identifier,
4188 (void *) identifier);
4192 static void interface_create_data_free(struct interface_create_data *data)
4194 g_free(data->ifname);
4195 g_free(data->driver);
4196 g_free(data->bridge);
4200 static bool interface_exists(GSupplicantInterface *interface,
4203 GSupplicantInterface *tmp;
4205 tmp = g_hash_table_lookup(interface_table, path);
4206 if (tmp && tmp == interface)
4212 static void interface_create_property(const char *key, DBusMessageIter *iter,
4215 struct interface_create_data *data = user_data;
4216 GSupplicantInterface *interface = data->interface;
4219 if (data->callback) {
4220 data->callback(0, data->interface, data->user_data);
4221 #if !defined TIZEN_EXT
4222 callback_p2p_support(interface);
4226 interface_create_data_free(data);
4229 interface_property(key, iter, interface);
4232 static void interface_create_result(const char *error,
4233 DBusMessageIter *iter, void *user_data)
4235 struct interface_create_data *data = user_data;
4236 const char *path = NULL;
4242 g_warning("error %s", error);
4247 dbus_message_iter_get_basic(iter, &path);
4253 if (!system_available) {
4258 data->interface = g_hash_table_lookup(interface_table, path);
4259 if (!data->interface) {
4260 data->interface = interface_alloc(path);
4261 if (!data->interface) {
4267 err = supplicant_dbus_property_get_all(path,
4268 SUPPLICANT_INTERFACE ".Interface",
4269 interface_create_property, data,
4276 data->callback(err, NULL, data->user_data);
4278 interface_create_data_free(data);
4281 static void interface_create_params(DBusMessageIter *iter, void *user_data)
4283 struct interface_create_data *data = user_data;
4284 DBusMessageIter dict;
4285 char *config_file = NULL;
4289 supplicant_dbus_dict_open(iter, &dict);
4291 supplicant_dbus_dict_append_basic(&dict, "Ifname",
4292 DBUS_TYPE_STRING, &data->ifname);
4295 supplicant_dbus_dict_append_basic(&dict, "Driver",
4296 DBUS_TYPE_STRING, &data->driver);
4299 supplicant_dbus_dict_append_basic(&dict, "BridgeIfname",
4300 DBUS_TYPE_STRING, &data->bridge);
4302 config_file = g_hash_table_lookup(config_file_table, data->ifname);
4304 SUPPLICANT_DBG("[%s] ConfigFile %s", data->ifname, config_file);
4306 supplicant_dbus_dict_append_basic(&dict, "ConfigFile",
4307 DBUS_TYPE_STRING, &config_file);
4310 supplicant_dbus_dict_close(iter, &dict);
4313 static void interface_get_result(const char *error,
4314 DBusMessageIter *iter, void *user_data)
4316 struct interface_create_data *data = user_data;
4317 GSupplicantInterface *interface;
4318 const char *path = NULL;
4324 SUPPLICANT_DBG("Interface not created yet");
4328 dbus_message_iter_get_basic(iter, &path);
4334 interface = g_hash_table_lookup(interface_table, path);
4340 if (data->callback) {
4341 data->callback(0, interface, data->user_data);
4342 #if !defined TIZEN_EXT
4343 callback_p2p_support(interface);
4347 interface_create_data_free(data);
4352 if (!system_available) {
4357 SUPPLICANT_DBG("Creating interface");
4359 err = supplicant_dbus_method_call(SUPPLICANT_PATH,
4360 SUPPLICANT_INTERFACE,
4362 interface_create_params,
4363 interface_create_result, data,
4370 data->callback(err, NULL, data->user_data);
4372 interface_create_data_free(data);
4375 static void interface_get_params(DBusMessageIter *iter, void *user_data)
4377 struct interface_create_data *data = user_data;
4381 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
4384 int g_supplicant_interface_create(const char *ifname, const char *driver,
4386 GSupplicantInterfaceCallback callback,
4389 struct interface_create_data *data;
4392 SUPPLICANT_DBG("ifname %s", ifname);
4397 if (!system_available)
4400 data = dbus_malloc0(sizeof(*data));
4404 data->ifname = g_strdup(ifname);
4405 data->driver = g_strdup(driver);
4406 data->bridge = g_strdup(bridge);
4407 data->callback = callback;
4408 data->user_data = user_data;
4410 ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
4411 SUPPLICANT_INTERFACE,
4413 interface_get_params,
4414 interface_get_result, data,
4417 interface_create_data_free(data);
4422 static void interface_remove_result(const char *error,
4423 DBusMessageIter *iter, void *user_data)
4425 struct interface_data *data = user_data;
4430 SUPPLICANT_DBG("error: %s", error);
4434 if (!system_available) {
4440 * The gsupplicant interface is already freed by the InterfaceRemoved
4441 * signal callback. Simply invoke the interface_data callback.
4449 data->callback(err, NULL, data->user_data);
4455 static void interface_remove_params(DBusMessageIter *iter, void *user_data)
4457 struct interface_data *data = user_data;
4459 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
4460 &data->interface->path);
4464 int g_supplicant_interface_remove(GSupplicantInterface *interface,
4465 GSupplicantInterfaceCallback callback,
4468 struct interface_data *data;
4474 if (!system_available)
4477 g_supplicant_interface_cancel(interface);
4479 data = dbus_malloc0(sizeof(*data));
4483 data->interface = interface;
4484 data->path = g_strdup(interface->path);
4485 data->callback = callback;
4486 data->user_data = user_data;
4488 ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
4489 SUPPLICANT_INTERFACE,
4491 interface_remove_params,
4492 interface_remove_result, data,
4501 static void interface_scan_result(const char *error,
4502 DBusMessageIter *iter, void *user_data)
4504 struct interface_scan_data *data = user_data;
4508 SUPPLICANT_DBG("error %s", error);
4512 /* A non ready interface cannot send/receive anything */
4513 if (interface_exists(data->interface, data->path)) {
4514 if (!data->interface->ready)
4522 data->callback(err, data->interface, data->user_data);
4524 data->interface->scan_callback = data->callback;
4525 data->interface->scan_data = data->user_data;
4528 if (data->scan_params)
4529 g_supplicant_free_scan_params(data->scan_params);
4534 static void add_scan_frequency(DBusMessageIter *iter, unsigned int freq)
4536 DBusMessageIter data;
4537 unsigned int width = 0; /* Not used by wpa_supplicant atm */
4539 dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &data);
4541 dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &freq);
4542 dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &width);
4544 dbus_message_iter_close_container(iter, &data);
4547 static void add_scan_frequencies(DBusMessageIter *iter,
4550 GSupplicantScanParams *scan_data = user_data;
4554 for (i = 0; i < scan_data->num_freqs; i++) {
4555 freq = scan_data->freqs[i];
4559 add_scan_frequency(iter, freq);
4563 static void append_ssid(DBusMessageIter *iter,
4564 const void *ssid, unsigned int len)
4566 DBusMessageIter array;
4568 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
4569 DBUS_TYPE_BYTE_AS_STRING, &array);
4571 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
4573 dbus_message_iter_close_container(iter, &array);
4576 static void append_ssids(DBusMessageIter *iter, void *user_data)
4578 GSupplicantScanParams *scan_data = user_data;
4581 for (list = scan_data->ssids; list; list = list->next) {
4582 struct scan_ssid *scan_ssid = list->data;
4584 append_ssid(iter, scan_ssid->ssid, scan_ssid->ssid_len);
4588 static void supplicant_add_scan_frequency(DBusMessageIter *dict,
4589 supplicant_dbus_array_function function,
4592 GSupplicantScanParams *scan_params = user_data;
4593 DBusMessageIter entry, value, array;
4594 const char *key = "Channels";
4596 if (scan_params->freqs && scan_params->freqs[0] != 0) {
4597 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
4600 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
4602 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
4603 DBUS_TYPE_ARRAY_AS_STRING
4604 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
4605 DBUS_TYPE_UINT32_AS_STRING
4606 DBUS_TYPE_UINT32_AS_STRING
4607 DBUS_STRUCT_END_CHAR_AS_STRING,
4610 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
4611 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
4612 DBUS_TYPE_UINT32_AS_STRING
4613 DBUS_TYPE_UINT32_AS_STRING
4614 DBUS_STRUCT_END_CHAR_AS_STRING,
4618 function(&array, user_data);
4620 dbus_message_iter_close_container(&value, &array);
4621 dbus_message_iter_close_container(&entry, &value);
4622 dbus_message_iter_close_container(dict, &entry);
4626 static void interface_scan_params(DBusMessageIter *iter, void *user_data)
4628 DBusMessageIter dict;
4629 const char *type = "passive";
4630 struct interface_scan_data *data = user_data;
4632 supplicant_dbus_dict_open(iter, &dict);
4634 if (data && data->scan_params) {
4637 supplicant_dbus_dict_append_basic(&dict, "Type",
4638 DBUS_TYPE_STRING, &type);
4640 #if defined TIZEN_EXT
4641 SUPPLICANT_DBG("[specific_scan] num_ssids %d", data->scan_params->num_ssids);
4642 if (data->scan_params->num_ssids != 0)
4644 supplicant_dbus_dict_append_array(&dict, "SSIDs",
4649 supplicant_add_scan_frequency(&dict, add_scan_frequencies,
4652 supplicant_dbus_dict_append_basic(&dict, "Type",
4653 DBUS_TYPE_STRING, &type);
4655 supplicant_dbus_dict_close(iter, &dict);
4658 static int interface_ready_to_scan(GSupplicantInterface *interface)
4663 if (!system_available)
4666 if (interface->scanning)
4669 switch (interface->state) {
4670 case G_SUPPLICANT_STATE_AUTHENTICATING:
4671 case G_SUPPLICANT_STATE_ASSOCIATING:
4672 case G_SUPPLICANT_STATE_ASSOCIATED:
4673 case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
4674 case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
4676 #if defined TIZEN_EXT
4677 case G_SUPPLICANT_STATE_DISABLED:
4679 case G_SUPPLICANT_STATE_UNKNOWN:
4681 case G_SUPPLICANT_STATE_UNKNOWN:
4682 case G_SUPPLICANT_STATE_DISABLED:
4684 case G_SUPPLICANT_STATE_DISCONNECTED:
4685 case G_SUPPLICANT_STATE_INACTIVE:
4686 case G_SUPPLICANT_STATE_SCANNING:
4687 case G_SUPPLICANT_STATE_COMPLETED:
4694 int g_supplicant_interface_scan(GSupplicantInterface *interface,
4695 GSupplicantScanParams *scan_data,
4696 GSupplicantInterfaceCallback callback,
4699 struct interface_scan_data *data;
4702 ret = interface_ready_to_scan(interface);
4706 data = dbus_malloc0(sizeof(*data));
4710 data->interface = interface;
4711 data->path = g_strdup(interface->path);
4712 #if defined TIZEN_EXT
4713 data->interface->scan_callback = data->callback = callback;
4714 data->interface->scan_data = data->user_data = user_data;
4716 data->callback = callback;
4717 data->user_data = user_data;
4719 data->scan_params = scan_data;
4721 interface->scan_callback = callback;
4722 interface->scan_data = user_data;
4724 ret = supplicant_dbus_method_call(interface->path,
4725 SUPPLICANT_INTERFACE ".Interface", "Scan",
4726 interface_scan_params, interface_scan_result, data,
4737 static int parse_supplicant_error(DBusMessageIter *iter)
4739 int err = -ECONNABORTED;
4745 /* If the given passphrase is malformed wpa_s returns
4746 * "invalid message format" but this error should be interpreted as
4749 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
4750 dbus_message_iter_get_basic(iter, &key);
4751 if (strncmp(key, "psk", 3) == 0 ||
4752 strncmp(key, "wep_key", 7) == 0 ||
4753 strcmp(key, "invalid message format") == 0) {
4757 dbus_message_iter_next(iter);
4763 static void interface_select_network_result(const char *error,
4764 DBusMessageIter *iter, void *user_data)
4766 struct interface_connect_data *data = user_data;
4773 #if defined TIZEN_EXT
4774 SUPPLICANT_DBG("SelectNetwork errorFreq %s", error);
4776 SUPPLICANT_DBG("SelectNetwork error %s", error);
4778 err = parse_supplicant_error(iter);
4784 data->callback(err, data->interface, data->user_data);
4790 static void interface_select_network_params(DBusMessageIter *iter,
4793 struct interface_connect_data *data = user_data;
4794 GSupplicantInterface *interface = data->interface;
4795 #if defined TIZEN_EXT
4796 GSupplicantSSID *ssid = data->ssid;
4799 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
4800 &interface->network_path);
4801 #if defined TIZEN_EXT
4802 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
4806 static void interface_add_network_result(const char *error,
4807 DBusMessageIter *iter, void *user_data)
4809 struct interface_connect_data *data = user_data;
4810 GSupplicantInterface *interface = data->interface;
4817 dbus_message_iter_get_basic(iter, &path);
4821 SUPPLICANT_DBG("PATH: %s", path);
4823 interface->network_path = g_strdup(path);
4825 store_network_information(interface, data->ssid);
4827 #if defined TIZEN_EXT
4828 SUPPLICANT_DBG(".Interface.SelectNetworkFreq");
4831 #if defined TIZEN_EXT
4832 supplicant_dbus_method_call(data->interface->path,
4833 SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq",
4834 interface_select_network_params,
4835 interface_select_network_result, data,
4838 supplicant_dbus_method_call(data->interface->path,
4839 SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
4840 interface_select_network_params,
4841 interface_select_network_result, data,
4848 SUPPLICANT_DBG("AddNetwork error %s", error);
4850 if (interface_exists(data->interface, data->interface->path)) {
4851 err = parse_supplicant_error(iter);
4853 data->callback(err, data->interface, data->user_data);
4855 g_free(interface->network_path);
4856 interface->network_path = NULL;
4864 static void add_network_security_none(DBusMessageIter *dict)
4866 const char *auth_alg = "OPEN";
4868 supplicant_dbus_dict_append_basic(dict, "auth_alg",
4869 DBUS_TYPE_STRING, &auth_alg);
4872 static void add_network_security_wep(DBusMessageIter *dict,
4873 GSupplicantSSID *ssid)
4875 const char *auth_alg = "OPEN SHARED";
4876 dbus_uint32_t key_index = 0;
4878 supplicant_dbus_dict_append_basic(dict, "auth_alg",
4879 DBUS_TYPE_STRING, &auth_alg);
4881 if (ssid->passphrase) {
4882 int size = strlen(ssid->passphrase);
4883 if (size == 10 || size == 26) {
4884 unsigned char *key = g_try_malloc(13);
4888 memset(tmp, 0, sizeof(tmp));
4892 for (i = 0; i < size / 2; i++) {
4893 memcpy(tmp, ssid->passphrase + (i * 2), 2);
4894 key[i] = (unsigned char) strtol(tmp, NULL, 16);
4897 supplicant_dbus_dict_append_fixed_array(dict,
4902 } else if (size == 5 || size == 13) {
4903 unsigned char *key = g_try_malloc(13);
4909 for (i = 0; i < size; i++)
4910 key[i] = (unsigned char) ssid->passphrase[i];
4912 supplicant_dbus_dict_append_fixed_array(dict,
4918 supplicant_dbus_dict_append_basic(dict,
4923 supplicant_dbus_dict_append_basic(dict, "wep_tx_keyidx",
4924 DBUS_TYPE_UINT32, &key_index);
4928 static dbus_bool_t is_psk_raw_key(const char *psk)
4932 /* A raw key is always 64 bytes length... */
4933 if (strlen(psk) != 64)
4936 /* ... and its content is in hex representation */
4937 for (i = 0; i < 64; i++)
4938 if (!isxdigit((unsigned char) psk[i]))
4944 static unsigned char hexchar2bin(char c)
4946 if ((c >= '0') && (c <= '9'))
4948 else if ((c >= 'A') && (c <= 'F'))
4949 return c - 'A' + 10;
4950 else if ((c >= 'a') && (c <= 'f'))
4951 return c - 'a' + 10;
4956 static void hexstring2bin(const char *string, unsigned char *data,
4961 for (i = 0; i < data_len; i++)
4962 data[i] = (hexchar2bin(string[i * 2 + 0]) << 4 |
4963 hexchar2bin(string[i * 2 + 1]) << 0);
4966 static void add_network_security_psk(DBusMessageIter *dict,
4967 GSupplicantSSID *ssid)
4969 if (ssid->passphrase && strlen(ssid->passphrase) > 0) {
4970 const char *key = "psk";
4972 if (is_psk_raw_key(ssid->passphrase)) {
4973 unsigned char data[32];
4974 unsigned char *datap = data;
4976 /* The above pointer alias is required by D-Bus because
4977 * with D-Bus and GCC, non-heap-allocated arrays cannot
4978 * be passed directly by their base pointer. */
4980 hexstring2bin(ssid->passphrase, datap, sizeof(data));
4982 supplicant_dbus_dict_append_fixed_array(dict,
4983 key, DBUS_TYPE_BYTE,
4984 &datap, sizeof(data));
4986 supplicant_dbus_dict_append_basic(dict,
4987 key, DBUS_TYPE_STRING,
4992 static void add_network_security_tls(DBusMessageIter *dict,
4993 GSupplicantSSID *ssid)
4996 * For TLS, we at least need:
4997 * The client certificate
4998 * The client private key file
4999 * The client private key file password
5001 * The Authority certificate is optional.
5003 if (!ssid->client_cert_path)
5006 if (!ssid->private_key_path)
5009 #if !defined TIZEN_EXT
5010 if (!ssid->private_key_passphrase)
5014 if (ssid->ca_cert_path)
5015 supplicant_dbus_dict_append_basic(dict, "ca_cert",
5016 DBUS_TYPE_STRING, &ssid->ca_cert_path);
5018 supplicant_dbus_dict_append_basic(dict, "private_key",
5020 &ssid->private_key_path);
5021 #if !defined TIZEN_EXT
5022 supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
5024 &ssid->private_key_passphrase);
5026 supplicant_dbus_dict_append_basic(dict, "client_cert",
5028 &ssid->client_cert_path);
5031 static void add_network_security_peap(DBusMessageIter *dict,
5032 GSupplicantSSID *ssid)
5037 * For PEAP/TTLS, we at least need
5038 * The authority certificate
5039 * The 2nd phase authentication method
5040 * The 2nd phase passphrase
5042 * The Client certificate is optional although strongly recommended
5043 * When setting it, we need in addition
5044 * The Client private key file
5045 * The Client private key file password
5047 if (!ssid->passphrase)
5050 if (!ssid->phase2_auth)
5053 if (ssid->client_cert_path) {
5054 if (!ssid->private_key_path)
5057 #if !defined TIZEN_EXT
5058 if (!ssid->private_key_passphrase)
5062 supplicant_dbus_dict_append_basic(dict, "client_cert",
5064 &ssid->client_cert_path);
5066 supplicant_dbus_dict_append_basic(dict, "private_key",
5068 &ssid->private_key_path);
5070 #if !defined TIZEN_EXT
5071 supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
5073 &ssid->private_key_passphrase);
5078 if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) {
5079 phase2_auth = g_strdup_printf("autheap=%s",
5080 ssid->phase2_auth + strlen("EAP-"));
5082 phase2_auth = g_strdup_printf("auth=%s", ssid->phase2_auth);
5084 supplicant_dbus_dict_append_basic(dict, "password",
5088 if (ssid->ca_cert_path)
5089 supplicant_dbus_dict_append_basic(dict, "ca_cert",
5091 &ssid->ca_cert_path);
5093 supplicant_dbus_dict_append_basic(dict, "phase2",
5097 g_free(phase2_auth);
5100 #if defined TIZEN_EXT
5101 static void add_network_security_aka_sim(DBusMessageIter *dict,
5102 GSupplicantSSID *ssid)
5104 if (!ssid->passphrase)
5107 supplicant_dbus_dict_append_basic(dict, "password",
5113 static void add_network_security_eap(DBusMessageIter *dict,
5114 GSupplicantSSID *ssid)
5118 #if defined TIZEN_EXT
5121 if (!ssid->eap || !ssid->identity)
5125 if (g_strcmp0(ssid->eap, "tls") == 0) {
5126 add_network_security_tls(dict, ssid);
5127 } else if (g_strcmp0(ssid->eap, "peap") == 0 ||
5128 g_strcmp0(ssid->eap, "ttls") == 0) {
5129 #if defined TIZEN_EXT
5130 if (!ssid->identity)
5133 add_network_security_peap(dict, ssid);
5135 #if defined TIZEN_EXT
5136 } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
5137 g_strcmp0(ssid->eap, "aka") == 0) {
5138 add_network_security_aka_sim(dict, ssid);
5143 eap_value = g_ascii_strup(ssid->eap, -1);
5145 supplicant_dbus_dict_append_basic(dict, "eap",
5148 #if defined TIZEN_EXT
5149 if (ssid->identity != NULL)
5150 supplicant_dbus_dict_append_basic(dict, "identity",
5154 supplicant_dbus_dict_append_basic(dict, "identity",
5158 if(ssid->anonymous_identity)
5159 supplicant_dbus_dict_append_basic(dict, "anonymous_identity",
5161 &ssid->anonymous_identity);
5163 if(ssid->subject_match)
5164 supplicant_dbus_dict_append_basic(dict, "subject_match",
5166 &ssid->subject_match);
5168 if(ssid->altsubject_match)
5169 supplicant_dbus_dict_append_basic(dict, "altsubject_match",
5171 &ssid->altsubject_match);
5173 if(ssid->domain_suffix_match)
5174 supplicant_dbus_dict_append_basic(dict, "domain_suffix_match",
5176 &ssid->domain_suffix_match);
5178 if(ssid->domain_match)
5179 supplicant_dbus_dict_append_basic(dict, "domain_match",
5181 &ssid->domain_match);
5186 static void add_network_security_ciphers(DBusMessageIter *dict,
5187 GSupplicantSSID *ssid)
5189 unsigned int p_cipher, g_cipher, i;
5190 char *pairwise, *group;
5191 char *pair_ciphers[4];
5192 char *group_ciphers[5];
5194 p_cipher = ssid->pairwise_cipher;
5195 g_cipher = ssid->group_cipher;
5197 if (p_cipher == 0 && g_cipher == 0)
5202 if (p_cipher & G_SUPPLICANT_PAIRWISE_CCMP)
5203 pair_ciphers[i++] = "CCMP";
5205 if (p_cipher & G_SUPPLICANT_PAIRWISE_TKIP)
5206 pair_ciphers[i++] = "TKIP";
5208 if (p_cipher & G_SUPPLICANT_PAIRWISE_NONE)
5209 pair_ciphers[i++] = "NONE";
5211 pair_ciphers[i] = NULL;
5215 if (g_cipher & G_SUPPLICANT_GROUP_CCMP)
5216 group_ciphers[i++] = "CCMP";
5218 if (g_cipher & G_SUPPLICANT_GROUP_TKIP)
5219 group_ciphers[i++] = "TKIP";
5221 if (g_cipher & G_SUPPLICANT_GROUP_WEP104)
5222 group_ciphers[i++] = "WEP104";
5224 if (g_cipher & G_SUPPLICANT_GROUP_WEP40)
5225 group_ciphers[i++] = "WEP40";
5227 group_ciphers[i] = NULL;
5229 pairwise = g_strjoinv(" ", pair_ciphers);
5230 group = g_strjoinv(" ", group_ciphers);
5232 SUPPLICANT_DBG("cipher %s %s", pairwise, group);
5234 supplicant_dbus_dict_append_basic(dict, "pairwise",
5237 supplicant_dbus_dict_append_basic(dict, "group",
5245 static void add_network_security_proto(DBusMessageIter *dict,
5246 GSupplicantSSID *ssid)
5248 unsigned int protocol, i;
5252 protocol = ssid->protocol;
5259 if (protocol & G_SUPPLICANT_PROTO_RSN)
5260 protos[i++] = "RSN";
5262 if (protocol & G_SUPPLICANT_PROTO_WPA)
5263 protos[i++] = "WPA";
5267 proto = g_strjoinv(" ", protos);
5269 SUPPLICANT_DBG("proto %s", proto);
5271 supplicant_dbus_dict_append_basic(dict, "proto",
5278 static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
5282 switch (ssid->security) {
5283 case G_SUPPLICANT_SECURITY_NONE:
5285 add_network_security_none(dict);
5286 add_network_security_ciphers(dict, ssid);
5288 case G_SUPPLICANT_SECURITY_UNKNOWN:
5289 case G_SUPPLICANT_SECURITY_WEP:
5291 add_network_security_wep(dict, ssid);
5292 add_network_security_ciphers(dict, ssid);
5294 case G_SUPPLICANT_SECURITY_PSK:
5295 key_mgmt = "WPA-PSK";
5296 add_network_security_psk(dict, ssid);
5297 add_network_security_ciphers(dict, ssid);
5298 add_network_security_proto(dict, ssid);
5300 case G_SUPPLICANT_SECURITY_IEEE8021X:
5301 key_mgmt = "WPA-EAP";
5302 add_network_security_eap(dict, ssid);
5303 add_network_security_ciphers(dict, ssid);
5304 add_network_security_proto(dict, ssid);
5306 #if defined TIZEN_EXT
5307 case G_SUPPLICANT_SECURITY_FT_PSK:
5308 key_mgmt = "FT-PSK";
5309 add_network_security_psk(dict, ssid);
5310 add_network_security_ciphers(dict, ssid);
5311 add_network_security_proto(dict, ssid);
5313 case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
5314 key_mgmt = "FT-EAP";
5315 add_network_security_eap(dict, ssid);
5316 add_network_security_ciphers(dict, ssid);
5317 add_network_security_proto(dict, ssid);
5322 supplicant_dbus_dict_append_basic(dict, "key_mgmt",
5323 DBUS_TYPE_STRING, &key_mgmt);
5326 static void add_network_mode(DBusMessageIter *dict, GSupplicantSSID *ssid)
5330 switch (ssid->mode) {
5331 case G_SUPPLICANT_MODE_UNKNOWN:
5332 case G_SUPPLICANT_MODE_INFRA:
5335 case G_SUPPLICANT_MODE_IBSS:
5338 case G_SUPPLICANT_MODE_MASTER:
5343 supplicant_dbus_dict_append_basic(dict, "mode",
5344 DBUS_TYPE_UINT32, &mode);
5347 static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
5349 DBusMessageIter dict;
5350 struct interface_connect_data *data = user_data;
5351 GSupplicantSSID *ssid = data->ssid;
5353 supplicant_dbus_dict_open(iter, &dict);
5355 if (ssid->scan_ssid)
5356 supplicant_dbus_dict_append_basic(&dict, "scan_ssid",
5357 DBUS_TYPE_UINT32, &ssid->scan_ssid);
5360 supplicant_dbus_dict_append_basic(&dict, "frequency",
5361 DBUS_TYPE_UINT32, &ssid->freq);
5364 supplicant_dbus_dict_append_basic(&dict, "bgscan",
5365 DBUS_TYPE_STRING, &ssid->bgscan);
5367 add_network_mode(&dict, ssid);
5369 add_network_security(&dict, ssid);
5371 supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
5372 DBUS_TYPE_BYTE, &ssid->ssid,
5375 supplicant_dbus_dict_append_basic(&dict, "ignore_broadcast_ssid",
5377 &ssid->ignore_broadcast_ssid);
5379 #if defined TIZEN_EXT
5382 bssid = g_try_malloc0(18);
5383 if (bssid == NULL) {
5384 SUPPLICANT_DBG("memory allocation error");
5385 supplicant_dbus_dict_close(iter, &dict);
5388 snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
5389 ssid->bssid[0], ssid->bssid[1], ssid->bssid[2],
5390 ssid->bssid[3], ssid->bssid[4], ssid->bssid[5]);
5391 supplicant_dbus_dict_append_basic(&dict, "bssid",
5392 DBUS_TYPE_STRING, &bssid);
5397 supplicant_dbus_dict_close(iter, &dict);
5400 static void interface_wps_start_result(const char *error,
5401 DBusMessageIter *iter, void *user_data)
5403 struct interface_connect_data *data = user_data;
5410 SUPPLICANT_DBG("error: %s", error);
5411 err = parse_supplicant_error(iter);
5415 data->callback(err, data->interface, data->user_data);
5422 static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
5424 struct interface_connect_data *data = user_data;
5425 GSupplicantSSID *ssid = data->ssid;
5426 const char *role = "enrollee", *type;
5427 DBusMessageIter dict;
5431 supplicant_dbus_dict_open(iter, &dict);
5433 supplicant_dbus_dict_append_basic(&dict, "Role",
5434 DBUS_TYPE_STRING, &role);
5437 if (ssid->pin_wps) {
5439 supplicant_dbus_dict_append_basic(&dict, "Pin",
5440 DBUS_TYPE_STRING, &ssid->pin_wps);
5443 supplicant_dbus_dict_append_basic(&dict, "Type",
5444 DBUS_TYPE_STRING, &type);
5446 #if defined TIZEN_EXT
5448 supplicant_dbus_dict_append_fixed_array(&dict, "Bssid",
5449 DBUS_TYPE_BYTE, &ssid->bssid, 6);
5452 supplicant_dbus_dict_close(iter, &dict);
5455 static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
5457 struct interface_connect_data *data = user_data;
5462 SUPPLICANT_DBG("error: %s", error);
5468 #if defined TIZEN_EXT
5469 GSupplicantSSID *ssid = data->ssid;
5470 if (ssid->pin_wps != NULL) {
5471 if (!g_utf8_validate(ssid->pin_wps, 8, NULL)) {
5472 SUPPLICANT_DBG("Invalid characters in WPS_PIN");
5479 supplicant_dbus_method_call(data->interface->path,
5480 SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
5481 interface_add_wps_params,
5482 interface_wps_start_result, data, NULL);
5485 static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
5487 dbus_bool_t credentials = TRUE;
5491 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
5495 #if defined TIZEN_EXT
5496 #define NETCONFIG_SERVICE "net.netconfig"
5497 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
5498 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
5500 struct dec_method_call_data {
5501 struct interface_connect_data *data;
5502 DBusPendingCall *pending_call;
5505 static struct dec_method_call_data decrypt_request_data;
5507 static void crypt_method_call_cancel(void)
5509 if (decrypt_request_data.pending_call) {
5510 dbus_pending_call_cancel(decrypt_request_data.pending_call);
5511 dbus_pending_call_unref(decrypt_request_data.pending_call);
5512 decrypt_request_data.pending_call = NULL;
5515 g_free(decrypt_request_data.data->path);
5516 g_free(decrypt_request_data.data->ssid);
5517 dbus_free(decrypt_request_data.data);
5518 decrypt_request_data.data = NULL;
5521 static void decryption_request_reply(DBusPendingCall *call,
5526 DBusMessageIter args;
5529 static gchar* origin_value = NULL;
5530 struct interface_connect_data *data = user_data;
5532 g_free(origin_value);
5533 origin_value = NULL;
5537 reply = dbus_pending_call_steal_reply(call);
5539 dbus_error_init(&error);
5540 if (dbus_set_error_from_message(&error, reply)) {
5541 SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message);
5542 dbus_error_free(&error);
5546 if (dbus_message_iter_init(reply, &args) == FALSE) {
5547 SUPPLICANT_DBG("dbus_message_iter_init() failed");
5551 dbus_message_iter_get_basic(&args, &out_data);
5553 origin_value = g_strdup((const gchar *)out_data);
5554 data->ssid->passphrase = origin_value;
5556 ret = supplicant_dbus_method_call(data->interface->path,
5557 SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
5558 interface_add_network_params,
5559 interface_add_network_result, data,
5563 SUPPLICANT_DBG("AddNetwork failed %d", ret);
5564 callback_assoc_failed(decrypt_request_data.data->user_data);
5571 dbus_message_unref(reply);
5572 dbus_pending_call_unref(call);
5574 decrypt_request_data.pending_call = NULL;
5575 decrypt_request_data.data = NULL;
5578 static int send_decryption_request(const char *passphrase,
5579 struct interface_connect_data *data)
5581 DBusMessage *msg = NULL;
5582 DBusPendingCall *call;
5584 SUPPLICANT_DBG("Decryption request");
5587 SUPPLICANT_DBG("Invalid parameter");
5594 msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
5595 NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase");
5599 dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
5602 if (!dbus_connection_send_with_reply(connection, msg,
5603 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
5604 dbus_message_unref(msg);
5609 dbus_message_unref(msg);
5613 decrypt_request_data.pending_call = call;
5614 decrypt_request_data.data = data;
5616 dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL);
5617 dbus_message_unref(msg);
5619 SUPPLICANT_DBG("Decryption request succeeded");
5625 int g_supplicant_interface_connect(GSupplicantInterface *interface,
5626 GSupplicantSSID *ssid,
5627 GSupplicantInterfaceCallback callback,
5630 struct interface_connect_data *data;
5631 struct interface_data *intf_data;
5639 if (!system_available)
5642 /* TODO: Check if we're already connected and switch */
5644 data = dbus_malloc0(sizeof(*data));
5648 data->interface = interface;
5649 data->path = g_strdup(interface->path);
5650 data->callback = callback;
5652 data->user_data = user_data;
5654 if (ssid->use_wps) {
5655 g_free(interface->wps_cred.key);
5656 memset(&interface->wps_cred, 0,
5657 sizeof(struct _GSupplicantWpsCredentials));
5659 ret = supplicant_dbus_property_set(interface->path,
5660 SUPPLICANT_INTERFACE ".Interface.WPS",
5661 "ProcessCredentials", DBUS_TYPE_BOOLEAN_AS_STRING,
5662 wps_process_credentials, wps_start, data, interface);
5664 /* By the time there is a request for connect and the network
5665 * path is not NULL it means that connman has not removed the
5666 * previous network pointer. This can happen in the case AP
5667 * deauthenticated client and connman does not remove the
5668 * previously connected network pointer. This causes supplicant
5669 * to reallocate the memory for struct wpa_ssid again even if it
5670 * is the same SSID. This causes memory usage of wpa_supplicnat
5671 * to go high. The idea here is that if the previously connected
5672 * network is not removed at the time of next connection attempt
5673 * check if the network path is not NULL. In case it is non-NULL
5674 * first remove the network and then once removal is successful, add
5678 if (interface->network_path != NULL) {
5683 * If this add network is for the same network for
5684 * which wpa_supplicant already has a profile then do
5685 * not need to add another profile. Only if the
5686 * profile that needs to get added is different from
5687 * what is there in wpa_s delete the current one. A
5688 * network is identified by its SSID, security_type
5689 * and passphrase (private passphrase in case security
5692 if (compare_network_parameters(interface, ssid)) {
5696 intf_data = dbus_malloc0(sizeof(*intf_data));
5700 intf_data->interface = interface;
5701 intf_data->path = g_strdup(interface->path);
5702 intf_data->callback = callback;
5703 intf_data->ssid = ssid;
5704 intf_data->user_data = user_data;
5705 intf_data->network_remove_in_progress = TRUE;
5706 network_remove(intf_data);
5708 #if defined TIZEN_EXT
5709 if (ssid->passphrase && g_strcmp0(ssid->passphrase, "") != 0) {
5710 ret = send_decryption_request(ssid->passphrase, data);
5712 SUPPLICANT_DBG("Decryption request failed %d", ret);
5715 ret = supplicant_dbus_method_call(interface->path,
5716 SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
5717 interface_add_network_params,
5718 interface_add_network_result, data,
5728 return -EINPROGRESS;
5731 static void network_remove_result(const char *error,
5732 DBusMessageIter *iter, void *user_data)
5734 struct interface_data *data = user_data;
5735 struct interface_connect_data *connect_data;
5742 SUPPLICANT_DBG("error: %s", error);
5744 if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
5746 result = -ECONNABORTED;
5749 g_free(data->interface->network_path);
5750 data->interface->network_path = NULL;
5752 remove_network_information(data->interface);
5754 if (data->network_remove_in_progress == TRUE) {
5755 data->network_remove_in_progress = FALSE;
5756 connect_data = dbus_malloc0(sizeof(*connect_data));
5760 connect_data->interface = data->interface;
5761 connect_data->path = g_strdup(data->path);
5762 connect_data->callback = data->callback;
5763 connect_data->ssid = data->ssid;
5764 connect_data->user_data = data->user_data;
5766 supplicant_dbus_method_call(data->interface->path,
5767 SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
5768 interface_add_network_params,
5769 interface_add_network_result, connect_data,
5770 connect_data->interface);
5773 data->callback(result, data->interface, data->user_data);
5779 static void network_remove_params(DBusMessageIter *iter, void *user_data)
5781 struct interface_data *data = user_data;
5782 const char *path = data->interface->network_path;
5784 SUPPLICANT_DBG("path %s", path);
5786 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
5789 static int network_remove(struct interface_data *data)
5791 GSupplicantInterface *interface = data->interface;
5795 #if defined TIZEN_EXT
5796 GSupplicantInterface *intf = NULL;
5798 * Check if 'interface' is valid
5800 intf = g_hash_table_lookup(interface_table, interface->path);
5805 return supplicant_dbus_method_call(interface->path,
5806 SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork",
5807 network_remove_params, network_remove_result, data,
5811 static void interface_disconnect_result(const char *error,
5812 DBusMessageIter *iter, void *user_data)
5814 struct interface_data *data = user_data;
5821 SUPPLICANT_DBG("error: %s", error);
5823 if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
5825 result = -ECONNABORTED;
5828 /* If we are disconnecting from previous WPS successful
5829 * association. i.e.: it did not went through AddNetwork,
5830 * and interface->network_path was never set. */
5831 if (!data->interface->network_path) {
5833 data->callback(result, data->interface,
5841 if (result < 0 && data->callback) {
5842 data->callback(result, data->interface, data->user_data);
5843 data->callback = NULL;
5846 if (result != -ECONNABORTED) {
5847 if (network_remove(data) < 0) {
5857 int g_supplicant_interface_disconnect(GSupplicantInterface *interface,
5858 GSupplicantInterfaceCallback callback,
5861 struct interface_data *data;
5869 if (!system_available)
5871 #if defined TIZEN_EXT
5872 if (decrypt_request_data.pending_call &&
5873 decrypt_request_data.data &&
5874 decrypt_request_data.data->user_data == user_data) {
5876 callback_assoc_failed(decrypt_request_data.data->user_data);
5877 crypt_method_call_cancel();
5882 data = dbus_malloc0(sizeof(*data));
5886 data->interface = interface;
5887 data->path = g_strdup(interface->path);
5888 data->callback = callback;
5889 data->user_data = user_data;
5891 ret = supplicant_dbus_method_call(interface->path,
5892 SUPPLICANT_INTERFACE ".Interface", "Disconnect",
5893 NULL, interface_disconnect_result, data,
5904 static void interface_p2p_find_result(const char *error,
5905 DBusMessageIter *iter, void *user_data)
5907 struct interface_scan_data *data = user_data;
5910 SUPPLICANT_DBG("error %s", error);
5915 if (interface_exists(data->interface, data->path)) {
5916 if (!data->interface->ready)
5919 data->interface->p2p_finding = true;
5923 data->callback(err, data->interface, data->user_data);
5929 static void interface_p2p_find_params(DBusMessageIter *iter, void *user_data)
5931 DBusMessageIter dict;
5933 supplicant_dbus_dict_open(iter, &dict);
5934 supplicant_dbus_dict_close(iter, &dict);
5937 int g_supplicant_interface_p2p_find(GSupplicantInterface *interface,
5938 GSupplicantInterfaceCallback callback,
5941 struct interface_scan_data *data;
5944 if (!interface->p2p_support)
5947 ret = interface_ready_to_scan(interface);
5948 if (ret && ret != -EALREADY)
5951 data = dbus_malloc0(sizeof(*data));
5955 data->interface = interface;
5956 data->path = g_strdup(interface->path);
5957 data->callback = callback;
5958 data->user_data = user_data;
5960 ret = supplicant_dbus_method_call(interface->path,
5961 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Find",
5962 interface_p2p_find_params, interface_p2p_find_result,
5972 bool g_supplicant_interface_is_p2p_finding(GSupplicantInterface *interface)
5977 return interface->p2p_finding;
5980 int g_supplicant_interface_p2p_stop_find(GSupplicantInterface *interface)
5982 if (!interface->p2p_finding)
5987 interface->p2p_finding = false;
5989 return supplicant_dbus_method_call(interface->path,
5990 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "StopFind",
5991 NULL, NULL, NULL, NULL);
5994 static void interface_p2p_connect_result(const char *error,
5995 DBusMessageIter *iter, void *user_data)
5997 struct interface_connect_data *data = user_data;
6003 SUPPLICANT_DBG("error: %s", error);
6004 err = parse_supplicant_error(iter);
6008 data->callback(err, data->interface, data->user_data);
6011 g_free(data->peer->wps_pin);
6012 g_free(data->peer->path);
6017 static void interface_p2p_connect_params(DBusMessageIter *iter, void *user_data)
6019 struct interface_connect_data *data = user_data;
6020 const char *wps = "pbc";
6021 DBusMessageIter dict;
6026 supplicant_dbus_dict_open(iter, &dict);
6028 if (data->peer->master)
6031 if (data->peer->wps_pin)
6034 supplicant_dbus_dict_append_basic(&dict, "peer",
6035 DBUS_TYPE_OBJECT_PATH, &data->peer->path);
6036 supplicant_dbus_dict_append_basic(&dict, "wps_method",
6037 DBUS_TYPE_STRING, &wps);
6038 if (data->peer->wps_pin) {
6039 supplicant_dbus_dict_append_basic(&dict, "pin",
6040 DBUS_TYPE_STRING, &data->peer->wps_pin);
6043 supplicant_dbus_dict_append_basic(&dict, "go_intent",
6044 DBUS_TYPE_INT32, &go_intent);
6046 supplicant_dbus_dict_close(iter, &dict);
6049 int g_supplicant_interface_p2p_connect(GSupplicantInterface *interface,
6050 GSupplicantPeerParams *peer_params,
6051 GSupplicantInterfaceCallback callback,
6054 struct interface_connect_data *data;
6059 if (!interface->p2p_support)
6062 data = dbus_malloc0(sizeof(*data));
6066 data->interface = interface;
6067 data->path = g_strdup(interface->path);
6068 data->peer = peer_params;
6069 data->callback = callback;
6070 data->user_data = user_data;
6072 ret = supplicant_dbus_method_call(interface->path,
6073 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Connect",
6074 interface_p2p_connect_params, interface_p2p_connect_result,
6082 return -EINPROGRESS;
6085 int g_supplicant_interface_p2p_disconnect(GSupplicantInterface *interface,
6086 GSupplicantPeerParams *peer_params)
6088 GSupplicantPeer *peer;
6094 if (!interface->p2p_support)
6097 peer = g_hash_table_lookup(interface->peer_table, peer_params->path);
6101 for (list = peer->groups; list; list = list->next, count++) {
6102 const char *group_obj_path = list->data;
6103 GSupplicantInterface *g_interface;
6104 GSupplicantGroup *group;
6106 group = g_hash_table_lookup(group_mapping, group_obj_path);
6107 if (!group || !group->interface)
6110 g_interface = group->interface;
6111 supplicant_dbus_method_call(g_interface->path,
6112 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
6113 "Disconnect", NULL, NULL, NULL, g_interface);
6116 if (count == 0 && peer->current_group_iface) {
6117 supplicant_dbus_method_call(peer->current_group_iface->path,
6118 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
6119 "Disconnect", NULL, NULL, NULL,
6120 peer->current_group_iface->path);
6123 peer->current_group_iface = NULL;
6125 return -EINPROGRESS;
6128 struct p2p_service_data {
6130 GSupplicantInterface *interface;
6131 GSupplicantP2PServiceParams *service;
6132 GSupplicantInterfaceCallback callback;
6136 static void interface_p2p_service_result(const char *error,
6137 DBusMessageIter *iter, void *user_data)
6139 struct p2p_service_data *data = user_data;
6142 SUPPLICANT_DBG("%s result - %s", data->registration ?
6143 "Registration" : "Deletion",
6144 error ? error : "Success");
6149 data->callback(result, data->interface, data->user_data);
6151 g_free(data->service->query);
6152 g_free(data->service->response);
6153 g_free(data->service->service);
6154 g_free(data->service->wfd_ies);
6155 g_free(data->service);
6159 static void interface_p2p_service_params(DBusMessageIter *iter,
6162 struct p2p_service_data *data = user_data;
6163 GSupplicantP2PServiceParams *service;
6164 DBusMessageIter dict;
6169 service = data->service;
6171 supplicant_dbus_dict_open(iter, &dict);
6173 if (service->query && service->response) {
6175 supplicant_dbus_dict_append_basic(&dict, "service_type",
6176 DBUS_TYPE_STRING, &type);
6177 supplicant_dbus_dict_append_fixed_array(&dict, "query",
6178 DBUS_TYPE_BYTE, &service->query,
6179 service->query_length);
6180 supplicant_dbus_dict_append_fixed_array(&dict, "response",
6181 DBUS_TYPE_BYTE, &service->response,
6182 service->response_length);
6183 } else if (service->version && service->service) {
6185 supplicant_dbus_dict_append_basic(&dict, "service_type",
6186 DBUS_TYPE_STRING, &type);
6187 supplicant_dbus_dict_append_basic(&dict, "version",
6188 DBUS_TYPE_INT32, &service->version);
6189 supplicant_dbus_dict_append_basic(&dict, "service",
6190 DBUS_TYPE_STRING, &service->service);
6193 supplicant_dbus_dict_close(iter, &dict);
6196 int g_supplicant_interface_p2p_add_service(GSupplicantInterface *interface,
6197 GSupplicantInterfaceCallback callback,
6198 GSupplicantP2PServiceParams *p2p_service_params,
6201 struct p2p_service_data *data;
6206 if (!interface->p2p_support)
6209 data = dbus_malloc0(sizeof(*data));
6213 data->registration = true;
6214 data->interface = interface;
6215 data->service = p2p_service_params;
6216 data->callback = callback;
6217 data->user_data = user_data;
6219 ret = supplicant_dbus_method_call(interface->path,
6220 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "AddService",
6221 interface_p2p_service_params, interface_p2p_service_result,
6228 return -EINPROGRESS;
6231 int g_supplicant_interface_p2p_del_service(GSupplicantInterface *interface,
6232 GSupplicantP2PServiceParams *p2p_service_params)
6234 struct p2p_service_data *data;
6239 if (!interface->p2p_support)
6242 data = dbus_malloc0(sizeof(*data));
6246 data->interface = interface;
6247 data->service = p2p_service_params;
6249 ret = supplicant_dbus_method_call(interface->path,
6250 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeleteService",
6251 interface_p2p_service_params, interface_p2p_service_result,
6258 return -EINPROGRESS;
6261 struct p2p_listen_data {
6266 static void interface_p2p_listen_params(DBusMessageIter *iter, void *user_data)
6268 struct p2p_listen_data *params = user_data;
6269 DBusMessageIter dict;
6271 supplicant_dbus_dict_open(iter, &dict);
6273 supplicant_dbus_dict_append_basic(&dict, "period",
6274 DBUS_TYPE_INT32, ¶ms->period);
6275 supplicant_dbus_dict_append_basic(&dict, "interval",
6276 DBUS_TYPE_INT32, ¶ms->interval);
6277 supplicant_dbus_dict_close(iter, &dict);
6280 int g_supplicant_interface_p2p_listen(GSupplicantInterface *interface,
6281 int period, int interval)
6283 struct p2p_listen_data params;
6287 if (!interface->p2p_support)
6290 params.period = period;
6291 params.interval = interval;
6293 return supplicant_dbus_method_call(interface->path,
6294 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
6295 "ExtendedListen", interface_p2p_listen_params,
6296 NULL, ¶ms, NULL);
6299 static void widi_ies_params(DBusMessageIter *iter, void *user_data)
6301 struct p2p_service_data *data = user_data;
6302 GSupplicantP2PServiceParams *service = data->service;
6303 DBusMessageIter array;
6305 SUPPLICANT_DBG("%p - %d", service->wfd_ies, service->wfd_ies_length);
6307 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
6308 DBUS_TYPE_BYTE_AS_STRING, &array);
6310 if (service->wfd_ies && service->wfd_ies_length > 0) {
6311 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
6312 &service->wfd_ies, service->wfd_ies_length);
6315 dbus_message_iter_close_container(iter, &array);
6318 int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params,
6319 GSupplicantInterfaceCallback callback,
6322 struct p2p_service_data *data;
6327 if (!system_available)
6330 data = dbus_malloc0(sizeof(*data));
6334 data->service = p2p_service_params;
6335 data->callback = callback;
6336 data->user_data = user_data;
6338 if (p2p_service_params->wfd_ies)
6339 data->registration = true;
6341 ret = supplicant_dbus_property_set(SUPPLICANT_PATH,
6342 SUPPLICANT_INTERFACE, "WFDIEs",
6343 DBUS_TYPE_ARRAY_AS_STRING
6344 DBUS_TYPE_BYTE_AS_STRING,
6346 interface_p2p_service_result,
6348 if (ret < 0 && ret != -EINPROGRESS) {
6353 return -EINPROGRESS;
6356 #if defined TIZEN_EXT
6357 int g_supplicant_interface_remove_network(GSupplicantInterface *interface)
6359 struct interface_data *data;
6363 if (interface == NULL)
6366 if (system_available == FALSE)
6369 data = dbus_malloc0(sizeof(*data));
6373 data->interface = interface;
6375 return network_remove(data);
6379 static const char *g_supplicant_rule0 = "type=signal,"
6380 "path=" DBUS_PATH_DBUS ","
6381 "sender=" DBUS_SERVICE_DBUS ","
6382 "interface=" DBUS_INTERFACE_DBUS ","
6383 "member=NameOwnerChanged,"
6384 "arg0=" SUPPLICANT_SERVICE;
6385 static const char *g_supplicant_rule1 = "type=signal,"
6386 "interface=" SUPPLICANT_INTERFACE;
6387 static const char *g_supplicant_rule2 = "type=signal,"
6388 "interface=" SUPPLICANT_INTERFACE ".Interface";
6389 static const char *g_supplicant_rule3 = "type=signal,"
6390 "interface=" SUPPLICANT_INTERFACE ".Interface.WPS";
6391 static const char *g_supplicant_rule4 = "type=signal,"
6392 "interface=" SUPPLICANT_INTERFACE ".BSS";
6393 static const char *g_supplicant_rule5 = "type=signal,"
6394 "interface=" SUPPLICANT_INTERFACE ".Network";
6395 #if !defined TIZEN_EXT
6396 static const char *g_supplicant_rule6 = "type=signal,"
6397 "interface=" SUPPLICANT_INTERFACE ".Interface.P2PDevice";
6398 static const char *g_supplicant_rule7 = "type=signal,"
6399 "interface=" SUPPLICANT_INTERFACE ".Peer";
6400 static const char *g_supplicant_rule8 = "type=signal,"
6401 "interface=" SUPPLICANT_INTERFACE ".Group";
6404 static void invoke_introspect_method(void)
6406 DBusMessage *message;
6408 message = dbus_message_new_method_call(SUPPLICANT_SERVICE,
6410 DBUS_INTERFACE_INTROSPECTABLE,
6416 dbus_message_set_no_reply(message, TRUE);
6417 dbus_connection_send(connection, message, NULL);
6418 dbus_message_unref(message);
6421 int g_supplicant_register(const GSupplicantCallbacks *callbacks)
6423 connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
6427 if (!dbus_connection_add_filter(connection, g_supplicant_filter,
6429 dbus_connection_unref(connection);
6434 callbacks_pointer = callbacks;
6437 interface_table = g_hash_table_new_full(g_str_hash, g_str_equal,
6438 NULL, remove_interface);
6440 bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
6442 peer_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
6444 group_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
6446 pending_peer_connection = g_hash_table_new_full(g_str_hash, g_str_equal,
6448 config_file_table = g_hash_table_new_full(g_str_hash, g_str_equal,
6451 supplicant_dbus_setup(connection);
6453 dbus_bus_add_match(connection, g_supplicant_rule0, NULL);
6454 dbus_bus_add_match(connection, g_supplicant_rule1, NULL);
6455 dbus_bus_add_match(connection, g_supplicant_rule2, NULL);
6456 dbus_bus_add_match(connection, g_supplicant_rule3, NULL);
6457 dbus_bus_add_match(connection, g_supplicant_rule4, NULL);
6458 dbus_bus_add_match(connection, g_supplicant_rule5, NULL);
6459 #if defined TIZEN_EXT
6460 dbus_bus_add_match(connection,
6461 "type=signal,interface=org.tizen.system.deviced.PowerOff,"
6462 "member=ChangeState", NULL);
6464 #if !defined TIZEN_EXT
6465 dbus_bus_add_match(connection, g_supplicant_rule6, NULL);
6466 dbus_bus_add_match(connection, g_supplicant_rule7, NULL);
6467 dbus_bus_add_match(connection, g_supplicant_rule8, NULL);
6469 dbus_connection_flush(connection);
6471 if (dbus_bus_name_has_owner(connection,
6472 SUPPLICANT_SERVICE, NULL)) {
6473 system_available = TRUE;
6474 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
6475 SUPPLICANT_INTERFACE,
6476 service_property, NULL, NULL);
6478 invoke_introspect_method();
6483 static void unregister_interface_remove_params(DBusMessageIter *iter,
6486 const char *path = user_data;
6488 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
6493 static void unregister_remove_interface(gpointer key, gpointer value,
6496 GSupplicantInterface *interface = value;
6498 supplicant_dbus_method_call(SUPPLICANT_PATH,
6499 SUPPLICANT_INTERFACE,
6501 unregister_interface_remove_params,
6502 NULL, interface->path, NULL);
6505 void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
6510 #if !defined TIZEN_EXT
6511 dbus_bus_remove_match(connection, g_supplicant_rule8, NULL);
6512 dbus_bus_remove_match(connection, g_supplicant_rule7, NULL);
6513 dbus_bus_remove_match(connection, g_supplicant_rule6, NULL);
6515 dbus_bus_remove_match(connection, g_supplicant_rule5, NULL);
6516 dbus_bus_remove_match(connection, g_supplicant_rule4, NULL);
6517 dbus_bus_remove_match(connection, g_supplicant_rule3, NULL);
6518 dbus_bus_remove_match(connection, g_supplicant_rule2, NULL);
6519 dbus_bus_remove_match(connection, g_supplicant_rule1, NULL);
6520 dbus_bus_remove_match(connection, g_supplicant_rule0, NULL);
6521 dbus_connection_flush(connection);
6523 dbus_connection_remove_filter(connection,
6524 g_supplicant_filter, NULL);
6527 if (config_file_table) {
6528 g_hash_table_destroy(config_file_table);
6529 config_file_table = NULL;
6533 g_hash_table_destroy(bss_mapping);
6538 g_hash_table_destroy(peer_mapping);
6539 peer_mapping = NULL;
6542 if (group_mapping) {
6543 g_hash_table_destroy(group_mapping);
6544 group_mapping = NULL;
6547 if (interface_table) {
6548 g_hash_table_foreach(interface_table,
6549 unregister_remove_interface, NULL);
6550 g_hash_table_destroy(interface_table);
6551 interface_table = NULL;
6554 if (system_available)
6555 callback_system_killed();
6558 dbus_connection_unref(connection);
6562 callbacks_pointer = NULL;