fce4f7b3a27922cf5a8dc7fb8d7da63cc6c2447a
[platform/upstream/connman.git] / gsupplicant / supplicant.c
1 /*
2  *
3  *  WPA supplicant library with GLib integration
4  *
5  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdint.h>
31 #include <syslog.h>
32 #include <ctype.h>
33 #include <stdbool.h>
34 #include <netinet/if_ether.h>
35 #include <netinet/in.h>
36
37 #include <glib.h>
38 #include <gdbus.h>
39
40 #include "dbus.h"
41 #include "gsupplicant.h"
42
43 #if defined TIZEN_EXT
44 #include "setting.h"
45 #endif
46
47 #define IEEE80211_CAP_ESS       0x0001
48 #define IEEE80211_CAP_IBSS      0x0002
49 #define IEEE80211_CAP_PRIVACY   0x0010
50
51 #if defined TIZEN_EXT
52 #define WLAN_EID_HT_CAP 45
53 #define WLAN_EID_VHT_CAP 191
54 #define WLAN_EID_SUPP_RATES 1
55 #define WLAN_EID_EXT_SUPP_RATES 50
56 #define COUNTRY_CODE_LENGTH     2
57 #endif
58
59 #if defined TIZEN_EXT
60 #define LAST_CONNECTED_TIMEOUT       (5 * 60)
61 #define ASSOC_REJECT_TIMEOUT         10
62 #define FREQ_RANGE_24GHZ_CHANNEL_1   2412
63 #define FREQ_RANGE_24GHZ_CHANNEL_14  2484
64 #define FREQ_RANGE_5GHZ_CHANNEL_32   5160
65 #define FREQ_RANGE_5GHZ_CHANNEL_165  5825
66
67 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
68 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
69 #endif
70
71 #define BSS_UNKNOWN_STRENGTH    -90
72
73 static DBusConnection *connection;
74
75 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
76 static GSupplicantCallbacks *callbacks_pointer;
77 #else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
78 static const GSupplicantCallbacks *callbacks_pointer;
79 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
80
81 static dbus_bool_t system_available = FALSE;
82 static dbus_bool_t system_ready = FALSE;
83
84 static dbus_int32_t debug_level;
85 static dbus_bool_t debug_timestamp = FALSE;
86 static dbus_bool_t debug_showkeys = FALSE;
87
88 static const char *debug_strings[] = {
89         "msgdump", "debug", "info", "warning", "error", NULL
90 };
91
92 static unsigned int eap_methods;
93
94 struct strvalmap {
95         const char *str;
96         unsigned int val;
97 };
98
99 static struct strvalmap eap_method_map[] = {
100         { "MD5",        G_SUPPLICANT_EAP_METHOD_MD5     },
101         { "TLS",        G_SUPPLICANT_EAP_METHOD_TLS     },
102         { "MSCHAPV2",   G_SUPPLICANT_EAP_METHOD_MSCHAPV2        },
103         { "PEAP",       G_SUPPLICANT_EAP_METHOD_PEAP    },
104         { "TTLS",       G_SUPPLICANT_EAP_METHOD_TTLS    },
105         { "GTC",        G_SUPPLICANT_EAP_METHOD_GTC     },
106         { "OTP",        G_SUPPLICANT_EAP_METHOD_OTP     },
107         { "LEAP",       G_SUPPLICANT_EAP_METHOD_LEAP    },
108         { "WSC",        G_SUPPLICANT_EAP_METHOD_WSC     },
109         { }
110 };
111
112 static struct strvalmap keymgmt_map[] = {
113         { "none",               G_SUPPLICANT_KEYMGMT_NONE               },
114         { "ieee8021x",          G_SUPPLICANT_KEYMGMT_IEEE8021X  },
115         { "wpa-none",           G_SUPPLICANT_KEYMGMT_WPA_NONE   },
116         { "wpa-psk",            G_SUPPLICANT_KEYMGMT_WPA_PSK    },
117         { "wpa-psk-sha256",     G_SUPPLICANT_KEYMGMT_WPA_PSK_256        },
118         { "wpa-ft-psk",         G_SUPPLICANT_KEYMGMT_WPA_FT_PSK },
119         { "wpa-ft-eap",         G_SUPPLICANT_KEYMGMT_WPA_FT_EAP },
120         { "wpa-eap",            G_SUPPLICANT_KEYMGMT_WPA_EAP    },
121         { "wpa-eap-sha256",     G_SUPPLICANT_KEYMGMT_WPA_EAP_256        },
122         { "wps",                G_SUPPLICANT_KEYMGMT_WPS                },
123 #if defined TIZEN_EXT
124         { "sae",                G_SUPPLICANT_KEYMGMT_SAE                },
125         { "ft-sae",             G_SUPPLICANT_KEYMGMT_FT_SAE             },
126         { "owe",                G_SUPPLICANT_KEYMGMT_OWE                },
127         { "dpp",                G_SUPPLICANT_KEYMGMT_DPP                },
128 #endif
129         { }
130 };
131
132 static struct strvalmap authalg_capa_map[] = {
133         { "open",       G_SUPPLICANT_CAPABILITY_AUTHALG_OPEN    },
134         { "shared",     G_SUPPLICANT_CAPABILITY_AUTHALG_SHARED  },
135         { "leap",       G_SUPPLICANT_CAPABILITY_AUTHALG_LEAP    },
136         { }
137 };
138
139 static struct strvalmap proto_capa_map[] = {
140         { "wpa",        G_SUPPLICANT_CAPABILITY_PROTO_WPA               },
141         { "rsn",        G_SUPPLICANT_CAPABILITY_PROTO_RSN               },
142         { }
143 };
144
145 static struct strvalmap group_map[] = {
146         { "wep40",      G_SUPPLICANT_GROUP_WEP40        },
147         { "wep104",     G_SUPPLICANT_GROUP_WEP104       },
148         { "tkip",       G_SUPPLICANT_GROUP_TKIP },
149         { "ccmp",       G_SUPPLICANT_GROUP_CCMP },
150         { }
151 };
152
153 static struct strvalmap pairwise_map[] = {
154         { "none",       G_SUPPLICANT_PAIRWISE_NONE      },
155         { "tkip",       G_SUPPLICANT_PAIRWISE_TKIP      },
156         { "ccmp",       G_SUPPLICANT_PAIRWISE_CCMP      },
157         { }
158 };
159
160 static struct strvalmap scan_capa_map[] = {
161         { "active",     G_SUPPLICANT_CAPABILITY_SCAN_ACTIVE     },
162         { "passive",    G_SUPPLICANT_CAPABILITY_SCAN_PASSIVE    },
163         { "ssid",       G_SUPPLICANT_CAPABILITY_SCAN_SSID               },
164         { }
165 };
166
167 static struct strvalmap mode_capa_map[] = {
168         { "infrastructure",     G_SUPPLICANT_CAPABILITY_MODE_INFRA      },
169         { "ad-hoc",             G_SUPPLICANT_CAPABILITY_MODE_IBSS       },
170         { "ap",                 G_SUPPLICANT_CAPABILITY_MODE_AP         },
171         { "p2p",                G_SUPPLICANT_CAPABILITY_MODE_P2P        },
172 #if defined TIZEN_EXT_WIFI_MESH
173         { "mesh",               G_SUPPLICANT_CAPABILITY_MODE_MESH       },
174 #endif
175         { }
176 };
177
178 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
179 struct _GSupplicantINSSettings {
180         GSupplicantINSPreferredFreq preferred_freq_bssid;
181         unsigned int preferred_freq_bssid_score;
182         bool last_connected_bssid;
183         unsigned int last_connected_bssid_score;
184         bool assoc_reject;
185         unsigned int assoc_reject_score;
186         bool signal_bssid;
187         int signal_level3_5ghz;
188         int signal_level3_24ghz;
189 };
190
191 static struct _GSupplicantINSSettings ins_settings;
192 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
193
194 #if defined TIZEN_EXT_INS
195 static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
196         0x00, 0x00, 0x00, 0x00, 0x00, 0x00
197 };
198 #endif
199
200 static GHashTable *interface_table;
201 static GHashTable *bss_mapping;
202 static GHashTable *peer_mapping;
203 static GHashTable *group_mapping;
204 static GHashTable *pending_peer_connection;
205 static GHashTable *config_file_table;
206
207 struct _GSupplicantWpsCredentials {
208         unsigned char ssid[32];
209         unsigned int ssid_len;
210         char *key;
211 };
212
213 struct added_network_information {
214         char * ssid;
215         GSupplicantSecurity security;
216         char * passphrase;
217         char * private_passphrase;
218 #if defined TIZEN_EXT
219         char *connector;
220         char *c_sign_key;
221         char *net_access_key;
222 #endif
223 };
224
225 #if defined TIZEN_EXT_WIFI_MESH
226 struct _GSupplicantMeshGroupInfo {
227         unsigned char ssid[32];
228         unsigned int ssid_len;
229         int disconnect_reason;
230 };
231 #endif
232
233 struct _GSupplicantInterface {
234         char *path;
235         char *network_path;
236         unsigned int keymgmt_capa;
237         unsigned int authalg_capa;
238         unsigned int proto_capa;
239         unsigned int group_capa;
240         unsigned int pairwise_capa;
241         unsigned int scan_capa;
242         unsigned int mode_capa;
243         unsigned int max_scan_ssids;
244         bool p2p_support;
245         bool p2p_finding;
246         bool ap_create_in_progress;
247         dbus_bool_t ready;
248         GSupplicantState state;
249         dbus_bool_t scanning;
250         GSupplicantInterfaceCallback scan_callback;
251         void *scan_data;
252         int apscan;
253         char *ifname;
254         char *driver;
255         char *bridge;
256         struct _GSupplicantWpsCredentials wps_cred;
257         GSupplicantWpsState wps_state;
258         GHashTable *network_table;
259         GHashTable *peer_table;
260         GHashTable *group_table;
261         GHashTable *bss_mapping;
262         void *data;
263         const char *pending_peer_path;
264         GSupplicantNetwork *current_network;
265         struct added_network_information network_info;
266 #if defined TIZEN_EXT
267         dbus_bool_t is_5_0_Ghz_supported;
268         int disconnect_reason;
269 #endif
270 #if defined TIZEN_EXT
271         unsigned char add_network_bssid[WIFI_BSSID_LEN_MAX];
272         unsigned char connected_bssid[WIFI_BSSID_LEN_MAX];
273 #endif
274 #if defined TIZEN_EXT_WIFI_MESH
275         bool mesh_support;
276         struct _GSupplicantMeshGroupInfo group_info;
277 #endif
278 };
279
280 struct g_supplicant_bss {
281         GSupplicantInterface *interface;
282         char *path;
283         unsigned char bssid[6];
284         unsigned char ssid[32];
285         unsigned int ssid_len;
286         dbus_uint16_t frequency;
287         dbus_uint32_t maxrate;
288         dbus_int16_t signal;
289         GSupplicantMode mode;
290         GSupplicantSecurity security;
291         dbus_bool_t rsn_selected;
292         unsigned int wpa_keymgmt;
293         unsigned int wpa_pairwise;
294         unsigned int wpa_group;
295         unsigned int rsn_keymgmt;
296         unsigned int rsn_pairwise;
297         unsigned int rsn_group;
298         unsigned int keymgmt;
299         dbus_bool_t privacy;
300         dbus_bool_t psk;
301         dbus_bool_t ieee8021x;
302 #if defined TIZEN_EXT
303         dbus_bool_t ft_psk;
304         dbus_bool_t ft_ieee8021x;
305         GSList *vsie_list;
306         dbus_bool_t hs20;
307         unsigned char country_code[COUNTRY_CODE_LENGTH];
308         GSupplicantPhy_mode phy_mode;
309         dbus_int16_t snr;
310         dbus_uint32_t est_throughput;
311         dbus_bool_t psk_sha256;
312 #endif
313         unsigned int wps_capabilities;
314 #if defined TIZEN_EXT
315         dbus_bool_t sae;
316         dbus_bool_t owe;
317         dbus_bool_t dpp;
318         dbus_bool_t owe_transition_mode;
319         unsigned int transition_mode_ssid_len;
320         unsigned char transition_mode_bssid[6];
321         unsigned char transition_mode_ssid[32];
322         dbus_bool_t pmf_required;
323 #endif
324 };
325
326 struct _GSupplicantNetwork {
327         GSupplicantInterface *interface;
328         char *path;
329         char *group;
330         char *name;
331         unsigned char ssid[32];
332         unsigned int ssid_len;
333         dbus_int16_t signal;
334         dbus_uint16_t frequency;
335         struct g_supplicant_bss *best_bss;
336         GSupplicantMode mode;
337         GSupplicantSecurity security;
338         dbus_bool_t wps;
339         unsigned int wps_capabilities;
340         GHashTable *bss_table;
341         GHashTable *config_table;
342 #if defined TIZEN_EXT
343         bool isHS20AP;
344         char *eap;
345         char *identity;
346         char *phase2;
347         unsigned int keymgmt;
348         GSList *vsie_list;
349         unsigned char country_code[COUNTRY_CODE_LENGTH];
350         GSupplicantPhy_mode phy_mode;
351         dbus_bool_t owe_transition_mode;
352         dbus_bool_t privacy;
353         unsigned int transition_mode_ssid_len;
354         unsigned char transition_mode_bssid[6];
355         unsigned char transition_mode_ssid[32];
356         unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
357         GHashTable *assoc_reject_table;
358 #endif
359 };
360
361 struct _GSupplicantPeer {
362         GSupplicantInterface *interface;
363         char *path;
364         unsigned char device_address[ETH_ALEN];
365         unsigned char iface_address[ETH_ALEN];
366         char *name;
367         unsigned char *widi_ies;
368         int widi_ies_length;
369         char *identifier;
370         unsigned int wps_capabilities;
371         GSList *groups;
372         const GSupplicantInterface *current_group_iface;
373         bool connection_requested;
374 };
375
376 struct _GSupplicantGroup {
377         GSupplicantInterface *interface;
378         GSupplicantInterface *orig_interface;
379         char *path;
380         int role;
381         GSList *members;
382 };
383
384 struct interface_data {
385         GSupplicantInterface *interface;
386         char *path; /* Interface path cannot be taken from interface (above) as
387                      * it might have been freed already.
388                      */
389         GSupplicantInterfaceCallback callback;
390         void *user_data;
391         bool network_remove_in_progress;
392         GSupplicantSSID *ssid;
393 };
394
395 #if defined TIZEN_EXT
396 struct interface_signalpoll_data {
397         GSupplicantInterface *interface;
398         char *path;
399         GSupplicantMaxSpeedCallback callback;
400         void *user_data;
401 };
402 #endif
403
404 struct interface_create_data {
405         char *ifname;
406         char *driver;
407         char *bridge;
408 #if defined TIZEN_EXT
409         unsigned int mac_addr;
410         unsigned int preassoc_mac_addr;
411         unsigned int random_mac_lifetime;
412 #endif /* TIZEN_EXT */
413 #if defined TIZEN_EXT_WIFI_MESH
414         char *parent_ifname;
415         bool is_mesh_interface;
416 #endif
417         GSupplicantInterface *interface;
418         GSupplicantInterfaceCallback callback;
419         void *user_data;
420 };
421
422 struct interface_connect_data {
423         GSupplicantInterface *interface;
424         char *path;
425         GSupplicantInterfaceCallback callback;
426         void *user_data;
427         union {
428                 GSupplicantSSID *ssid;
429                 GSupplicantPeerParams *peer;
430         };
431 };
432
433 struct interface_scan_data {
434         GSupplicantInterface *interface;
435         char *path;
436         GSupplicantInterfaceCallback callback;
437         GSupplicantScanParams *scan_params;
438         void *user_data;
439 };
440
441 #if defined TIZEN_EXT
442 struct update_bssid_data {
443         GSupplicantNetwork *network;
444         unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
445         GHashTable *assoc_reject_table;
446         GSList *bssid_list;
447 };
448
449 struct assoc_reject_data {
450         char *bssid;
451         GSList *reject_time_list;
452 };
453
454 struct assoc_count_data {
455         time_t ref_time;
456         int assoc_count;
457 };
458
459 #if defined TIZEN_EXT_INS
460 static unsigned int last_connected_bss_timeout = 0;
461 #endif
462 static bool simplified_log = true;
463 #endif
464
465 static int network_remove(struct interface_data *data);
466
467 #if defined TIZEN_EXT_WIFI_MESH
468 struct _GSupplicantMeshPeer {
469         GSupplicantInterface *interface;
470         char *peer_address;
471         int disconnect_reason;
472 };
473 #endif
474
475 static inline void debug(const char *format, ...)
476 {
477         char str[256];
478         va_list ap;
479
480         if (!callbacks_pointer || !callbacks_pointer->debug)
481                 return;
482
483         va_start(ap, format);
484
485         if (vsnprintf(str, sizeof(str), format, ap) > 0)
486                 callbacks_pointer->debug(str);
487
488         va_end(ap);
489 }
490
491 #define SUPPLICANT_DBG(fmt, arg...) \
492         debug("%s:%s() " fmt, __FILE__, __FUNCTION__ , ## arg);
493
494 static GSupplicantMode string2mode(const char *mode)
495 {
496         if (!mode)
497                 return G_SUPPLICANT_MODE_UNKNOWN;
498
499         if (g_str_equal(mode, "infrastructure"))
500                 return G_SUPPLICANT_MODE_INFRA;
501         else if (g_str_equal(mode, "ad-hoc"))
502                 return G_SUPPLICANT_MODE_IBSS;
503 #if defined TIZEN_EXT_WIFI_MESH
504         else if (g_str_equal(mode, "mesh"))
505                 return G_SUPPLICANT_MODE_MESH;
506 #endif
507
508         return G_SUPPLICANT_MODE_UNKNOWN;
509 }
510
511 static const char *mode2string(GSupplicantMode mode)
512 {
513         switch (mode) {
514         case G_SUPPLICANT_MODE_UNKNOWN:
515                 break;
516         case G_SUPPLICANT_MODE_INFRA:
517                 return "managed";
518         case G_SUPPLICANT_MODE_IBSS:
519                 return "adhoc";
520         case G_SUPPLICANT_MODE_MASTER:
521                 return "ap";
522 #if defined TIZEN_EXT_WIFI_MESH
523         case G_SUPPLICANT_MODE_MESH:
524                 return "mesh";
525 #endif
526         }
527
528         return NULL;
529 }
530
531 static const char *security2string(GSupplicantSecurity security)
532 {
533         switch (security) {
534         case G_SUPPLICANT_SECURITY_UNKNOWN:
535                 break;
536         case G_SUPPLICANT_SECURITY_NONE:
537                 return "none";
538         case G_SUPPLICANT_SECURITY_WEP:
539                 return "wep";
540         case G_SUPPLICANT_SECURITY_PSK:
541                 return "psk";
542         case G_SUPPLICANT_SECURITY_IEEE8021X:
543                 return "ieee8021x";
544 #if defined TIZEN_EXT
545         case G_SUPPLICANT_SECURITY_PSK_SHA256:
546                 return "psk_sha256";
547         case G_SUPPLICANT_SECURITY_FT_PSK:
548                 return "ft_psk";
549         case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
550                 return "ft_ieee8021x";
551         case G_SUPPLICANT_SECURITY_SAE:
552                 return "sae";
553         case G_SUPPLICANT_SECURITY_OWE:
554                 return "owe";
555         case G_SUPPLICANT_SECURITY_DPP:
556                 return "dpp";
557 #endif
558         }
559
560         return NULL;
561 }
562
563 static GSupplicantState string2state(const char *state)
564 {
565         if (!state)
566                 return G_SUPPLICANT_STATE_UNKNOWN;
567
568         if (g_str_equal(state, "unknown"))
569                 return G_SUPPLICANT_STATE_UNKNOWN;
570         else if (g_str_equal(state, "interface_disabled"))
571                 return G_SUPPLICANT_STATE_DISABLED;
572         else if (g_str_equal(state, "disconnected"))
573                 return G_SUPPLICANT_STATE_DISCONNECTED;
574         else if (g_str_equal(state, "inactive"))
575                 return G_SUPPLICANT_STATE_INACTIVE;
576         else if (g_str_equal(state, "scanning"))
577                 return G_SUPPLICANT_STATE_SCANNING;
578         else if (g_str_equal(state, "authenticating"))
579                 return G_SUPPLICANT_STATE_AUTHENTICATING;
580         else if (g_str_equal(state, "associating"))
581                 return G_SUPPLICANT_STATE_ASSOCIATING;
582         else if (g_str_equal(state, "associated"))
583                 return G_SUPPLICANT_STATE_ASSOCIATED;
584         else if (g_str_equal(state, "group_handshake"))
585                 return G_SUPPLICANT_STATE_GROUP_HANDSHAKE;
586         else if (g_str_equal(state, "4way_handshake"))
587                 return G_SUPPLICANT_STATE_4WAY_HANDSHAKE;
588         else if (g_str_equal(state, "completed"))
589                 return G_SUPPLICANT_STATE_COMPLETED;
590
591         return G_SUPPLICANT_STATE_UNKNOWN;
592 }
593
594 static bool compare_network_parameters(GSupplicantInterface *interface,
595                                 GSupplicantSSID *ssid)
596 {
597 #if defined TIZEN_EXT
598         if (!interface->network_info.ssid)
599                 return FALSE;
600 #endif
601
602         if (memcmp(interface->network_info.ssid, ssid->ssid, ssid->ssid_len))
603                 return FALSE;
604
605         if (interface->network_info.security != ssid->security)
606                 return FALSE;
607
608         if (interface->network_info.passphrase &&
609                         g_strcmp0(interface->network_info.passphrase,
610                                 ssid->passphrase) != 0) {
611                 return FALSE;
612         }
613
614         if (interface->network_info.private_passphrase &&
615                         g_strcmp0(interface->network_info.private_passphrase,
616                                 ssid->private_key_passphrase) != 0) {
617                 return FALSE;
618         }
619
620 #if defined TIZEN_EXT
621         if (interface->network_info.connector &&
622                         g_strcmp0(interface->network_info.connector,
623                                 ssid->connector) != 0) {
624                 return FALSE;
625         }
626         if (interface->network_info.c_sign_key &&
627                         g_strcmp0(interface->network_info.c_sign_key,
628                                 ssid->c_sign_key) != 0) {
629                 return FALSE;
630         }
631         if (interface->network_info.net_access_key &&
632                         g_strcmp0(interface->network_info.net_access_key,
633                                 ssid->net_access_key) != 0) {
634                 return FALSE;
635         }
636 #endif
637         return TRUE;
638 }
639
640 static void remove_network_information(GSupplicantInterface * interface)
641 {
642         g_free(interface->network_info.ssid);
643         g_free(interface->network_info.passphrase);
644         g_free(interface->network_info.private_passphrase);
645 #if defined TIZEN_EXT
646         g_free(interface->network_info.connector);
647         g_free(interface->network_info.c_sign_key);
648         g_free(interface->network_info.net_access_key);
649 #endif
650         interface->network_info.ssid = NULL;
651         interface->network_info.passphrase = NULL;
652         interface->network_info.private_passphrase = NULL;
653 #if defined TIZEN_EXT
654         interface->network_info.connector = NULL;
655         interface->network_info.c_sign_key = NULL;
656         interface->network_info.net_access_key = NULL;
657 #endif
658 }
659
660 static int store_network_information(GSupplicantInterface * interface,
661                                 GSupplicantSSID *ssid)
662 {
663         interface->network_info.ssid = g_malloc(ssid->ssid_len + 1);
664         if (interface->network_info.ssid != NULL) {
665                 memcpy(interface->network_info.ssid, ssid->ssid,
666                         ssid->ssid_len);
667                 interface->network_info.ssid[ssid->ssid_len] = '\0';
668         } else {
669                 return -ENOMEM;
670         }
671
672         interface->network_info.security = ssid->security;
673
674         if ((ssid->security == G_SUPPLICANT_SECURITY_WEP ||
675                 ssid->security == G_SUPPLICANT_SECURITY_PSK ||
676 #if defined TIZEN_EXT
677                 ssid->security == G_SUPPLICANT_SECURITY_SAE ||
678                 ssid->security == G_SUPPLICANT_SECURITY_PSK_SHA256 ||
679 #endif
680                 ssid->security == G_SUPPLICANT_SECURITY_NONE) &&
681                 ssid->passphrase) {
682                 interface->network_info.passphrase = g_strdup(ssid->passphrase);
683         }
684
685         if (ssid->security == G_SUPPLICANT_SECURITY_IEEE8021X &&
686                         ssid->private_key_passphrase) {
687                 interface->network_info.private_passphrase =
688                         g_strdup(ssid->private_key_passphrase);
689         }
690
691         return 0;
692 }
693
694 static void callback_system_ready(void)
695 {
696         if (system_ready)
697                 return;
698
699         system_ready = TRUE;
700
701         if (!callbacks_pointer)
702                 return;
703
704         if (!callbacks_pointer->system_ready)
705                 return;
706
707         callbacks_pointer->system_ready();
708 }
709
710 static void callback_system_killed(void)
711 {
712         system_ready = FALSE;
713
714         if (!callbacks_pointer)
715                 return;
716
717         if (!callbacks_pointer->system_killed)
718                 return;
719
720         callbacks_pointer->system_killed();
721 }
722
723 static void callback_interface_added(GSupplicantInterface *interface)
724 {
725         SUPPLICANT_DBG("");
726
727         if (!callbacks_pointer)
728                 return;
729
730         if (!callbacks_pointer->interface_added)
731                 return;
732
733         callbacks_pointer->interface_added(interface);
734 }
735
736 static void callback_interface_state(GSupplicantInterface *interface)
737 {
738         if (!callbacks_pointer)
739                 return;
740
741         if (!callbacks_pointer->interface_state)
742                 return;
743
744         callbacks_pointer->interface_state(interface);
745 }
746
747 static void callback_interface_removed(GSupplicantInterface *interface)
748 {
749         if (!callbacks_pointer)
750                 return;
751
752         if (!callbacks_pointer->interface_removed)
753                 return;
754
755         callbacks_pointer->interface_removed(interface);
756 }
757
758 #if !defined TIZEN_EXT
759 static void callback_p2p_support(GSupplicantInterface *interface)
760 {
761         SUPPLICANT_DBG("");
762
763         if (!interface->p2p_support)
764                 return;
765
766         if (callbacks_pointer && callbacks_pointer->p2p_support)
767                 callbacks_pointer->p2p_support(interface);
768 }
769 #endif
770
771 #if defined TIZEN_EXT_WIFI_MESH
772 static void callback_mesh_support(GSupplicantInterface *interface)
773 {
774         SUPPLICANT_DBG("");
775
776         if (!interface->mesh_support)
777                 return;
778
779         if (callbacks_pointer && callbacks_pointer->mesh_support)
780                 callbacks_pointer->mesh_support(interface);
781 }
782
783 bool g_supplicant_interface_has_mesh(GSupplicantInterface *interface)
784 {
785         if (!interface)
786                 return false;
787
788         return interface->mesh_support;
789 }
790 #endif
791
792 static void callback_scan_started(GSupplicantInterface *interface)
793 {
794         if (!callbacks_pointer)
795                 return;
796
797         if (!callbacks_pointer->scan_started)
798                 return;
799
800         callbacks_pointer->scan_started(interface);
801 }
802
803 static void callback_ap_create_fail(GSupplicantInterface *interface)
804 {
805         if (!callbacks_pointer)
806                 return;
807
808         if (!callbacks_pointer->ap_create_fail)
809                 return;
810
811         callbacks_pointer->ap_create_fail(interface);
812 }
813
814 static void callback_scan_finished(GSupplicantInterface *interface)
815 {
816         if (!callbacks_pointer)
817                 return;
818
819         if (!callbacks_pointer->scan_finished)
820                 return;
821
822         callbacks_pointer->scan_finished(interface);
823 }
824
825 static void callback_network_added(GSupplicantNetwork *network)
826 {
827         if (!callbacks_pointer)
828                 return;
829
830         if (!callbacks_pointer->network_added)
831                 return;
832
833         callbacks_pointer->network_added(network);
834 }
835
836 static void callback_network_removed(GSupplicantNetwork *network)
837 {
838         if (!callbacks_pointer)
839                 return;
840
841         if (!callbacks_pointer->network_removed)
842                 return;
843
844         callbacks_pointer->network_removed(network);
845 }
846
847 #if defined TIZEN_EXT
848 static void callback_network_merged(GSupplicantNetwork *network)
849 {
850         if (!callbacks_pointer)
851                 return;
852
853         if (!callbacks_pointer->network_merged)
854                 return;
855
856         callbacks_pointer->network_merged(network);
857 }
858
859 static void callback_assoc_failed(void *user_data)
860 {
861         if (!callbacks_pointer)
862                 return;
863
864         if (!callbacks_pointer->assoc_failed)
865                 return;
866
867         callbacks_pointer->assoc_failed(user_data);
868 }
869
870 static void callback_scan_done(GSupplicantInterface *interface)
871 {
872         if (!callbacks_pointer)
873                 return;
874
875         if (!callbacks_pointer->scan_done)
876                 return;
877
878         callbacks_pointer->scan_done(interface);
879 }
880 #endif
881
882 static void callback_network_changed(GSupplicantNetwork *network,
883                                         const char *property)
884 {
885         if (!callbacks_pointer)
886                 return;
887
888         if (!callbacks_pointer->network_changed)
889                 return;
890
891         callbacks_pointer->network_changed(network, property);
892 }
893
894 static void callback_network_associated(GSupplicantNetwork *network)
895 {
896         if (!callbacks_pointer)
897                 return;
898
899         if (!callbacks_pointer->network_associated)
900                 return;
901
902         callbacks_pointer->network_associated(network);
903 }
904
905 static void callback_sta_authorized(GSupplicantInterface *interface,
906                                         const char *addr)
907 {
908         if (!callbacks_pointer)
909                 return;
910
911         if (!callbacks_pointer->sta_authorized)
912                 return;
913
914         callbacks_pointer->sta_authorized(interface, addr);
915 }
916
917 static void callback_sta_deauthorized(GSupplicantInterface *interface,
918                                         const char *addr)
919 {
920         if (!callbacks_pointer)
921                 return;
922
923         if (!callbacks_pointer->sta_deauthorized)
924                 return;
925
926         callbacks_pointer->sta_deauthorized(interface, addr);
927 }
928
929 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
930 static void callback_eap(GSupplicantInterface *interface, bool status)
931 {
932         if (!callbacks_pointer)
933                 return;
934
935         if (!callbacks_pointer->eap)
936                 return;
937
938         callbacks_pointer->eap(interface, status);
939 }
940 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
941
942 static void callback_peer_found(GSupplicantPeer *peer)
943 {
944         if (!callbacks_pointer)
945                 return;
946
947         if (!callbacks_pointer->peer_found)
948                 return;
949
950         callbacks_pointer->peer_found(peer);
951 }
952
953 static void callback_peer_lost(GSupplicantPeer *peer)
954 {
955         if (!callbacks_pointer)
956                 return;
957
958         if (!callbacks_pointer->peer_lost)
959                 return;
960
961         callbacks_pointer->peer_lost(peer);
962 }
963
964 static void callback_peer_changed(GSupplicantPeer *peer,
965                                                 GSupplicantPeerState state)
966 {
967         if (!callbacks_pointer)
968                 return;
969
970         if (!callbacks_pointer->peer_changed)
971                 return;
972
973         callbacks_pointer->peer_changed(peer, state);
974 }
975
976 static void callback_peer_request(GSupplicantPeer *peer)
977 {
978         if (!callbacks_pointer)
979                 return;
980
981         if (!callbacks_pointer->peer_request)
982                 return;
983
984         peer->connection_requested = true;
985
986         callbacks_pointer->peer_request(peer);
987 }
988
989 static void callback_disconnect_reason_code(GSupplicantInterface *interface,
990                                         int reason_code)
991 {
992         if (!callbacks_pointer)
993                 return;
994
995         if (!callbacks_pointer->disconnect_reasoncode)
996                 return;
997
998         if (reason_code != 0)
999                 callbacks_pointer->disconnect_reasoncode(interface,
1000                                                         reason_code);
1001 }
1002
1003 static void callback_assoc_status_code(GSupplicantInterface *interface,
1004                                 int status_code)
1005 {
1006         if (!callbacks_pointer)
1007                 return;
1008
1009         if (!callbacks_pointer->assoc_status_code)
1010                 return;
1011
1012         callbacks_pointer->assoc_status_code(interface, status_code);
1013
1014 }
1015
1016 static void remove_group(gpointer data)
1017 {
1018         GSupplicantGroup *group = data;
1019
1020         if (group->members)
1021                 g_slist_free_full(group->members, g_free);
1022
1023         g_free(group->path);
1024         g_free(group);
1025 }
1026
1027 static void remove_interface(gpointer data)
1028 {
1029         GSupplicantInterface *interface = data;
1030
1031         g_hash_table_destroy(interface->bss_mapping);
1032         g_hash_table_destroy(interface->network_table);
1033         g_hash_table_destroy(interface->peer_table);
1034         g_hash_table_destroy(interface->group_table);
1035
1036         if (interface->scan_callback) {
1037                 SUPPLICANT_DBG("call interface %p callback %p scanning %d",
1038                                 interface, interface->scan_callback,
1039                                 interface->scanning);
1040
1041                 interface->scan_callback(-EIO, interface, interface->scan_data);
1042                 interface->scan_callback = NULL;
1043                 interface->scan_data = NULL;
1044
1045                 if (interface->scanning) {
1046                         interface->scanning = FALSE;
1047                         callback_scan_finished(interface);
1048                 }
1049         }
1050
1051         callback_interface_removed(interface);
1052
1053         g_free(interface->wps_cred.key);
1054         g_free(interface->path);
1055         g_free(interface->network_path);
1056 #if defined TIZEN_EXT
1057         interface->network_path = NULL;
1058 #endif
1059         g_free(interface->ifname);
1060         g_free(interface->driver);
1061         g_free(interface->bridge);
1062         remove_network_information(interface);
1063         g_free(interface);
1064 }
1065
1066 static void remove_network(gpointer data)
1067 {
1068         GSupplicantNetwork *network = data;
1069
1070         g_hash_table_destroy(network->bss_table);
1071
1072         callback_network_removed(network);
1073
1074         g_hash_table_destroy(network->config_table);
1075 #if defined TIZEN_EXT
1076         g_hash_table_destroy(network->assoc_reject_table);
1077 #endif
1078
1079         g_free(network->path);
1080         g_free(network->group);
1081         g_free(network->name);
1082 #if defined TIZEN_EXT
1083         g_free(network->eap);
1084         g_free(network->identity);
1085         g_free(network->phase2);
1086 #endif
1087 #if defined TIZEN_EXT
1088         g_slist_free_full(network->vsie_list, g_free);
1089 #endif
1090
1091         g_free(network);
1092 }
1093
1094 static void remove_bss(gpointer data)
1095 {
1096         struct g_supplicant_bss *bss = data;
1097
1098         supplicant_dbus_property_call_cancel_all(bss);
1099
1100         g_free(bss->path);
1101 #if defined TIZEN_EXT
1102         g_slist_free_full(bss->vsie_list, g_free);
1103 #endif
1104         g_free(bss);
1105 }
1106
1107 static void remove_peer(gpointer data)
1108 {
1109         GSupplicantPeer *peer = data;
1110
1111         callback_peer_lost(peer);
1112
1113         if (peer->groups)
1114                 g_slist_free_full(peer->groups, g_free);
1115
1116         if (peer_mapping)
1117                 g_hash_table_remove(peer_mapping, peer->path);
1118
1119         if (pending_peer_connection)
1120                 g_hash_table_remove(pending_peer_connection, peer->path);
1121
1122         g_free(peer->path);
1123         g_free(peer->name);
1124         g_free(peer->identifier);
1125         g_free(peer->widi_ies);
1126
1127         g_free(peer);
1128 }
1129
1130 #if defined TIZEN_EXT
1131 static void remove_assoc_data(gpointer data)
1132 {
1133         struct assoc_reject_data *assoc_data = data;
1134
1135         g_free(assoc_data->bssid);
1136         g_slist_free(assoc_data->reject_time_list);
1137
1138         g_free(assoc_data);
1139 }
1140 #endif
1141
1142 static void debug_strvalmap(const char *label, struct strvalmap *map,
1143                                                         unsigned int val)
1144 {
1145         int i;
1146 #if defined TIZEN_EXT
1147         if (!simplified_log)
1148 #endif
1149         for (i = 0; map[i].str; i++) {
1150                 if (val & map[i].val)
1151                         SUPPLICANT_DBG("%s: %s", label, map[i].str);
1152         }
1153 }
1154
1155 static void interface_capability_keymgmt(DBusMessageIter *iter, void *user_data)
1156 {
1157         GSupplicantInterface *interface = user_data;
1158         const char *str = NULL;
1159         int i;
1160
1161         dbus_message_iter_get_basic(iter, &str);
1162         if (!str)
1163                 return;
1164
1165         for (i = 0; keymgmt_map[i].str; i++)
1166                 if (strcmp(str, keymgmt_map[i].str) == 0) {
1167                         interface->keymgmt_capa |= keymgmt_map[i].val;
1168                         break;
1169                 }
1170 }
1171
1172 static void interface_capability_authalg(DBusMessageIter *iter, void *user_data)
1173 {
1174         GSupplicantInterface *interface = user_data;
1175         const char *str = NULL;
1176         int i;
1177
1178         dbus_message_iter_get_basic(iter, &str);
1179         if (!str)
1180                 return;
1181
1182         for (i = 0; authalg_capa_map[i].str; i++)
1183                 if (strcmp(str, authalg_capa_map[i].str) == 0) {
1184                         interface->authalg_capa |= authalg_capa_map[i].val;
1185                         break;
1186                 }
1187 }
1188
1189 static void interface_capability_proto(DBusMessageIter *iter, void *user_data)
1190 {
1191         GSupplicantInterface *interface = user_data;
1192         const char *str = NULL;
1193         int i;
1194
1195         dbus_message_iter_get_basic(iter, &str);
1196         if (!str)
1197                 return;
1198
1199         for (i = 0; proto_capa_map[i].str; i++)
1200                 if (strcmp(str, proto_capa_map[i].str) == 0) {
1201                         interface->proto_capa |= proto_capa_map[i].val;
1202                         break;
1203                 }
1204 }
1205
1206 static void interface_capability_pairwise(DBusMessageIter *iter,
1207                                                         void *user_data)
1208 {
1209         GSupplicantInterface *interface = user_data;
1210         const char *str = NULL;
1211         int i;
1212
1213         dbus_message_iter_get_basic(iter, &str);
1214         if (!str)
1215                 return;
1216
1217         for (i = 0; pairwise_map[i].str; i++)
1218                 if (strcmp(str, pairwise_map[i].str) == 0) {
1219                         interface->pairwise_capa |= pairwise_map[i].val;
1220                         break;
1221                 }
1222 }
1223
1224 static void interface_capability_group(DBusMessageIter *iter, void *user_data)
1225 {
1226         GSupplicantInterface *interface = user_data;
1227         const char *str = NULL;
1228         int i;
1229
1230         dbus_message_iter_get_basic(iter, &str);
1231         if (!str)
1232                 return;
1233
1234         for (i = 0; group_map[i].str; i++)
1235                 if (strcmp(str, group_map[i].str) == 0) {
1236                         interface->group_capa |= group_map[i].val;
1237                         break;
1238                 }
1239 }
1240
1241 static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
1242 {
1243         GSupplicantInterface *interface = user_data;
1244         const char *str = NULL;
1245         int i;
1246
1247         dbus_message_iter_get_basic(iter, &str);
1248         if (!str)
1249                 return;
1250
1251         for (i = 0; scan_capa_map[i].str; i++)
1252                 if (strcmp(str, scan_capa_map[i].str) == 0) {
1253                         interface->scan_capa |= scan_capa_map[i].val;
1254                         break;
1255                 }
1256 }
1257
1258 static void interface_capability_mode(DBusMessageIter *iter, void *user_data)
1259 {
1260         GSupplicantInterface *interface = user_data;
1261         const char *str = NULL;
1262         int i;
1263
1264         dbus_message_iter_get_basic(iter, &str);
1265         if (!str)
1266                 return;
1267
1268         for (i = 0; mode_capa_map[i].str; i++)
1269                 if (strcmp(str, mode_capa_map[i].str) == 0) {
1270                         interface->mode_capa |= mode_capa_map[i].val;
1271                         break;
1272                 }
1273 }
1274
1275 static void interface_capability(const char *key, DBusMessageIter *iter,
1276                                                         void *user_data)
1277 {
1278         GSupplicantInterface *interface = user_data;
1279
1280         if (!key)
1281                 return;
1282
1283         if (g_strcmp0(key, "KeyMgmt") == 0)
1284                 supplicant_dbus_array_foreach(iter,
1285                                 interface_capability_keymgmt, interface);
1286         else if (g_strcmp0(key, "AuthAlg") == 0)
1287                 supplicant_dbus_array_foreach(iter,
1288                                 interface_capability_authalg, interface);
1289         else if (g_strcmp0(key, "Protocol") == 0)
1290                 supplicant_dbus_array_foreach(iter,
1291                                 interface_capability_proto, interface);
1292         else if (g_strcmp0(key, "Pairwise") == 0)
1293                 supplicant_dbus_array_foreach(iter,
1294                                 interface_capability_pairwise, interface);
1295         else if (g_strcmp0(key, "Group") == 0)
1296                 supplicant_dbus_array_foreach(iter,
1297                                 interface_capability_group, interface);
1298         else if (g_strcmp0(key, "Scan") == 0)
1299                 supplicant_dbus_array_foreach(iter,
1300                                 interface_capability_scan, interface);
1301         else if (g_strcmp0(key, "Modes") == 0)
1302                 supplicant_dbus_array_foreach(iter,
1303                                 interface_capability_mode, interface);
1304         else if (g_strcmp0(key, "MaxScanSSID") == 0) {
1305                 dbus_int32_t max_scan_ssid;
1306
1307                 dbus_message_iter_get_basic(iter, &max_scan_ssid);
1308                 if (max_scan_ssid < 2)
1309                         max_scan_ssid = 0;
1310                 interface->max_scan_ssids = max_scan_ssid;
1311 #if defined TIZEN_EXT
1312         } else if (g_strcmp0(key, "Is5GhzSupported") == 0) {
1313                 dbus_bool_t is_5_0_Ghz_supported;
1314
1315                 dbus_message_iter_get_basic(iter, &is_5_0_Ghz_supported);
1316                 interface->is_5_0_Ghz_supported = is_5_0_Ghz_supported;
1317 #endif
1318         } else
1319                 SUPPLICANT_DBG("key %s type %c",
1320                                 key, dbus_message_iter_get_arg_type(iter));
1321 }
1322
1323 static void set_bss_expiration_age(DBusMessageIter *iter, void *user_data)
1324 {
1325         unsigned int bss_expiration_age = GPOINTER_TO_UINT(user_data);
1326
1327         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
1328                                 &bss_expiration_age);
1329 }
1330
1331 int g_supplicant_interface_set_bss_expiration_age(GSupplicantInterface *interface,
1332                                         unsigned int bss_expiration_age)
1333 {
1334        return supplicant_dbus_property_set(interface->path,
1335                                        SUPPLICANT_INTERFACE ".Interface",
1336                                        "BSSExpireAge", DBUS_TYPE_UINT32_AS_STRING,
1337                                        set_bss_expiration_age, NULL,
1338                                        GUINT_TO_POINTER(bss_expiration_age), NULL);
1339 }
1340
1341 struct set_apscan_data
1342 {
1343         unsigned int ap_scan;
1344         GSupplicantInterface *interface;
1345 };
1346
1347 static void set_apscan(DBusMessageIter *iter, void *user_data)
1348 {
1349         struct set_apscan_data *data = user_data;
1350         unsigned int ap_scan = data->ap_scan;
1351
1352         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &ap_scan);
1353 }
1354
1355 static void set_apscan_complete(const char *error,
1356                 DBusMessageIter *iter, void *user_data)
1357 {
1358         struct set_apscan_data *data = user_data;
1359         GSupplicantInterface *interface = data->interface;
1360
1361         if (error) {
1362                 interface->ap_create_in_progress = false;
1363                 SUPPLICANT_DBG("Set AP scan error %s", error);
1364                 goto error;
1365         }
1366
1367         interface->ap_create_in_progress = true;
1368 error:
1369         dbus_free(data);
1370 }
1371
1372 int g_supplicant_interface_set_apscan(GSupplicantInterface *interface,
1373                                                         unsigned int ap_scan)
1374 {
1375         struct set_apscan_data *data;
1376         int ret;
1377
1378         data = dbus_malloc0(sizeof(*data));
1379
1380         if (!data)
1381                 return -ENOMEM;
1382
1383         data->ap_scan = ap_scan;
1384         data->interface = interface;
1385
1386         ret = supplicant_dbus_property_set(interface->path,
1387                         SUPPLICANT_INTERFACE ".Interface",
1388                         "ApScan", DBUS_TYPE_UINT32_AS_STRING,
1389                         set_apscan, set_apscan_complete, data, NULL);
1390         if (ret < 0)
1391                 dbus_free(data);
1392
1393         return ret;
1394 }
1395
1396 void g_supplicant_interface_set_data(GSupplicantInterface *interface,
1397                                                                 void *data)
1398 {
1399         if (!interface)
1400                 return;
1401
1402         interface->data = data;
1403
1404         if (!data)
1405                 interface->scan_callback = NULL;
1406 }
1407
1408 void *g_supplicant_interface_get_data(GSupplicantInterface *interface)
1409 {
1410         if (!interface)
1411                 return NULL;
1412
1413         return interface->data;
1414 }
1415
1416 const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface)
1417 {
1418         if (!interface)
1419                 return NULL;
1420
1421         return interface->ifname;
1422 }
1423
1424 #if defined TIZEN_EXT
1425 bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *interface)
1426 {
1427         if (!interface)
1428                 return NULL;
1429
1430         return interface->is_5_0_Ghz_supported;
1431 }
1432
1433 unsigned char *g_supplicant_interface_get_add_network_bssid(GSupplicantInterface *interface)
1434 {
1435         if (!interface)
1436                 return NULL;
1437
1438         return (unsigned char *)interface->add_network_bssid;
1439 }
1440 #endif
1441
1442 const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface)
1443 {
1444         if (!interface)
1445                 return NULL;
1446
1447         return interface->driver;
1448 }
1449
1450 GSupplicantState g_supplicant_interface_get_state(
1451                                         GSupplicantInterface *interface)
1452 {
1453         if (!interface)
1454                 return G_SUPPLICANT_STATE_UNKNOWN;
1455
1456         return interface->state;
1457 }
1458
1459 const char *g_supplicant_interface_get_wps_key(GSupplicantInterface *interface)
1460 {
1461         if (!interface)
1462                 return NULL;
1463
1464         return (const char *)interface->wps_cred.key;
1465 }
1466
1467 const void *g_supplicant_interface_get_wps_ssid(GSupplicantInterface *interface,
1468                                                         unsigned int *ssid_len)
1469 {
1470         if (!ssid_len)
1471                 return NULL;
1472
1473         if (!interface || interface->wps_cred.ssid_len == 0) {
1474                 *ssid_len = 0;
1475                 return NULL;
1476         }
1477
1478         *ssid_len = interface->wps_cred.ssid_len;
1479         return interface->wps_cred.ssid;
1480 }
1481
1482 GSupplicantWpsState g_supplicant_interface_get_wps_state(
1483                                         GSupplicantInterface *interface)
1484 {
1485         if (!interface)
1486                 return G_SUPPLICANT_WPS_STATE_UNKNOWN;
1487
1488         return interface->wps_state;
1489 }
1490
1491 unsigned int g_supplicant_interface_get_mode(GSupplicantInterface *interface)
1492 {
1493         if (!interface)
1494                 return 0;
1495
1496         return interface->mode_capa;
1497 }
1498
1499 unsigned int g_supplicant_interface_get_max_scan_ssids(
1500                                 GSupplicantInterface *interface)
1501 {
1502         if (!interface)
1503                 return 0;
1504
1505         if (interface->max_scan_ssids == 0)
1506                 return WPAS_MAX_SCAN_SSIDS;
1507
1508         return interface->max_scan_ssids;
1509 }
1510
1511 static void set_network_enabled(DBusMessageIter *iter, void *user_data)
1512 {
1513         dbus_bool_t enable = *(dbus_bool_t *)user_data;
1514
1515         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &enable);
1516 }
1517
1518 int g_supplicant_interface_enable_selected_network(GSupplicantInterface *interface,
1519                                                         dbus_bool_t enable)
1520 {
1521         if (!interface)
1522                 return -1;
1523
1524         if (!interface->network_path)
1525                 return -1;
1526
1527         SUPPLICANT_DBG(" ");
1528         return supplicant_dbus_property_set(interface->network_path,
1529                                 SUPPLICANT_INTERFACE ".Network",
1530                                 "Enabled", DBUS_TYPE_BOOLEAN_AS_STRING,
1531                                 set_network_enabled, NULL, &enable, NULL);
1532 }
1533
1534 dbus_bool_t g_supplicant_interface_get_ready(GSupplicantInterface *interface)
1535 {
1536         if (!interface)
1537                 return FALSE;
1538
1539         return interface->ready;
1540 }
1541
1542 GSupplicantInterface *g_supplicant_network_get_interface(
1543                                         GSupplicantNetwork *network)
1544 {
1545         if (!network)
1546                 return NULL;
1547
1548         return network->interface;
1549 }
1550
1551 const char *g_supplicant_network_get_name(GSupplicantNetwork *network)
1552 {
1553         if (!network || !network->name)
1554                 return "";
1555
1556         return network->name;
1557 }
1558
1559 const char *g_supplicant_network_get_identifier(GSupplicantNetwork *network)
1560 {
1561         if (!network || !network->group)
1562                 return "";
1563
1564         return network->group;
1565 }
1566
1567 const char *g_supplicant_network_get_path(GSupplicantNetwork *network)
1568 {
1569         if (!network || !network->path)
1570                 return NULL;
1571
1572         return network->path;
1573 }
1574
1575 const char *g_supplicant_network_get_mode(GSupplicantNetwork *network)
1576 {
1577         if (!network)
1578                 return NULL;
1579
1580         return mode2string(network->mode);
1581 }
1582
1583 const char *g_supplicant_network_get_security(GSupplicantNetwork *network)
1584 {
1585         if (!network)
1586                 return NULL;
1587
1588         return security2string(network->security);
1589 }
1590
1591 const void *g_supplicant_network_get_ssid(GSupplicantNetwork *network,
1592                                                 unsigned int *ssid_len)
1593 {
1594         if (!network) {
1595                 *ssid_len = 0;
1596                 return NULL;
1597         }
1598
1599         *ssid_len = network->ssid_len;
1600         return network->ssid;
1601 }
1602
1603 dbus_int16_t g_supplicant_network_get_signal(GSupplicantNetwork *network)
1604 {
1605         if (!network)
1606                 return 0;
1607
1608         return network->signal;
1609 }
1610
1611 #if defined TIZEN_EXT
1612 void g_supplicant_network_set_signal(GSupplicantNetwork *network, int signal)
1613 {
1614         if (!network)
1615                 return;
1616
1617         network->signal = (dbus_int16_t)signal;
1618 }
1619
1620 void g_supplicant_network_set_bss_signal(GSupplicantNetwork *network,
1621                 int signal, int snr)
1622 {
1623         struct g_supplicant_bss *best_bss;
1624
1625         if (!network)
1626                 return;
1627
1628         best_bss = network->best_bss;
1629         if (!best_bss)
1630                 return;
1631
1632         best_bss->signal = (dbus_int16_t)signal;
1633         best_bss->snr = (dbus_int16_t)snr;
1634 }
1635 #endif
1636
1637 dbus_uint16_t g_supplicant_network_get_frequency(GSupplicantNetwork *network)
1638 {
1639         if (!network)
1640                 return 0;
1641
1642         return network->frequency;
1643 }
1644
1645 dbus_bool_t g_supplicant_network_get_wps(GSupplicantNetwork *network)
1646 {
1647         if (!network)
1648                 return FALSE;
1649
1650         return network->wps;
1651 }
1652
1653 dbus_bool_t g_supplicant_network_is_wps_active(GSupplicantNetwork *network)
1654 {
1655         if (!network)
1656                 return FALSE;
1657
1658         if (network->wps_capabilities & G_SUPPLICANT_WPS_CONFIGURED)
1659                 return TRUE;
1660
1661         return FALSE;
1662 }
1663
1664 dbus_bool_t g_supplicant_network_is_wps_pbc(GSupplicantNetwork *network)
1665 {
1666         if (!network)
1667                 return FALSE;
1668
1669         if (network->wps_capabilities & G_SUPPLICANT_WPS_PBC)
1670                 return TRUE;
1671
1672         return FALSE;
1673 }
1674
1675 dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
1676 {
1677         if (!network)
1678                 return FALSE;
1679
1680         if (network->wps_capabilities & G_SUPPLICANT_WPS_REGISTRAR)
1681                 return TRUE;
1682
1683         return FALSE;
1684 }
1685
1686 #ifdef TIZEN_EXT
1687 GSupplicantPhy_mode g_supplicant_network_get_phy_mode(GSupplicantNetwork *network)
1688 {
1689         if (!network)
1690                 return G_SUPPLICANT_MODE_IEEE80211_UNKNOWN;
1691
1692         return network->phy_mode;
1693 }
1694 #endif
1695
1696 GSupplicantInterface *g_supplicant_peer_get_interface(GSupplicantPeer *peer)
1697 {
1698         if (!peer)
1699                 return NULL;
1700
1701         return peer->interface;
1702 }
1703
1704 const char *g_supplicant_peer_get_path(GSupplicantPeer *peer)
1705 {
1706         if (!peer)
1707                 return NULL;
1708
1709         return peer->path;
1710 }
1711
1712 const char *g_supplicant_peer_get_identifier(GSupplicantPeer *peer)
1713 {
1714         if (!peer)
1715                 return NULL;
1716
1717         return peer->identifier;
1718 }
1719
1720 const void *g_supplicant_peer_get_device_address(GSupplicantPeer *peer)
1721 {
1722         if (!peer)
1723                 return NULL;
1724
1725         return peer->device_address;
1726 }
1727
1728 const void *g_supplicant_peer_get_iface_address(GSupplicantPeer *peer)
1729 {
1730         if (!peer)
1731                 return NULL;
1732
1733         return peer->iface_address;
1734 }
1735
1736 const char *g_supplicant_peer_get_name(GSupplicantPeer *peer)
1737 {
1738         if (!peer)
1739                 return NULL;
1740
1741         return peer->name;
1742 }
1743
1744 #if defined TIZEN_EXT
1745 bool g_supplicant_network_is_hs20AP(GSupplicantNetwork *network)
1746 {
1747         if (!network)
1748                 return 0;
1749
1750         return network->isHS20AP;
1751 }
1752
1753 const char *g_supplicant_network_get_eap(GSupplicantNetwork *network)
1754 {
1755         if (!network || !network->eap)
1756                 return NULL;
1757
1758         return network->eap;
1759 }
1760
1761 const char *g_supplicant_network_get_identity(GSupplicantNetwork *network)
1762 {
1763         if (!network || !network->identity)
1764                 return NULL;
1765
1766         return network->identity;
1767 }
1768
1769 const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network)
1770 {
1771         if (!network || !network->phase2)
1772                 return NULL;
1773
1774         return network->phase2;
1775 }
1776
1777 unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network)
1778 {
1779         if (!network)
1780                 return 0;
1781
1782         return network->keymgmt;
1783 }
1784
1785 dbus_bool_t g_supplicant_network_get_privacy(GSupplicantNetwork *network)
1786 {
1787         if (!network)
1788                 return FALSE;
1789
1790         return network->privacy;
1791 }
1792
1793 const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork
1794                                                           *network)
1795 {
1796         if (!network)
1797                 return NULL;
1798
1799         return network->country_code;
1800 }
1801
1802 dbus_bool_t g_supplicant_network_is_pmf_required(GSupplicantNetwork *network)
1803 {
1804         if (!network || !network->best_bss)
1805                 return FALSE;
1806
1807         return network->best_bss->pmf_required;
1808 }
1809 #endif
1810
1811 const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer,
1812                                                                 int *length)
1813 {
1814         if (!peer || !length)
1815                 return NULL;
1816
1817         *length = peer->widi_ies_length;
1818         return peer->widi_ies;
1819 }
1820
1821 bool g_supplicant_peer_is_wps_pbc(GSupplicantPeer *peer)
1822 {
1823         if (!peer)
1824                 return false;
1825
1826         if (peer->wps_capabilities & G_SUPPLICANT_WPS_PBC)
1827                 return true;
1828
1829         return false;
1830 }
1831
1832 bool g_supplicant_peer_is_wps_pin(GSupplicantPeer *peer)
1833 {
1834         if (!peer)
1835                 return false;
1836
1837         if (peer->wps_capabilities & G_SUPPLICANT_WPS_PIN)
1838                 return true;
1839
1840         return false;
1841 }
1842
1843 bool g_supplicant_peer_is_in_a_group(GSupplicantPeer *peer)
1844 {
1845         if (!peer || !peer->groups)
1846                 return false;
1847
1848         return true;
1849 }
1850
1851 GSupplicantInterface *g_supplicant_peer_get_group_interface(GSupplicantPeer *peer)
1852 {
1853         if (!peer)
1854                 return NULL;
1855
1856         return (GSupplicantInterface *) peer->current_group_iface;
1857 }
1858
1859 bool g_supplicant_peer_is_client(GSupplicantPeer *peer)
1860 {
1861         GSupplicantGroup *group;
1862         GSList *list;
1863
1864         if (!peer)
1865                 return false;
1866
1867         for (list = peer->groups; list; list = list->next) {
1868                 const char *path = list->data;
1869
1870                 group = g_hash_table_lookup(group_mapping, path);
1871                 if (!group)
1872                         continue;
1873
1874                 if (group->role != G_SUPPLICANT_GROUP_ROLE_CLIENT ||
1875                                 group->orig_interface != peer->interface)
1876                         continue;
1877
1878                 if (group->interface == peer->current_group_iface)
1879                         return true;
1880         }
1881
1882         return false;
1883 }
1884
1885 bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer)
1886 {
1887         if (!peer)
1888                 return false;
1889
1890         return peer->connection_requested;
1891 }
1892
1893 #if defined TIZEN_EXT
1894 /*
1895  * Description: Network client requires additional wifi specific info
1896  */
1897 const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
1898 {
1899         if (network == NULL || network->best_bss == NULL)
1900                 return NULL;
1901
1902         return (const unsigned char *)network->best_bss->bssid;
1903 }
1904
1905 dbus_bool_t g_supplicant_network_get_transition_mode(GSupplicantNetwork *network)
1906 {
1907         if (network == NULL)
1908                 return FALSE;
1909
1910         return network->owe_transition_mode;
1911 }
1912
1913 const unsigned char *g_supplicant_network_get_transition_mode_bssid(GSupplicantNetwork *network)
1914 {
1915         if (network == NULL)
1916                 return NULL;
1917
1918         return (const unsigned char *)network->transition_mode_bssid;
1919 }
1920
1921 const void *g_supplicant_network_get_transition_mode_ssid(GSupplicantNetwork *network,
1922                                                 unsigned int *transition_mode_ssid_len)
1923 {
1924         if (!network) {
1925                 *transition_mode_ssid_len = 0;
1926                 return NULL;
1927         }
1928
1929         *transition_mode_ssid_len = network->transition_mode_ssid_len;
1930         return network->transition_mode_ssid;
1931 }
1932
1933 unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
1934 {
1935         if (network == NULL || network->best_bss == NULL)
1936                 return 0;
1937
1938         return network->best_bss->maxrate;
1939 }
1940
1941 const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
1942 {
1943         if (network == NULL || network->best_bss == NULL)
1944                 return NULL;
1945
1946         if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
1947                         network->best_bss->security == G_SUPPLICANT_SECURITY_SAE ||
1948                         network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
1949                         network->best_bss->security == G_SUPPLICANT_SECURITY_DPP ||
1950                         network->best_bss->security == G_SUPPLICANT_SECURITY_PSK_SHA256 ||
1951                         network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
1952                 unsigned int pairwise;
1953
1954                 pairwise = network->best_bss->rsn_pairwise |
1955                                 network->best_bss->wpa_pairwise;
1956
1957                 if ((pairwise & G_SUPPLICANT_PAIRWISE_CCMP) &&
1958                     (pairwise & G_SUPPLICANT_PAIRWISE_TKIP))
1959                         return "mixed";
1960                 else if (pairwise & G_SUPPLICANT_PAIRWISE_CCMP)
1961                         return "aes";
1962                 else if (pairwise & G_SUPPLICANT_PAIRWISE_TKIP)
1963                         return "tkip";
1964
1965         } else if (network->best_bss->security == G_SUPPLICANT_SECURITY_WEP)
1966                 return "wep";
1967         else if (network->best_bss->security == G_SUPPLICANT_SECURITY_NONE)
1968                 return "none";
1969
1970         return NULL;
1971 }
1972
1973 bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network)
1974 {
1975         if (network == NULL || network->best_bss == NULL)
1976                 return 0;
1977
1978         if (network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
1979                         network->best_bss->security == G_SUPPLICANT_SECURITY_DPP)
1980                 return false;
1981
1982         if (network->best_bss->rsn_selected) {
1983                 const char *mode = g_supplicant_network_get_enc_mode(network);
1984                 if (g_strcmp0(mode, "aes") == 0 ||
1985                                 g_strcmp0(mode, "mixed") == 0)
1986                         return true;
1987                 else
1988                         return false;
1989         } else
1990                 return false;
1991 }
1992
1993 void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network)
1994 {
1995         GSList *vsie_list = NULL;
1996
1997         if (!network)
1998                 return NULL;
1999
2000         if (g_slist_length(network->vsie_list) > 0) {
2001                 GSList *list = NULL;
2002                 unsigned char *vsie = NULL;
2003                 for (list = network->vsie_list; list; list = list->next) {
2004                         unsigned char *ie = (unsigned char *)list->data;
2005                         if (ie == NULL)
2006                                 continue;
2007                         vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1)
2008
2009                         if (vsie) {
2010                                 memcpy(vsie, ie, ie[1]+2);
2011                                 vsie_list = g_slist_append(vsie_list, vsie);
2012                         } else
2013                                 SUPPLICANT_DBG("Failed to allocate memory");
2014                 }
2015         }
2016
2017         return vsie_list;
2018 }
2019
2020 #if defined TIZEN_EXT_INS
2021 static bool compare_bssid(unsigned char *bssid_a, unsigned char *bssid_b)
2022 {
2023         if (!memcmp(bssid_a, bssid_b, WIFI_BSSID_LEN_MAX))
2024                 return true;
2025
2026         return false;
2027 }
2028
2029 static gchar *convert_bssid_to_str(unsigned char *bssid)
2030 {
2031         GString *bssid_str;
2032         unsigned int i;
2033
2034         bssid_str = g_string_sized_new(18);
2035         if (!bssid_str)
2036                 return NULL;
2037
2038         for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
2039                 g_string_append_printf(bssid_str, "%02x", bssid[i]);
2040                 if (i < WIFI_BSSID_LEN_MAX - 1)
2041                         g_string_append(bssid_str, ":");
2042         }
2043
2044         return g_string_free(bssid_str, FALSE);
2045 }
2046
2047 static void count_assoc_reject(gpointer data, gpointer user_data)
2048 {
2049         time_t assoc_reject_time = GPOINTER_TO_INT(data);
2050         struct assoc_count_data *assoc_count = user_data;
2051
2052         if (assoc_reject_time > assoc_count->ref_time)
2053                 assoc_count->assoc_count++;
2054 }
2055
2056 static uint16_t get_assoc_reject_cnt(GHashTable *assoc_reject_table, unsigned char *bssid)
2057 {
2058         gchar *bssid_str;
2059         struct assoc_reject_data *assoc_data;
2060         struct assoc_count_data assoc_count;
2061         time_t curr_time;
2062         struct tm* timeinfo;
2063
2064         if (g_hash_table_size(assoc_reject_table) < 1)
2065                 return 0;
2066
2067         if (!bssid)
2068                 return 0;
2069
2070         if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
2071                 return 0;
2072
2073         bssid_str = convert_bssid_to_str(bssid);
2074         if (!bssid_str)
2075                 return 0;
2076
2077         assoc_data = g_hash_table_lookup(assoc_reject_table, bssid_str);
2078         if (!assoc_data) {
2079                 g_free(bssid_str);
2080                 return 0;
2081         }
2082
2083         if (g_slist_length(assoc_data->reject_time_list) < 1) {
2084                 g_free(bssid_str);
2085                 return 0;
2086         }
2087
2088         /* Only events that occur within one hour are appened. */
2089         curr_time = time(NULL);
2090         timeinfo = localtime(&curr_time);
2091         timeinfo->tm_hour -= 1;
2092
2093         assoc_count.ref_time = mktime(timeinfo);
2094         assoc_count.assoc_count = 0;
2095
2096         g_slist_foreach(assoc_data->reject_time_list, count_assoc_reject, &assoc_count);
2097
2098         g_free(bssid_str);
2099         return assoc_count.assoc_count;
2100 }
2101
2102 static int calculate_score_last_connected_bssid(bool is_last_connected)
2103 {
2104         int score = 0;
2105
2106         if (ins_settings.last_connected_bssid) {
2107                 if (is_last_connected)
2108                         score += ins_settings.last_connected_bssid_score;
2109         }
2110
2111         return score;
2112 }
2113
2114 static int calculate_score_assoc_reject(uint16_t assoc_reject_cnt)
2115 {
2116         int score = 0;
2117
2118         if (ins_settings.assoc_reject)
2119                 score -= (assoc_reject_cnt * ins_settings.assoc_reject_score);
2120
2121         return score;
2122 }
2123
2124 static int calculate_score_frequency(dbus_int16_t strength, dbus_uint16_t frequency)
2125 {
2126         int score = 0;
2127
2128         switch (ins_settings.preferred_freq_bssid) {
2129         case G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ:
2130                 if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
2131                         frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
2132                         (strength > ins_settings.signal_level3_24ghz))
2133                         score += ins_settings.preferred_freq_bssid_score;
2134
2135                 break;
2136         case G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ:
2137                 if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
2138                         frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
2139                         (strength > ins_settings.signal_level3_5ghz))
2140                         score += ins_settings.preferred_freq_bssid_score;
2141
2142                 break;
2143         default:
2144                 break;
2145         }
2146
2147         return score;
2148 }
2149
2150 static int calculate_score_strength(dbus_int16_t strength)
2151 {
2152         int score = 0;
2153
2154         if (ins_settings.signal_bssid)
2155                 score += (((strength > -60) ? -60 : strength) + 85);
2156
2157         return score;
2158 }
2159
2160 static int calculate_score_est_throughput(dbus_uint32_t est_throughput)
2161 {
2162         int score = 0;
2163
2164         if (est_throughput >= 10000)
2165                 score = est_throughput / 10000;
2166
2167         if (score > 40)
2168                 score = 40;
2169
2170         return score;
2171 }
2172
2173 static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt,
2174                 dbus_uint16_t frequency, dbus_int16_t strength,
2175                 dbus_int16_t snr, dbus_uint32_t est_throughput)
2176 {
2177         int score = 0;
2178
2179         score += calculate_score_last_connected_bssid(is_last_connected);
2180         score += calculate_score_assoc_reject(assoc_reject_cnt);
2181         score += calculate_score_frequency(strength, frequency);
2182         score += calculate_score_strength(strength);
2183         score += (int)snr;
2184         score += calculate_score_est_throughput(est_throughput);
2185
2186         return score;
2187 }
2188 #endif /* defined TIZEN_EXT_INS */
2189
2190 static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
2191 {
2192         struct g_supplicant_bss *bss = value;
2193         struct g_connman_bssids *bssids = NULL;
2194         struct update_bssid_data *bssid_data = (struct update_bssid_data *)user_data;
2195
2196         bssids = (struct g_connman_bssids *)g_try_malloc0(sizeof(struct g_connman_bssids));
2197
2198         if (bssids) {
2199                 memcpy(bssids->bssid, bss->bssid, WIFI_BSSID_LEN_MAX);
2200
2201                 bssids->strength = bss->signal;
2202                 bssids->strength += 120;
2203
2204                 if (bssids->strength > 100)
2205                         bssids->strength = 100;
2206
2207                 bssids->frequency = bss->frequency;
2208                 bssids->est_throughput = bss->est_throughput;
2209                 bssids->score_snr = (int)bss->snr;
2210
2211 #if defined TIZEN_EXT_INS
2212                 bssids->assoc_reject_cnt = get_assoc_reject_cnt(bssid_data->assoc_reject_table, bssids->bssid);
2213                 bssids->is_last_connected = compare_bssid(bssids->bssid, bssid_data->last_connected_bssid);
2214
2215                 bssids->score_last_connected_bssid = calculate_score_last_connected_bssid(bssids->is_last_connected);
2216                 bssids->score_assoc_reject = calculate_score_assoc_reject(bssids->assoc_reject_cnt);
2217                 bssids->score_frequency = calculate_score_frequency(bss->signal, bssids->frequency);
2218                 bssids->score_strength = calculate_score_strength(bss->signal);
2219                 bssids->score_est_throughput = calculate_score_est_throughput(bss->est_throughput);
2220
2221                 bssids->ins_score = calculate_score(bssids->is_last_connected,
2222                         bssids->assoc_reject_cnt, bssids->frequency, bss->signal,
2223                         bss->snr, bss->est_throughput);
2224 #else
2225                 bssids->ins_score = bss->signal;
2226 #endif
2227                 bssid_data->bssid_list = g_slist_append(bssid_data->bssid_list, bssids);
2228         } else
2229                 SUPPLICANT_DBG("Failed to allocate memory");
2230 }
2231
2232 static gint cmp_bss(gconstpointer a, gconstpointer b)
2233 {
2234         struct g_connman_bssids *entry_a = (struct g_connman_bssids *)a;
2235         struct g_connman_bssids *entry_b = (struct g_connman_bssids *)b;
2236
2237         if (entry_a->ins_score > entry_b->ins_score)
2238                 return -1;
2239
2240         if (entry_a->ins_score < entry_b->ins_score)
2241                 return 1;
2242
2243         if (entry_a->ins_score == entry_b->ins_score) {
2244                 if (entry_a->strength >= entry_b->strength)
2245                         return -1;
2246                 else
2247                         return 1;
2248         }
2249
2250         return 0;
2251 }
2252
2253 #if defined TIZEN_EXT_INS
2254 static void print_bssid_sort(gpointer data, gpointer user_data)
2255 {
2256         struct g_connman_bssids *bssids = data;
2257
2258         GSupplicantNetwork *network = (GSupplicantNetwork *) user_data;
2259
2260         if (!bssids || !network)
2261                 return;
2262
2263         if (!simplified_log)
2264                 SUPPLICANT_DBG("ssid [%-20s] bssid[" MACSTR "] total[%2d] freq[%2d] "
2265                                 "last_conn[%2d] assoc_reject[%2d] strength[%2d] rssi[%2d]",
2266                                 network->ssid, MAC2STR(bssids->bssid), bssids->ins_score,
2267                                 bssids->score_frequency, bssids->score_last_connected_bssid,
2268                                 bssids->score_assoc_reject, bssids->score_strength, bssids->strength - 120);
2269 }
2270 #endif
2271
2272 void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network)
2273 {
2274         struct update_bssid_data bssid_data;
2275
2276         if (g_hash_table_size(network->bss_table) < 1)
2277                 return NULL;
2278
2279         bssid_data.network = network;
2280         memset(&bssid_data, 0, sizeof(bssid_data));
2281         memcpy(bssid_data.last_connected_bssid, network->last_connected_bssid, WIFI_BSSID_LEN_MAX);
2282         bssid_data.assoc_reject_table = network->assoc_reject_table;
2283
2284         g_hash_table_foreach(network->bss_table, update_bssid_list, &bssid_data);
2285         bssid_data.bssid_list = g_slist_sort(bssid_data.bssid_list, cmp_bss);
2286 #if defined TIZEN_EXT_INS
2287         g_slist_foreach(bssid_data.bssid_list, print_bssid_sort, (gpointer)network);
2288 #endif
2289
2290         return bssid_data.bssid_list;
2291 }
2292
2293 #if defined TIZEN_EXT_INS
2294 void g_supplicant_network_set_last_connected_bssid(GSupplicantNetwork *network, const unsigned char *bssid)
2295 {
2296         if (!bssid)
2297                 return;
2298
2299         if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
2300                 return;
2301
2302         memcpy(network->last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX);
2303
2304         SUPPLICANT_DBG("last connected bssid [" MACSTR "]", MAC2STR(bssid));
2305 }
2306
2307 const unsigned char *g_supplicant_network_get_last_connected_bssid(GSupplicantNetwork *network)
2308 {
2309         if (network == NULL)
2310                 return NULL;
2311
2312         return (const unsigned char *)network->last_connected_bssid;
2313 }
2314
2315 void g_supplicant_network_update_assoc_reject(GSupplicantInterface *interface,
2316                 GSupplicantNetwork *network)
2317 {
2318         struct assoc_reject_data *assoc_data;
2319         gchar *bssid_str;
2320         time_t curr_time;
2321
2322         if (!network)
2323                 return;
2324
2325         bssid_str = convert_bssid_to_str(interface->add_network_bssid);
2326         if (!bssid_str)
2327                 return;
2328
2329         assoc_data = g_hash_table_lookup(network->assoc_reject_table, bssid_str);
2330         if (!assoc_data) {
2331                 assoc_data = g_try_new0(struct assoc_reject_data, 1);
2332                 if (!assoc_data) {
2333                         g_free(bssid_str);
2334                         return;
2335                 }
2336
2337                 assoc_data->bssid = g_strdup(bssid_str);
2338                 g_hash_table_insert(network->assoc_reject_table, assoc_data->bssid, assoc_data);
2339         }
2340
2341         curr_time = time(NULL);
2342         assoc_data->reject_time_list = g_slist_append(assoc_data->reject_time_list, GINT_TO_POINTER(curr_time));
2343
2344         SUPPLICANT_DBG("bssid [%s] time [%u]", bssid_str, curr_time);
2345
2346         g_free(bssid_str);
2347
2348         callback_network_changed(network, "UpdateAssocReject");
2349 }
2350
2351 GHashTable *g_supplicant_network_get_assoc_reject_table(GSupplicantNetwork *network)
2352 {
2353         if (!network)
2354                 return NULL;
2355
2356         return network->assoc_reject_table;
2357 }
2358
2359 static void copy_assoc_reject(gpointer key, gpointer value, gpointer user_data)
2360 {
2361         struct assoc_reject_data *cloned_assoc_data;
2362         struct assoc_reject_data *assoc_data = value;
2363         GHashTable *cloned_assoc_reject_table = user_data;
2364
2365         if (assoc_data && cloned_assoc_reject_table) {
2366                 cloned_assoc_data = g_try_new0(struct assoc_reject_data, 1);
2367                 if (!cloned_assoc_data)
2368                         return;
2369
2370                 cloned_assoc_data->bssid = g_strdup(assoc_data->bssid);
2371                 cloned_assoc_data->reject_time_list = g_slist_copy(assoc_data->reject_time_list);
2372                 g_hash_table_insert(cloned_assoc_reject_table,
2373                                         cloned_assoc_data->bssid, cloned_assoc_data);
2374         }
2375 }
2376
2377 GHashTable *g_supplicant_network_clone_assoc_reject_table(GSupplicantNetwork *network)
2378 {
2379         GHashTable *cloned_assoc_reject_table;
2380
2381         if (!network)
2382                 return NULL;
2383
2384         GHashTable *assoc_reject_table = g_supplicant_network_get_assoc_reject_table(network);
2385         if (!assoc_reject_table)
2386                 return NULL;
2387
2388         cloned_assoc_reject_table = g_hash_table_new_full(g_str_hash, g_str_equal,
2389                                                                 NULL, remove_assoc_data);
2390         g_hash_table_foreach(assoc_reject_table, copy_assoc_reject, cloned_assoc_reject_table);
2391
2392         return cloned_assoc_reject_table;
2393 }
2394 #endif /* defined TIZEN_EXT_INS */
2395
2396 GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface,
2397                 const char *group)
2398 {
2399         if (!interface)
2400                 return NULL;
2401
2402         return g_hash_table_lookup(interface->network_table, group);
2403 }
2404 #endif /* defined TIZEN_EXT */
2405
2406 static void merge_network(GSupplicantNetwork *network)
2407 {
2408         GString *str;
2409         const char *ssid, *mode, *key_mgmt;
2410 #if defined TIZEN_EXT
2411         const char *isHS20AP;
2412         const char *eap, *identity, *phase2;
2413 #endif
2414         unsigned int i, ssid_len;
2415         char *group;
2416
2417         ssid = g_hash_table_lookup(network->config_table, "ssid");
2418         mode = g_hash_table_lookup(network->config_table, "mode");
2419         key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt");
2420 #if defined TIZEN_EXT
2421         isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP");
2422         eap = g_hash_table_lookup(network->config_table, "eap");
2423         identity = g_hash_table_lookup(network->config_table, "identity");
2424         phase2 = g_hash_table_lookup(network->config_table, "phase2");
2425 #endif
2426
2427         SUPPLICANT_DBG("ssid %s mode %s", ssid, mode);
2428
2429         if (ssid)
2430                 ssid_len = strlen(ssid);
2431         else
2432                 ssid_len = 0;
2433
2434         str = g_string_sized_new((ssid_len * 2) + 24);
2435         if (!str)
2436                 return;
2437
2438         for (i = 0; i < ssid_len; i++)
2439 #if defined TIZEN_EXT
2440         {
2441                 if (ssid[i] != '"')
2442 #endif
2443                 g_string_append_printf(str, "%02x", ssid[i]);
2444 #if defined TIZEN_EXT
2445         }
2446 #endif
2447
2448         if (g_strcmp0(mode, "0") == 0)
2449                 g_string_append_printf(str, "_managed");
2450         else if (g_strcmp0(mode, "1") == 0)
2451                 g_string_append_printf(str, "_adhoc");
2452 #if defined TIZEN_EXT_WIFI_MESH
2453         else if (g_strcmp0(mode, "5") == 0)
2454                 g_string_append_printf(str, "_mesh");
2455 #endif
2456
2457         if ((g_strcmp0(key_mgmt, "WPA-PSK") == 0) ||
2458             (g_strcmp0(key_mgmt, "SAE") == 0))
2459                 g_string_append_printf(str, "_psk");
2460 #if defined TIZEN_EXT
2461         else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0)
2462                 g_string_append_printf(str, "_ieee8021x");
2463         else
2464                 g_string_append_printf(str, "_none");
2465 #endif
2466
2467         group = g_string_free(str, FALSE);
2468
2469         SUPPLICANT_DBG("%s", group);
2470
2471 #if defined TIZEN_EXT
2472         if (g_strcmp0(isHS20AP, "1") == 0) {
2473                 network->isHS20AP = 1;
2474                 if (network->eap)
2475                         g_free(network->eap);
2476                 network->eap = g_strdup(eap);
2477
2478                 if (network->identity)
2479                         g_free(network->identity);
2480                 network->identity = g_strdup(identity);
2481
2482                 if (network->phase2)
2483                         g_free(network->phase2);
2484                 network->phase2 = g_strdup(phase2);
2485         } else
2486                 network->isHS20AP = 0;
2487
2488         network->group = g_strdup(group);
2489         callback_network_merged(network);
2490         g_free(network->group);
2491 #endif
2492
2493         g_free(group);
2494
2495         g_hash_table_destroy(network->config_table);
2496
2497         g_free(network->path);
2498         g_free(network);
2499 }
2500
2501 static void network_property(const char *key, DBusMessageIter *iter,
2502                                                         void *user_data)
2503 {
2504         GSupplicantNetwork *network = user_data;
2505
2506         if (!network->interface)
2507                 return;
2508
2509         if (!key) {
2510                 merge_network(network);
2511                 return;
2512         }
2513
2514         if (g_strcmp0(key, "Enabled") == 0) {
2515                 dbus_bool_t enabled = FALSE;
2516
2517                 dbus_message_iter_get_basic(iter, &enabled);
2518         } else if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
2519                 const char *str = NULL;
2520
2521                 dbus_message_iter_get_basic(iter, &str);
2522                 if (str) {
2523                         g_hash_table_replace(network->config_table,
2524                                                 g_strdup(key), g_strdup(str));
2525                 }
2526         } else
2527                 SUPPLICANT_DBG("key %s type %c",
2528                                 key, dbus_message_iter_get_arg_type(iter));
2529 }
2530
2531 static void interface_network_added(DBusMessageIter *iter, void *user_data)
2532 {
2533         GSupplicantInterface *interface = user_data;
2534         GSupplicantNetwork *network;
2535         const char *path = NULL;
2536
2537         SUPPLICANT_DBG("");
2538
2539         dbus_message_iter_get_basic(iter, &path);
2540         if (!path)
2541                 return;
2542
2543         if (g_strcmp0(path, "/") == 0)
2544                 return;
2545
2546         network = g_try_new0(GSupplicantNetwork, 1);
2547         if (!network)
2548                 return;
2549
2550         network->interface = interface;
2551         network->path = g_strdup(path);
2552
2553         network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
2554                                                         g_free, g_free);
2555
2556         dbus_message_iter_next(iter);
2557         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
2558                 supplicant_dbus_property_foreach(iter, network_property,
2559                                                                 network);
2560                 network_property(NULL, NULL, network);
2561                 return;
2562         }
2563
2564         supplicant_dbus_property_get_all(path,
2565                                 SUPPLICANT_INTERFACE ".Network",
2566                                         network_property, network, NULL);
2567 }
2568
2569 static void interface_network_removed(DBusMessageIter *iter, void *user_data)
2570 {
2571         SUPPLICANT_DBG("");
2572 }
2573
2574 static char *create_name(unsigned char *ssid, int ssid_len)
2575 {
2576         GString *string;
2577         const gchar *remainder, *invalid;
2578         int valid_bytes, remaining_bytes;
2579
2580         if (ssid_len < 1 || ssid[0] == '\0')
2581                 return g_strdup("");
2582
2583         string = NULL;
2584         remainder = (const gchar *)ssid;
2585         remaining_bytes = ssid_len;
2586
2587         while (remaining_bytes != 0) {
2588                 if (g_utf8_validate(remainder, remaining_bytes,
2589                                         &invalid)) {
2590                         break;
2591                 }
2592
2593                 valid_bytes = invalid - remainder;
2594
2595                 if (!string)
2596                         string = g_string_sized_new(remaining_bytes);
2597
2598                 g_string_append_len(string, remainder, valid_bytes);
2599
2600                 /* append U+FFFD REPLACEMENT CHARACTER */
2601                 g_string_append(string, "\357\277\275");
2602
2603                 remaining_bytes -= valid_bytes + 1;
2604                 remainder = invalid + 1;
2605         }
2606
2607         if (!string)
2608                 return g_strndup((const gchar *)ssid, ssid_len + 1);
2609
2610         g_string_append(string, remainder);
2611
2612         return g_string_free(string, FALSE);
2613 }
2614
2615 static char *create_group(struct g_supplicant_bss *bss)
2616 {
2617         GString *str;
2618         unsigned int i;
2619         const char *mode, *security;
2620
2621         str = g_string_sized_new((bss->ssid_len * 2) + 24);
2622         if (!str)
2623                 return NULL;
2624
2625         if (bss->ssid_len > 0 && bss->ssid[0] != '\0') {
2626                 for (i = 0; i < bss->ssid_len; i++)
2627                         g_string_append_printf(str, "%02x", bss->ssid[i]);
2628         } else
2629                 g_string_append_printf(str, "hidden");
2630
2631         mode = mode2string(bss->mode);
2632         if (mode)
2633                 g_string_append_printf(str, "_%s", mode);
2634
2635 #if defined TIZEN_EXT
2636         if (bss->security == G_SUPPLICANT_SECURITY_PSK_SHA256)
2637                 security = "psk";
2638         else
2639                 security = security2string(bss->security);
2640 #else
2641         security = security2string(bss->security);
2642 #endif
2643         if (security)
2644                 g_string_append_printf(str, "_%s", security);
2645
2646         return g_string_free(str, FALSE);
2647 }
2648 #if defined TIZEN_EXT
2649 static void update_network_with_best_bss(GSupplicantNetwork *network,
2650                 struct g_supplicant_bss *best_bss)
2651 {
2652         /*
2653          * Do not change best BSS if we are connected.
2654          */
2655         if (network->interface->state == G_SUPPLICANT_STATE_COMPLETED && network->best_bss)
2656                 return;
2657
2658         network->signal = best_bss->signal;
2659         network->frequency = best_bss->frequency;
2660         network->best_bss = best_bss;
2661 }
2662
2663 static bool update_best_bss(GSupplicantNetwork *network,
2664                 struct g_supplicant_bss *bss, struct g_supplicant_bss *best_bss)
2665 {
2666         int score_new;
2667         int score_best;
2668
2669         if (network->best_bss == NULL) {
2670                 update_network_with_best_bss(network, bss);
2671                 return true;
2672         }
2673
2674 #if defined TIZEN_EXT_INS
2675         score_new = calculate_score(
2676                 compare_bssid(bss->bssid, network->last_connected_bssid),
2677                 get_assoc_reject_cnt(network->assoc_reject_table, bss->bssid),
2678                 bss->frequency, bss->signal, bss->snr, bss->est_throughput);
2679
2680         score_best = calculate_score(
2681                 compare_bssid(network->best_bss->bssid, network->last_connected_bssid),
2682                 get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid),
2683                 network->best_bss->frequency, network->best_bss->signal,
2684                 network->best_bss->snr, network->best_bss->est_throughput);
2685 #else
2686         score_new = bss->signal;
2687         score_best = network->best_bss->signal;
2688 #endif
2689
2690         if (score_new > score_best) {
2691                 SUPPLICANT_DBG("new[" MACSTR "][%d] : best[" MACSTR "][%d]",
2692                         MAC2STR(bss->bssid), score_new,
2693                         MAC2STR(network->best_bss->bssid), score_best);
2694
2695                 update_network_with_best_bss(network, bss);
2696
2697                 SUPPLICANT_DBG("Update best BSS for %s", network->name);
2698
2699                 return true;
2700         }
2701
2702         return false;
2703 }
2704 #endif
2705 static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
2706 {
2707         GSupplicantInterface *interface = bss->interface;
2708         GSupplicantNetwork *network;
2709         char *group;
2710         bool is_new_network;
2711
2712         group = create_group(bss);
2713         SUPPLICANT_DBG("New group created: %s", group);
2714
2715         if (!group)
2716                 return -ENOMEM;
2717
2718         network = g_hash_table_lookup(interface->network_table, group);
2719         if (network) {
2720                 g_free(group);
2721                 SUPPLICANT_DBG("Network %s already exist", network->name);
2722                 is_new_network = false;
2723
2724                 goto done;
2725         }
2726
2727         is_new_network = true;
2728
2729         network = g_try_new0(GSupplicantNetwork, 1);
2730         if (!network) {
2731                 g_free(group);
2732                 return -ENOMEM;
2733         }
2734
2735         network->interface = interface;
2736         if (!network->path)
2737                 network->path = g_strdup(bss->path);
2738         network->group = group;
2739         network->name = create_name(bss->ssid, bss->ssid_len);
2740         network->mode = bss->mode;
2741         network->security = bss->security;
2742         network->keymgmt = bss->keymgmt;
2743         network->ssid_len = bss->ssid_len;
2744         memcpy(network->ssid, bss->ssid, bss->ssid_len);
2745         network->signal = bss->signal;
2746         network->frequency = bss->frequency;
2747         network->best_bss = bss;
2748
2749         if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
2750                 network->wps = TRUE;
2751                 network->wps_capabilities = bss->wps_capabilities;
2752         }
2753
2754 #if defined TIZEN_EXT
2755         network->owe_transition_mode = bss->owe_transition_mode;
2756         network->privacy = bss->privacy;
2757         memcpy(network->transition_mode_ssid, bss->transition_mode_ssid, bss->transition_mode_ssid_len);
2758         memcpy(network->transition_mode_bssid, bss->transition_mode_bssid, WIFI_BSSID_LEN_MAX);
2759
2760         network->keymgmt = bss->keymgmt;
2761
2762         if (g_slist_length(bss->vsie_list) > 0) {
2763                 GSList *list = NULL;
2764                 unsigned char *vsie = NULL;
2765                 for (list = bss->vsie_list; list; list = list->next) {
2766                         unsigned char *ie = (unsigned char *)list->data;
2767                         vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1)
2768
2769                         if (vsie) {
2770                                 memcpy(vsie, ie, ie[1]+2);
2771                                 network->vsie_list = g_slist_append(network->vsie_list, vsie);
2772                         } else
2773                                 SUPPLICANT_DBG("Failed to allocate memory.");
2774                 }
2775         }
2776
2777         network->isHS20AP = bss->hs20;
2778         memcpy(network->country_code, bss->country_code, COUNTRY_CODE_LENGTH);
2779         network->phy_mode = bss->phy_mode;
2780 #endif
2781
2782         SUPPLICANT_DBG("New network %s created", network->name);
2783
2784         network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
2785                                                         NULL, remove_bss);
2786
2787         network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
2788                                                         g_free, g_free);
2789
2790 #if defined TIZEN_EXT
2791         network->assoc_reject_table = g_hash_table_new_full(g_str_hash, g_str_equal,
2792                                                         NULL, remove_assoc_data);
2793 #endif
2794
2795         g_hash_table_replace(interface->network_table,
2796                                                 network->group, network);
2797
2798         callback_network_added(network);
2799
2800 done:
2801         /* We update network's WPS properties if only bss provides WPS. */
2802         if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
2803                 network->wps = TRUE;
2804                 network->wps_capabilities = bss->wps_capabilities;
2805
2806                 if (!is_new_network)
2807                         callback_network_changed(network, "WPSCapabilities");
2808         }
2809
2810         /*
2811          * Do not change best BSS if we are connected. It will be done through
2812          * CurrentBSS property in case of misalignment with wpa_s or roaming.
2813          */
2814 #if defined TIZEN_EXT
2815         if (network != interface->current_network) {
2816                 if (update_best_bss(network, bss, network->best_bss))
2817                         callback_network_changed(network, "Signal");
2818         }
2819 #else
2820         if (network != interface->current_network &&
2821                                 bss->signal > network->signal) {
2822                 network->signal = bss->signal;
2823                 network->best_bss = bss;
2824                 callback_network_changed(network, "Signal");
2825         }
2826 #endif
2827
2828         g_hash_table_replace(interface->bss_mapping, bss->path, network);
2829         g_hash_table_replace(network->bss_table, bss->path, bss);
2830
2831         g_hash_table_replace(bss_mapping, bss->path, interface);
2832
2833         return 0;
2834 }
2835
2836 static void bss_rates(DBusMessageIter *iter, void *user_data)
2837 {
2838         struct g_supplicant_bss *bss = user_data;
2839         dbus_uint32_t rate = 0;
2840
2841         dbus_message_iter_get_basic(iter, &rate);
2842         if (rate == 0)
2843                 return;
2844
2845         if (rate > bss->maxrate)
2846                 bss->maxrate = rate;
2847 }
2848
2849 static void bss_keymgmt(DBusMessageIter *iter, void *user_data)
2850 {
2851         unsigned int *keymgmt = user_data;
2852         const char *str = NULL;
2853         int i;
2854
2855         dbus_message_iter_get_basic(iter, &str);
2856         if (!str)
2857                 return;
2858
2859         for (i = 0; keymgmt_map[i].str; i++)
2860                 if (strcmp(str, keymgmt_map[i].str) == 0) {
2861                         SUPPLICANT_DBG("Keymgmt: %s", str);
2862                         *keymgmt |= keymgmt_map[i].val;
2863                         break;
2864                 }
2865 }
2866
2867 static void bss_group(DBusMessageIter *iter, void *user_data)
2868 {
2869         unsigned int *group = user_data;
2870         const char *str = NULL;
2871         int i;
2872
2873         dbus_message_iter_get_basic(iter, &str);
2874         if (!str)
2875                 return;
2876
2877         for (i = 0; group_map[i].str; i++)
2878                 if (strcmp(str, group_map[i].str) == 0) {
2879                         SUPPLICANT_DBG("Group: %s", str);
2880                         *group |= group_map[i].val;
2881                         break;
2882                 }
2883 }
2884
2885 static void bss_pairwise(DBusMessageIter *iter, void *user_data)
2886 {
2887         unsigned int *pairwise = user_data;
2888         const char *str = NULL;
2889         int i;
2890
2891         dbus_message_iter_get_basic(iter, &str);
2892         if (!str)
2893                 return;
2894
2895         for (i = 0; pairwise_map[i].str; i++)
2896                 if (strcmp(str, pairwise_map[i].str) == 0) {
2897                         SUPPLICANT_DBG("Pairwise: %s", str);
2898                         *pairwise |= pairwise_map[i].val;
2899                         break;
2900                 }
2901 }
2902
2903 static void bss_wpa(const char *key, DBusMessageIter *iter,
2904                         void *user_data)
2905 {
2906         struct g_supplicant_bss *bss = user_data;
2907         unsigned int value = 0;
2908
2909         SUPPLICANT_DBG("Key: %s", key);
2910
2911         if (g_strcmp0(key, "KeyMgmt") == 0) {
2912                 supplicant_dbus_array_foreach(iter, bss_keymgmt, &value);
2913
2914                 if (bss->rsn_selected)
2915                         bss->rsn_keymgmt = value;
2916                 else
2917                         bss->wpa_keymgmt = value;
2918         } else if (g_strcmp0(key, "Group") == 0) {
2919                 supplicant_dbus_array_foreach(iter, bss_group, &value);
2920
2921                 if (bss->rsn_selected)
2922                         bss->rsn_group = value;
2923                 else
2924                         bss->wpa_group = value;
2925         } else if (g_strcmp0(key, "Pairwise") == 0) {
2926                 supplicant_dbus_array_foreach(iter, bss_pairwise, &value);
2927
2928                 if (bss->rsn_selected)
2929                         bss->rsn_pairwise = value;
2930                 else
2931                         bss->wpa_pairwise = value;
2932         }
2933 }
2934
2935 static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size,
2936                                                         unsigned int type)
2937 {
2938         unsigned int len = 0;
2939
2940         while (len + 4 < ie_size) {
2941                 unsigned int hi = ie[len];
2942                 unsigned int lo = ie[len + 1];
2943                 unsigned int tmp_type = (hi << 8) + lo;
2944                 unsigned int v_len = 0;
2945
2946                 /* hi and lo are used to recreate an unsigned int
2947                  * based on 2 8bits length unsigned int. */
2948
2949                 hi = ie[len + 2];
2950                 lo = ie[len + 3];
2951                 v_len = (hi << 8) + lo;
2952
2953                 if (tmp_type == type) {
2954                         unsigned int ret_value = 0;
2955                         unsigned char *value = (unsigned char *)&ret_value;
2956
2957                         SUPPLICANT_DBG("IE: match type 0x%x", type);
2958
2959                         /* Verifying length relevance */
2960                         if (v_len > sizeof(unsigned int) ||
2961                                 len + 4 + v_len > ie_size)
2962                                 break;
2963
2964                         memcpy(value, ie + len + 4, v_len);
2965
2966                         SUPPLICANT_DBG("returning 0x%x", ret_value);
2967                         return ret_value;
2968                 }
2969
2970                 len += v_len + 4;
2971         }
2972
2973         SUPPLICANT_DBG("returning 0");
2974         return 0;
2975 }
2976
2977 #if defined TIZEN_EXT
2978 static void get_bss_phy_mode(unsigned int max_rate,
2979                 unsigned int max_ext_rate, bool ht, bool vht, void *data)
2980 {
2981         struct g_supplicant_bss *bss = data;
2982         unsigned int freq = bss->frequency;
2983
2984         /* Following conditions are used to determine
2985          * IEEE 802.11 Protocol Modes:-
2986          *
2987          * 1. If “Supported rates” is only till 11 Mbps,
2988          *    and frequency is in 2.4GHz band, then protocol is 11B.
2989          * 2. If “Supported rates” is till 54Mbps or
2990          *    “Extended supported rates” are present,
2991          *    and frequency is in 2.4GHz band, then protocol is 11G.
2992          * 3. If “Supported rates” is only till 54 Mbps,
2993          *    frequency is in 5GHz band , then protocol is 11A.
2994          * 4. If “HT capabilities” is supported , then protocol is 11N.
2995          * 5. If “HT capabilities” & “VHT” is supported and
2996          *    frequency is in 5 GHz band, then protocol is 11AC.
2997          * */
2998
2999         if (freq >= 2412 && freq <= 2484) { /* 2.4 Ghz Band */
3000                 if (max_rate <= 11 && max_ext_rate <= 0 && !ht)
3001                         bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211B;
3002                 else if ((max_rate <= 54 || max_ext_rate > 0) && !ht)
3003                         bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BG;
3004                 else if ((max_rate >= 54 || max_ext_rate > 0) && ht)
3005                         bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BGN;
3006                 else
3007                         bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
3008         } else if (freq >= 5180 && freq <= 5825) { /* 5 Ghz Band */
3009                 if (max_rate <= 54 && !ht)
3010                         bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211A;
3011                 else if ((max_rate >= 54 || max_ext_rate > 0) && ht && !vht)
3012                         bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211AN;
3013                 else if ((max_rate >= 54 || max_ext_rate > 0) && ht && vht)
3014                         bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211ANAC;
3015                 else
3016                         bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
3017         }
3018 }
3019 #endif
3020
3021 static void bss_process_ies(DBusMessageIter *iter, void *user_data)
3022 {
3023         struct g_supplicant_bss *bss = user_data;
3024         const unsigned char WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
3025         unsigned char *ie, *ie_end;
3026         DBusMessageIter array;
3027         unsigned int value;
3028         int ie_len;
3029 #if defined TIZEN_EXT
3030         const unsigned char OWE_WFA_OUI[] = { 0x50, 0x6f, 0x9a, 0x1c };
3031         int r_len, j;
3032         unsigned char *rates = NULL;
3033         unsigned char *ext_rates = NULL;
3034         unsigned int max_rate = 0;
3035         unsigned int max_ext_rate = 0;
3036         unsigned int offset = 0;
3037         bool ht = false;
3038         bool vht = false;
3039 #endif
3040
3041 #define WMM_WPA1_WPS_INFO 221
3042 #define WPS_INFO_MIN_LEN  6
3043 #define WPS_VERSION_TLV   0x104A
3044 #define WPS_STATE_TLV     0x1044
3045 #define WPS_METHODS_TLV   0x1012
3046 #define WPS_REGISTRAR_TLV 0x1041
3047 #define WPS_VERSION       0x10
3048 #define WPS_PBC           0x04
3049 #define WPS_PIN           0x00
3050 #define WPS_CONFIGURED    0x02
3051 #if defined TIZEN_EXT
3052 #define VENDOR_SPECIFIC_INFO 0xDD
3053 #define WLAN_EID_COUNTRY 7
3054 #define WLAN_EID_RSN_INFO 48
3055 #define RSN_CAPABILITY_MFP_REQ (1 << 6)
3056 #endif
3057
3058         dbus_message_iter_recurse(iter, &array);
3059         dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
3060
3061         if (!ie || ie_len < 2)
3062                 return;
3063
3064         bss->wps_capabilities = 0;
3065         bss->keymgmt = 0;
3066
3067         for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
3068                                                         ie += ie[1] + 2) {
3069 #if defined TIZEN_EXT
3070                 unsigned char *vsie;
3071                 int vsie_len = 0;
3072
3073                 if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, OWE_WFA_OUI, sizeof(OWE_WFA_OUI)) == 0) {
3074                         SUPPLICANT_DBG("IE: match vendor specific data : OWE Transition Mode");
3075
3076 /*
3077                 Tag: Vendor Specific: Wi-Fi Alliance: OWE Transition Mode
3078                         Tag Number: Vendor Specific (221)    -> ie[0]
3079                         Tag length: 26                       -> ie[1]
3080                         OUI: 50:6f:9a (Wi-Fi Alliance)       -> ie[2]
3081                         Vendor Specific OUI Type: 28         -> ie[5]
3082                         BSSID: 92:fd:f0:20:2b:09             -> ie[6]
3083                         SSID length: 15                      -> ie[12]
3084                         SSID: Wi-Fi-5.2.3-owe                -> ie[13]
3085
3086 0000   dd 1a 50 6f 9a 1c 92 fd f0 20 2b 09 0f 57 69 2d   ..Po..... +..Wi-
3087 0010   46 69 2d 35 2e 32 2e 33 2d 6f 77 65               Fi-5.2.3-owe
3088
3089 */
3090                         bss->owe_transition_mode = TRUE;
3091                         if (ie[1] >= 11) { // Tag length is at least up to ssid length position.
3092                                 memcpy(bss->transition_mode_bssid, ie+6, WIFI_BSSID_LEN_MAX);
3093                                 if (ie[12] > 0 && ie[12] < 32) {
3094                                         memcpy(bss->transition_mode_ssid, ie+13, ie[12]);
3095                                         bss->transition_mode_ssid_len = ie[12];
3096                                 } else
3097                                         bss->transition_mode_ssid_len = 0;
3098                         } else
3099                                 bss->owe_transition_mode = FALSE;
3100                         continue;
3101                 }
3102
3103                 if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) {
3104
3105                         if (!simplified_log)
3106                                 SUPPLICANT_DBG("IE: match vendor specific data");
3107
3108                         vsie_len = ie[1]+2;     // tag number size(1), tag length size(1)
3109                         vsie = (unsigned char *)g_try_malloc0(vsie_len);
3110
3111                         if (vsie) {
3112                                 memcpy(vsie, ie, vsie_len);
3113                                 bss->vsie_list = g_slist_append(bss->vsie_list, vsie);
3114                         } else
3115                                 SUPPLICANT_DBG("Failed to allocate memory");
3116                         continue;
3117                 }
3118
3119                 if (ie[0] == WLAN_EID_COUNTRY && ie[1] >= 2) {
3120                         /* Add country code only if it is a valid alphabet */
3121                         if (ie[2] >= 65 && ie[2] <= 90 && ie[3] >= 65 && ie[3] <= 90) {
3122                                 memcpy(bss->country_code, ie+2, COUNTRY_CODE_LENGTH);
3123                                 continue;
3124                         }
3125                 }
3126
3127                 if (ie[0] == WLAN_EID_HT_CAP && ie[1]) {
3128                         ht = true;
3129                         continue;
3130                 }
3131
3132                 if (ie[0] == WLAN_EID_VHT_CAP && ie[1]) {
3133                         vht = true;
3134                         continue;
3135                 }
3136
3137                 if (ie[0] == WLAN_EID_SUPP_RATES && ie[1]) {
3138                         r_len = ie[1];
3139                         rates = g_malloc0(r_len);
3140                         if (!rates)
3141                                 continue;
3142
3143                         for (j = 0; ie && j < r_len; j++) {
3144                                 rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
3145                                 if (max_rate < rates[j])
3146                                         max_rate = rates[j];
3147                         }
3148                         continue;
3149                 }
3150
3151                 if (ie[0] == WLAN_EID_EXT_SUPP_RATES && ie[1] > 0) {
3152                         r_len = ie[1];
3153                         ext_rates = g_malloc0(r_len);
3154                         if (!ext_rates)
3155                                 continue;
3156
3157                         for (j = 0; ie && j < r_len; j++) {
3158                                 ext_rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
3159                                 if (max_ext_rate < ext_rates[j])
3160                                         max_ext_rate = ext_rates[j];
3161                         }
3162                         continue;
3163                 }
3164
3165                 if (ie[0] == WLAN_EID_RSN_INFO && ie[1] >= 20) {
3166                         r_len = ie[1];
3167                         offset = 10 + ie[8] * 4;
3168                         offset += ie[offset] * 4 + 2;
3169
3170                         if (offset <= r_len + 1 &&
3171                                         (ie[offset] & RSN_CAPABILITY_MFP_REQ) != 0)
3172                                 bss->pmf_required = TRUE;
3173
3174                         continue;
3175                 }
3176 #endif
3177                 if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
3178                         memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
3179                         continue;
3180
3181                 SUPPLICANT_DBG("IE: match WPS_OUI");
3182
3183                 value = get_tlv(&ie[6], ie[1], WPS_STATE_TLV);
3184                 if (get_tlv(&ie[6], ie[1], WPS_VERSION_TLV) == WPS_VERSION &&
3185                                                                 value != 0) {
3186                         bss->keymgmt |= G_SUPPLICANT_KEYMGMT_WPS;
3187
3188                         if (value == WPS_CONFIGURED)
3189                                 bss->wps_capabilities |=
3190                                         G_SUPPLICANT_WPS_CONFIGURED;
3191                 }
3192
3193                 value = get_tlv(&ie[6], ie[1], WPS_METHODS_TLV);
3194                 if (value != 0) {
3195                         if (GUINT16_FROM_BE(value) == WPS_PBC)
3196                                 bss->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
3197                         if (GUINT16_FROM_BE(value) == WPS_PIN)
3198                                 bss->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
3199                 } else
3200                         bss->wps_capabilities |=
3201                                 G_SUPPLICANT_WPS_PBC | G_SUPPLICANT_WPS_PIN;
3202
3203                 /* If the AP sends this it means it's advertizing
3204                  * as a registrar and the WPS process is launched
3205                  * on its side */
3206                 if (get_tlv(&ie[6], ie[1], WPS_REGISTRAR_TLV) != 0)
3207                         bss->wps_capabilities |= G_SUPPLICANT_WPS_REGISTRAR;
3208
3209                 SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
3210         }
3211 #ifdef TIZEN_EXT
3212         get_bss_phy_mode(max_rate, max_ext_rate, ht, vht, user_data);
3213         if (rates)
3214                 g_free(rates);
3215         if (ext_rates)
3216                 g_free(ext_rates);
3217 #endif
3218 }
3219
3220 static void bss_compute_security(struct g_supplicant_bss *bss)
3221 {
3222         /*
3223          * Combining RSN and WPA keymgmt
3224          * We combine it since parsing IEs might have set something for WPS. */
3225         bss->keymgmt |= bss->rsn_keymgmt | bss->wpa_keymgmt;
3226
3227         bss->ieee8021x = FALSE;
3228         bss->psk = FALSE;
3229 #if defined TIZEN_EXT
3230         bss->ft_ieee8021x = FALSE;
3231         bss->ft_psk = FALSE;
3232 #endif
3233
3234 #if defined TIZEN_EXT
3235         if (bss->keymgmt &
3236                         (G_SUPPLICANT_KEYMGMT_WPA_EAP |
3237                                 G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
3238                 bss->ieee8021x = TRUE;
3239         else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
3240                 bss->ft_ieee8021x = TRUE;
3241 #else
3242         if (bss->keymgmt &
3243                         (G_SUPPLICANT_KEYMGMT_WPA_EAP |
3244                                 G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
3245                                 G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
3246                 bss->ieee8021x = TRUE;
3247 #endif
3248
3249 #if defined TIZEN_EXT
3250         if (bss->keymgmt &
3251                         G_SUPPLICANT_KEYMGMT_WPA_PSK_256) {
3252                 bss->psk_sha256 = TRUE;
3253         }
3254
3255         if (bss->keymgmt &
3256                         (G_SUPPLICANT_KEYMGMT_WPA_PSK |
3257                                 G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
3258                 bss->psk = TRUE;
3259         else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
3260                 bss->ft_psk = TRUE;
3261 #else
3262         if (bss->keymgmt &
3263                         (G_SUPPLICANT_KEYMGMT_WPA_PSK |
3264                                 G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
3265                                 G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
3266                 bss->psk = TRUE;
3267 #endif
3268
3269 #if defined TIZEN_EXT
3270         if (bss->keymgmt &
3271                         (G_SUPPLICANT_KEYMGMT_SAE |
3272                                 G_SUPPLICANT_KEYMGMT_FT_SAE))
3273                 bss->sae = TRUE;
3274         if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_OWE)
3275                 bss->owe = TRUE;
3276         if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_DPP)
3277                 bss->dpp = TRUE;
3278 #endif
3279
3280         if (bss->ieee8021x)
3281                 bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
3282 #if defined TIZEN_EXT
3283         else if (bss->ft_ieee8021x)
3284                 bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
3285         else if (bss->sae)
3286                 bss->security = G_SUPPLICANT_SECURITY_SAE;
3287         else if (bss->psk_sha256)
3288                 bss->security = G_SUPPLICANT_SECURITY_PSK_SHA256;
3289 #endif
3290         else if (bss->psk)
3291                 bss->security = G_SUPPLICANT_SECURITY_PSK;
3292 #if defined TIZEN_EXT
3293         else if (bss->ft_psk)
3294                 bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
3295         else if (bss->owe || bss->owe_transition_mode)
3296                 bss->security = G_SUPPLICANT_SECURITY_OWE;
3297         else if (bss->dpp)
3298                 bss->security = G_SUPPLICANT_SECURITY_DPP;
3299 #endif
3300         else if (bss->privacy)
3301                 bss->security = G_SUPPLICANT_SECURITY_WEP;
3302         else
3303                 bss->security = G_SUPPLICANT_SECURITY_NONE;
3304 }
3305
3306
3307 static void bss_property(const char *key, DBusMessageIter *iter,
3308                                                         void *user_data)
3309 {
3310         struct g_supplicant_bss *bss = user_data;
3311
3312         if (!bss->interface)
3313                 return;
3314 #if defined TIZEN_EXT
3315         if (!simplified_log)
3316 #endif
3317         SUPPLICANT_DBG("key %s", key);
3318
3319         if (!key)
3320                 return;
3321
3322         if (g_strcmp0(key, "BSSID") == 0) {
3323                 DBusMessageIter array;
3324                 unsigned char *addr;
3325                 int addr_len;
3326
3327                 dbus_message_iter_recurse(iter, &array);
3328                 dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
3329
3330                 if (addr_len == 6)
3331                         memcpy(bss->bssid, addr, addr_len);
3332         } else if (g_strcmp0(key, "SSID") == 0) {
3333                 DBusMessageIter array;
3334                 unsigned char *ssid;
3335                 int ssid_len;
3336
3337                 dbus_message_iter_recurse(iter, &array);
3338                 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
3339
3340                 if (ssid_len > 0 && ssid_len < 33) {
3341                         memcpy(bss->ssid, ssid, ssid_len);
3342                         bss->ssid_len = ssid_len;
3343                 } else {
3344                         memset(bss->ssid, 0, sizeof(bss->ssid));
3345                         bss->ssid_len = 0;
3346                 }
3347         } else if (g_strcmp0(key, "Capabilities") == 0) {
3348                 dbus_uint16_t capabilities = 0x0000;
3349
3350                 dbus_message_iter_get_basic(iter, &capabilities);
3351
3352                 if (capabilities & IEEE80211_CAP_ESS)
3353                         bss->mode = G_SUPPLICANT_MODE_INFRA;
3354                 else if (capabilities & IEEE80211_CAP_IBSS)
3355                         bss->mode = G_SUPPLICANT_MODE_IBSS;
3356
3357                 if (capabilities & IEEE80211_CAP_PRIVACY)
3358                         bss->privacy = TRUE;
3359         } else if (g_strcmp0(key, "Mode") == 0) {
3360                 const char *mode = NULL;
3361
3362                 dbus_message_iter_get_basic(iter, &mode);
3363                 bss->mode = string2mode(mode);
3364         } else if (g_strcmp0(key, "Frequency") == 0) {
3365                 dbus_uint16_t frequency = 0;
3366
3367                 dbus_message_iter_get_basic(iter, &frequency);
3368                 bss->frequency = frequency;
3369         } else if (g_strcmp0(key, "Signal") == 0) {
3370                 dbus_int16_t signal = 0;
3371
3372                 dbus_message_iter_get_basic(iter, &signal);
3373
3374                 bss->signal = signal;
3375                 if (!bss->signal)
3376                         bss->signal = BSS_UNKNOWN_STRENGTH;
3377
3378         } else if (g_strcmp0(key, "Level") == 0) {
3379                 dbus_int32_t level = 0;
3380
3381                 dbus_message_iter_get_basic(iter, &level);
3382         } else if (g_strcmp0(key, "Rates") == 0) {
3383                 supplicant_dbus_array_foreach(iter, bss_rates, bss);
3384         } else if (g_strcmp0(key, "MaxRate") == 0) {
3385                 dbus_uint32_t maxrate = 0;
3386
3387                 dbus_message_iter_get_basic(iter, &maxrate);
3388                 if (maxrate != 0)
3389                         bss->maxrate = maxrate;
3390         } else if (g_strcmp0(key, "Privacy") == 0) {
3391                 dbus_bool_t privacy = FALSE;
3392
3393                 dbus_message_iter_get_basic(iter, &privacy);
3394                 bss->privacy = privacy;
3395         } else if (g_strcmp0(key, "RSN") == 0) {
3396                 bss->rsn_selected = TRUE;
3397
3398                 supplicant_dbus_property_foreach(iter, bss_wpa, bss);
3399         } else if (g_strcmp0(key, "WPA") == 0) {
3400                 bss->rsn_selected = FALSE;
3401
3402                 supplicant_dbus_property_foreach(iter, bss_wpa, bss);
3403 #if defined TIZEN_EXT
3404         } else if (g_strcmp0(key, "HS20") == 0) {
3405                 dbus_bool_t hs20 = FALSE;
3406                 dbus_message_iter_get_basic(iter, &hs20);
3407                 bss->hs20 = hs20;
3408         } else if (g_strcmp0(key, "SNR") == 0) {
3409                 dbus_int16_t snr = 0;
3410
3411                 dbus_message_iter_get_basic(iter, &snr);
3412                 bss->snr = snr;
3413         } else if (g_strcmp0(key, "EstThroughput") == 0) {
3414                 dbus_uint32_t est_throughput = 0;
3415
3416                 dbus_message_iter_get_basic(iter, &est_throughput);
3417                 if (est_throughput != 0)
3418                         bss->est_throughput = est_throughput;
3419 #endif
3420         } else if (g_strcmp0(key, "IEs") == 0)
3421                 bss_process_ies(iter, bss);
3422         else
3423                 SUPPLICANT_DBG("key %s type %c",
3424                                 key, dbus_message_iter_get_arg_type(iter));
3425 }
3426
3427 static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
3428                                                         void *user_data)
3429 {
3430         GSupplicantInterface *interface = user_data;
3431         GSupplicantNetwork *network;
3432         struct g_supplicant_bss *bss;
3433         const char *path = NULL;
3434 #if defined TIZEN_EXT
3435         if (!simplified_log)
3436 #endif
3437         SUPPLICANT_DBG("");
3438
3439         dbus_message_iter_get_basic(iter, &path);
3440         if (!path)
3441                 return NULL;
3442
3443         if (g_strcmp0(path, "/") == 0)
3444                 return NULL;
3445 #if defined TIZEN_EXT
3446         if (!simplified_log)
3447 #endif
3448         SUPPLICANT_DBG("%s", path);
3449
3450         network = g_hash_table_lookup(interface->bss_mapping, path);
3451         if (network) {
3452                 bss = g_hash_table_lookup(network->bss_table, path);
3453                 if (bss)
3454                         return NULL;
3455         }
3456
3457         bss = g_try_new0(struct g_supplicant_bss, 1);
3458         if (!bss)
3459                 return NULL;
3460
3461         bss->interface = interface;
3462         bss->path = g_strdup(path);
3463         bss->signal = BSS_UNKNOWN_STRENGTH;
3464
3465         return bss;
3466 }
3467
3468 static void interface_bss_added_with_keys(DBusMessageIter *iter,
3469                                                 void *user_data)
3470 {
3471         struct g_supplicant_bss *bss;
3472 #if defined TIZEN_EXT
3473         if (!simplified_log)
3474 #endif
3475         SUPPLICANT_DBG("");
3476
3477         bss = interface_bss_added(iter, user_data);
3478         if (!bss)
3479                 return;
3480
3481         dbus_message_iter_next(iter);
3482
3483         if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID)
3484 #if defined TIZEN_EXT
3485         {
3486                 g_free(bss->path);
3487                 g_free(bss);
3488                 return;
3489         }
3490 #else
3491                 return;
3492 #endif
3493
3494         supplicant_dbus_property_foreach(iter, bss_property, bss);
3495
3496         bss_compute_security(bss);
3497         if (add_or_replace_bss_to_network(bss) < 0)
3498                 SUPPLICANT_DBG("add_or_replace_bss_to_network failed");
3499 }
3500
3501 static void interface_bss_added_without_keys(DBusMessageIter *iter,
3502                                                 void *user_data)
3503 {
3504         struct g_supplicant_bss *bss;
3505 #if defined TIZEN_EXT
3506         if (!simplified_log)
3507 #endif
3508         SUPPLICANT_DBG("");
3509
3510         bss = interface_bss_added(iter, user_data);
3511         if (!bss)
3512                 return;
3513
3514         supplicant_dbus_property_get_all(bss->path,
3515                                         SUPPLICANT_INTERFACE ".BSS",
3516                                         bss_property, bss, bss);
3517
3518         bss_compute_security(bss);
3519         if (add_or_replace_bss_to_network(bss) < 0)
3520                         SUPPLICANT_DBG("add_or_replace_bss_to_network failed");
3521 }
3522
3523 static void update_signal(gpointer key, gpointer value,
3524                                                 gpointer user_data)
3525 {
3526         struct g_supplicant_bss *bss = value;
3527         GSupplicantNetwork *network = user_data;
3528
3529 #if defined TIZEN_EXT
3530         if (!network->best_bss || (network->best_bss == bss)) {
3531                 if (bss->signal > network->signal) {
3532                         network->signal = bss->signal;
3533                         network->best_bss = bss;
3534                 }
3535                 return;
3536         }
3537
3538         update_best_bss(network, bss, network->best_bss);
3539 #else
3540         if (bss->signal > network->signal) {
3541                 network->signal = bss->signal;
3542                 network->best_bss = bss;
3543         }
3544 #endif
3545 }
3546
3547 static void update_network_signal(GSupplicantNetwork *network)
3548 {
3549         if (g_hash_table_size(network->bss_table) <= 1 && network->best_bss)
3550                 return;
3551
3552         g_hash_table_foreach(network->bss_table,
3553                                 update_signal, network);
3554
3555         SUPPLICANT_DBG("New network signal %d", network->signal);
3556 }
3557
3558 #if defined TIZEN_EXT_INS
3559 static gboolean last_connected_timeout(gpointer data)
3560 {
3561         GSupplicantInterface *interface = data;
3562         GSupplicantNetwork *current_network = interface->current_network;
3563
3564         SUPPLICANT_DBG("Timeout last connected bss");
3565
3566         if (current_network && current_network->best_bss) {
3567                 if (compare_bssid(current_network->best_bss->bssid, interface->connected_bssid)) {
3568                         g_supplicant_network_set_last_connected_bssid(current_network, interface->connected_bssid);
3569                         callback_network_changed(current_network, "LastConnectedBSSID");
3570                 }
3571         }
3572
3573         last_connected_bss_timeout = 0;
3574         return FALSE;
3575 }
3576
3577 static void add_timer_for_last_connected(GSupplicantInterface *interface)
3578 {
3579         GSupplicantNetwork *current_network = interface->current_network;
3580
3581         if (interface->state == G_SUPPLICANT_STATE_COMPLETED) {
3582                 if (current_network) {
3583                         struct g_supplicant_bss *best_bss = current_network->best_bss;
3584
3585                         memcpy(interface->connected_bssid, best_bss->bssid, WIFI_BSSID_LEN_MAX);
3586
3587                         if (last_connected_bss_timeout)
3588                                 g_source_remove(last_connected_bss_timeout);
3589
3590                         last_connected_bss_timeout = g_timeout_add_seconds(LAST_CONNECTED_TIMEOUT,
3591                                 last_connected_timeout, interface);
3592
3593                         SUPPLICANT_DBG("Add timer for last connected bssid [" MACSTR "]",
3594                                         MAC2STR(best_bss->bssid));
3595                 }
3596         }
3597 }
3598
3599 static void remove_timer_for_last_connected(GSupplicantInterface *interface)
3600 {
3601         if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED) {
3602                 if (last_connected_bss_timeout != 0) {
3603                         g_source_remove(last_connected_bss_timeout);
3604                         last_connected_bss_timeout = 0;
3605                         SUPPLICANT_DBG("Remove timer for last connected bss");
3606                 }
3607         }
3608 }
3609 #endif /* defined TIZEN_EXT_INS */
3610
3611 static void interface_current_bss(GSupplicantInterface *interface,
3612                                                 DBusMessageIter *iter)
3613 {
3614         GSupplicantNetwork *network;
3615         struct g_supplicant_bss *bss;
3616         const char *path;
3617 #if defined TIZEN_EXT
3618         char bssid_buff1[WIFI_BSSID_STR_LEN] = {0,};
3619         char bssid_buff2[WIFI_BSSID_STR_LEN] = {0,};
3620         char *bssid_str1 = bssid_buff1;
3621         char *bssid_str2 = bssid_buff2;
3622         gboolean update = FALSE;
3623 #endif
3624
3625         dbus_message_iter_get_basic(iter, &path);
3626         if (g_strcmp0(path, "/") == 0) {
3627                 interface->current_network = NULL;
3628                 return;
3629         }
3630
3631         interface_bss_added_without_keys(iter, interface);
3632
3633         network = g_hash_table_lookup(interface->bss_mapping, path);
3634         if (!network)
3635                 return;
3636
3637         bss = g_hash_table_lookup(network->bss_table, path);
3638         if (!bss)
3639                 return;
3640
3641         interface->current_network = network;
3642 #if defined TIZEN_EXT
3643         snprintf(bssid_str1, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bss->bssid));
3644         snprintf(bssid_str2, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(network->best_bss->bssid));
3645
3646         SUPPLICANT_DBG("current network [%p], Passed bss %s, best bss %s",
3647                         interface->current_network, bssid_str1, bssid_str2);
3648
3649         if (network->frequency != bss->frequency) {
3650                 network->frequency = bss->frequency;
3651                 update = TRUE;
3652         }
3653 #endif
3654
3655         if (bss != network->best_bss) {
3656                 /*
3657                  * This is the case where either wpa_s got associated
3658                  * to a BSS different than the one ConnMan considers
3659                  * the best, or we are roaming.
3660                  */
3661                 SUPPLICANT_DBG("Update best BSS for %s", network->name);
3662
3663                 network->best_bss = bss;
3664
3665                 if (network->signal != bss->signal) {
3666                         SUPPLICANT_DBG("New network signal %d dBm",
3667                                                 bss->signal);
3668
3669                         network->signal = bss->signal;
3670                         callback_network_changed(network, "Signal");
3671 #if defined TIZEN_EXT
3672                         update = FALSE;
3673                 } else {
3674                         update = TRUE;
3675 #endif
3676                 }
3677         }
3678
3679 #if defined TIZEN_EXT
3680         if (update)
3681                 callback_network_changed(network, "");
3682 #endif
3683
3684         /*
3685          * wpa_s could notify about CurrentBSS in any state once
3686          * it got associated. It is not sure such notification will
3687          * arrive together with transition to ASSOCIATED state.
3688          * In fact, for networks with security WEP or OPEN, it
3689          * always arrives together with transition to COMPLETED.
3690          */
3691         switch (interface->state) {
3692         case G_SUPPLICANT_STATE_UNKNOWN:
3693         case G_SUPPLICANT_STATE_DISABLED:
3694         case G_SUPPLICANT_STATE_DISCONNECTED:
3695         case G_SUPPLICANT_STATE_INACTIVE:
3696         case G_SUPPLICANT_STATE_SCANNING:
3697         case G_SUPPLICANT_STATE_AUTHENTICATING:
3698         case G_SUPPLICANT_STATE_ASSOCIATING:
3699                 return;
3700         case G_SUPPLICANT_STATE_ASSOCIATED:
3701         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
3702         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
3703         case G_SUPPLICANT_STATE_COMPLETED:
3704                 callback_network_associated(network);
3705 #if defined TIZEN_EXT_INS
3706                 add_timer_for_last_connected(interface);
3707 #endif
3708                 break;
3709         }
3710 }
3711
3712 static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
3713 {
3714         GSupplicantInterface *interface = user_data;
3715         GSupplicantNetwork *network;
3716         struct g_supplicant_bss *bss = NULL;
3717         const char *path = NULL;
3718         bool is_current_network_bss = false;
3719
3720         dbus_message_iter_get_basic(iter, &path);
3721         if (!path)
3722                 return;
3723
3724         network = g_hash_table_lookup(interface->bss_mapping, path);
3725         if (!network)
3726                 return;
3727
3728         bss = g_hash_table_lookup(network->bss_table, path);
3729         if (network->best_bss == bss) {
3730                 network->best_bss = NULL;
3731                 network->signal = BSS_UNKNOWN_STRENGTH;
3732                 is_current_network_bss = true;
3733         }
3734
3735         g_hash_table_remove(bss_mapping, path);
3736
3737         g_hash_table_remove(interface->bss_mapping, path);
3738         g_hash_table_remove(network->bss_table, path);
3739
3740         update_network_signal(network);
3741
3742         if (g_hash_table_size(network->bss_table) == 0) {
3743                 g_hash_table_remove(interface->network_table, network->group);
3744         } else {
3745                 if (is_current_network_bss && network->best_bss)
3746 #if defined TIZEN_EXT
3747                         callback_network_changed(network, "CheckMultiBssidConnect");
3748 #else
3749                         callback_network_changed(network, "");
3750 #endif
3751         }
3752 }
3753
3754 static void set_config_methods(DBusMessageIter *iter, void *user_data)
3755 {
3756         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, user_data);
3757 }
3758
3759 static void wps_property(const char *key, DBusMessageIter *iter,
3760                                                         void *user_data)
3761 {
3762         GSupplicantInterface *interface = user_data;
3763
3764         if (!interface)
3765                 return;
3766 #if defined TIZEN_EXT
3767         if (!simplified_log)
3768 #endif
3769         SUPPLICANT_DBG("key: %s", key);
3770
3771         if (g_strcmp0(key, "ConfigMethods") == 0) {
3772                 const char *config_methods = "push_button", *str = NULL;
3773
3774                 dbus_message_iter_get_basic(iter, &str);
3775                 if (str && strlen(str) > 0) {
3776                         /* It was already set at wpa_s level, don't modify it. */
3777                         SUPPLICANT_DBG("%s", str);
3778                         return;
3779                 }
3780
3781                 supplicant_dbus_property_set(interface->path,
3782                         SUPPLICANT_INTERFACE ".Interface.WPS",
3783                         "ConfigMethods", DBUS_TYPE_STRING_AS_STRING,
3784                         set_config_methods, NULL, &config_methods, NULL);
3785
3786                 SUPPLICANT_DBG("No value. Set %s", config_methods);
3787         }
3788
3789 }
3790
3791 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
3792 void g_supplicant_replace_config_file(const char *ifname, const char *config_file)
3793 {
3794         if (!ifname)
3795                return;
3796
3797         if (!config_file)
3798                 return;
3799
3800         SUPPLICANT_DBG("New {%s, %s}", ifname, config_file);
3801         g_hash_table_replace(config_file_table,
3802                         g_strdup(ifname), g_strdup(config_file));
3803 }
3804 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
3805
3806 static void interface_property(const char *key, DBusMessageIter *iter,
3807                                                         void *user_data)
3808 {
3809         GSupplicantInterface *interface = user_data;
3810
3811         if (!interface)
3812                 return;
3813 #if defined TIZEN_EXT
3814         if (!simplified_log)
3815 #endif
3816         SUPPLICANT_DBG("%s", key);
3817
3818         if (!key) {
3819                 debug_strvalmap("KeyMgmt capability", keymgmt_map,
3820                                                 interface->keymgmt_capa);
3821                 debug_strvalmap("AuthAlg capability", authalg_capa_map,
3822                                                 interface->authalg_capa);
3823                 debug_strvalmap("Protocol capability", proto_capa_map,
3824                                                 interface->proto_capa);
3825                 debug_strvalmap("Pairwise capability", pairwise_map,
3826                                                 interface->pairwise_capa);
3827                 debug_strvalmap("Group capability", group_map,
3828                                                 interface->group_capa);
3829                 debug_strvalmap("Scan capability", scan_capa_map,
3830                                                 interface->scan_capa);
3831                 debug_strvalmap("Mode capability", mode_capa_map,
3832                                                 interface->mode_capa);
3833
3834                 supplicant_dbus_property_get_all(interface->path,
3835                                 SUPPLICANT_INTERFACE ".Interface.WPS",
3836                                 wps_property, interface, interface);
3837
3838                 if (interface->ready)
3839                         callback_interface_added(interface);
3840
3841                 return;
3842         }
3843
3844         if (g_strcmp0(key, "Capabilities") == 0) {
3845                 supplicant_dbus_property_foreach(iter, interface_capability,
3846                                                                 interface);
3847 #if !defined TIZEN_EXT
3848                 if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_P2P)
3849                         interface->p2p_support = true;
3850 #endif
3851 #if defined TIZEN_EXT_WIFI_MESH
3852                 if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_MESH)
3853                         interface->mesh_support = true;
3854 #endif
3855         } else if (g_strcmp0(key, "State") == 0) {
3856                 const char *str = NULL;
3857
3858                 dbus_message_iter_get_basic(iter, &str);
3859                 if (str)
3860                         if (string2state(str) != interface->state) {
3861                                 interface->state = string2state(str);
3862                                 callback_interface_state(interface);
3863                         }
3864 #if defined TIZEN_EXT_INS
3865                 switch (interface->state) {
3866                 case G_SUPPLICANT_STATE_COMPLETED:
3867                         add_timer_for_last_connected(interface);
3868                         break;
3869                 case G_SUPPLICANT_STATE_DISCONNECTED:
3870                         remove_timer_for_last_connected(interface);
3871                         break;
3872                 default:
3873                         break;
3874                 }
3875 #endif
3876                 if (interface->ap_create_in_progress) {
3877                         if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED)
3878                                 callback_ap_create_fail(interface);
3879
3880                         interface->ap_create_in_progress = false;
3881                 }
3882
3883                 if (interface->state == G_SUPPLICANT_STATE_DISABLED)
3884                         interface->ready = FALSE;
3885                 else
3886                         interface->ready = TRUE;
3887
3888                 SUPPLICANT_DBG("state %s (%d)", str, interface->state);
3889         } else if (g_strcmp0(key, "Scanning") == 0) {
3890                 dbus_bool_t scanning = FALSE;
3891
3892                 dbus_message_iter_get_basic(iter, &scanning);
3893                 interface->scanning = scanning;
3894
3895                 if (interface->ready) {
3896                         if (interface->scanning)
3897                                 callback_scan_started(interface);
3898                         else
3899                                 callback_scan_finished(interface);
3900                 }
3901         } else if (g_strcmp0(key, "ApScan") == 0) {
3902                 int apscan = 1;
3903
3904                 dbus_message_iter_get_basic(iter, &apscan);
3905                 interface->apscan = apscan;
3906         } else if (g_strcmp0(key, "Ifname") == 0) {
3907                 const char *str = NULL;
3908
3909                 dbus_message_iter_get_basic(iter, &str);
3910                 if (str) {
3911                         g_free(interface->ifname);
3912                         interface->ifname = g_strdup(str);
3913                 }
3914         } else if (g_strcmp0(key, "Driver") == 0) {
3915                 const char *str = NULL;
3916
3917                 dbus_message_iter_get_basic(iter, &str);
3918                 if (str) {
3919                         g_free(interface->driver);
3920                         interface->driver = g_strdup(str);
3921                 }
3922         } else if (g_strcmp0(key, "BridgeIfname") == 0) {
3923                 const char *str = NULL;
3924
3925                 dbus_message_iter_get_basic(iter, &str);
3926                 if (str) {
3927                         g_free(interface->bridge);
3928                         interface->bridge = g_strdup(str);
3929                 }
3930         } else if (g_strcmp0(key, "ConfigFile") == 0) {
3931                 const char *str = NULL;
3932
3933                 dbus_message_iter_get_basic(iter, &str);
3934                 if (str && strlen(str) > 0 && interface->ifname) {
3935                         SUPPLICANT_DBG("New {%s, %s}", interface->ifname, str);
3936                         g_hash_table_replace(config_file_table,
3937                                 g_strdup(interface->ifname), g_strdup(str));
3938                 }
3939         } else if (g_strcmp0(key, "CurrentBSS") == 0) {
3940                 interface_current_bss(interface, iter);
3941         } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
3942 #if defined TIZEN_EXT
3943                 if (interface->state != G_SUPPLICANT_STATE_COMPLETED)
3944 #endif
3945                 interface_network_added(iter, interface);
3946         } else if (g_strcmp0(key, "BSSs") == 0) {
3947                 supplicant_dbus_array_foreach(iter,
3948                                         interface_bss_added_without_keys,
3949                                         interface);
3950         } else if (g_strcmp0(key, "Blobs") == 0) {
3951                 /* Nothing */
3952         } else if (g_strcmp0(key, "Networks") == 0) {
3953                 supplicant_dbus_array_foreach(iter, interface_network_added,
3954                                                                 interface);
3955         } else if (g_strcmp0(key, "DisconnectReason") == 0) {
3956                 int reason_code;
3957                 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
3958                         dbus_message_iter_get_basic(iter, &reason_code);
3959                         callback_disconnect_reason_code(interface, reason_code);
3960 #if defined TIZEN_EXT
3961                         SUPPLICANT_DBG("reason code (%d)", reason_code);
3962 #endif
3963                 }
3964         } else if (g_strcmp0(key, "AssocStatusCode") == 0) {
3965                 int status_code;
3966                 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
3967                         dbus_message_iter_get_basic(iter, &status_code);
3968                         callback_assoc_status_code(interface, status_code);
3969 #if defined TIZEN_EXT
3970                         SUPPLICANT_DBG("status code (%d)", status_code);
3971 #endif
3972                 }
3973         } else {
3974                 SUPPLICANT_DBG("key %s type %c",
3975                                 key, dbus_message_iter_get_arg_type(iter));
3976         }
3977 }
3978
3979 static void scan_network_update(DBusMessageIter *iter, void *user_data)
3980 {
3981         GSupplicantInterface *interface = user_data;
3982         GSupplicantNetwork *network;
3983         char *path;
3984
3985         if (!iter)
3986                 return;
3987
3988         dbus_message_iter_get_basic(iter, &path);
3989
3990         if (!path)
3991                 return;
3992
3993         if (g_strcmp0(path, "/") == 0)
3994                 return;
3995
3996         /* Update the network details based on scan BSS data */
3997         network = g_hash_table_lookup(interface->bss_mapping, path);
3998         if (network)
3999                 callback_network_added(network);
4000 }
4001
4002 static void scan_bss_data(const char *key, DBusMessageIter *iter,
4003                                 void *user_data)
4004 {
4005         GSupplicantInterface *interface = user_data;
4006
4007 /*Fixed : stucking in scanning state when scan failed*/
4008 #if defined TIZEN_EXT
4009         GSupplicantInterfaceCallback scan_callback;
4010         SUPPLICANT_DBG("");
4011 #endif
4012
4013         if (iter)
4014                 supplicant_dbus_array_foreach(iter, scan_network_update,
4015                                                 interface);
4016
4017 #if defined TIZEN_EXT
4018         scan_callback = interface->scan_callback;
4019         callback_scan_done(interface);
4020 #endif
4021
4022         if (interface->scan_callback)
4023                 interface->scan_callback(0, interface, interface->scan_data);
4024
4025 #if defined TIZEN_EXT
4026         if (interface->scan_callback == scan_callback) {
4027 #endif
4028         interface->scan_callback = NULL;
4029         interface->scan_data = NULL;
4030 #if defined TIZEN_EXT
4031         }
4032 #endif
4033 }
4034
4035 static GSupplicantInterface *interface_alloc(const char *path)
4036 {
4037         GSupplicantInterface *interface;
4038
4039         interface = g_try_new0(GSupplicantInterface, 1);
4040         if (!interface)
4041                 return NULL;
4042
4043         interface->path = g_strdup(path);
4044
4045         interface->network_table = g_hash_table_new_full(g_str_hash,
4046                                         g_str_equal, NULL, remove_network);
4047         interface->peer_table = g_hash_table_new_full(g_str_hash,
4048                                         g_str_equal, NULL, remove_peer);
4049         interface->group_table = g_hash_table_new_full(g_str_hash,
4050                                         g_str_equal, NULL, remove_group);
4051         interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
4052                                                                 NULL, NULL);
4053
4054         g_hash_table_replace(interface_table, interface->path, interface);
4055
4056         return interface;
4057 }
4058
4059 static void interface_added(DBusMessageIter *iter, void *user_data)
4060 {
4061         GSupplicantInterface *interface;
4062         const char *path = NULL;
4063         bool properties_appended = GPOINTER_TO_UINT(user_data);
4064
4065         SUPPLICANT_DBG("");
4066
4067         dbus_message_iter_get_basic(iter, &path);
4068         if (!path)
4069                 return;
4070
4071         if (g_strcmp0(path, "/") == 0)
4072                 return;
4073
4074         interface = g_hash_table_lookup(interface_table, path);
4075         if (interface)
4076                 return;
4077
4078         interface = interface_alloc(path);
4079         if (!interface)
4080                 return;
4081
4082         if (!properties_appended) {
4083                 supplicant_dbus_property_get_all(path,
4084                                                 SUPPLICANT_INTERFACE ".Interface",
4085                                                 interface_property, interface,
4086                                                 interface);
4087                 return;
4088         }
4089
4090         dbus_message_iter_next(iter);
4091         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
4092                 supplicant_dbus_property_foreach(iter, interface_property,
4093                                                                 interface);
4094                 interface_property(NULL, NULL, interface);
4095         }
4096 }
4097
4098 static void interface_removed(DBusMessageIter *iter, void *user_data)
4099 {
4100         const char *path = NULL;
4101         GSupplicantInterface *interface = user_data;
4102
4103         dbus_message_iter_get_basic(iter, &path);
4104         if (!path)
4105                 return;
4106
4107         interface = g_hash_table_lookup(interface_table, path);
4108         g_supplicant_interface_cancel(interface);
4109
4110         g_hash_table_remove(interface_table, path);
4111 }
4112
4113 static void eap_method(DBusMessageIter *iter, void *user_data)
4114 {
4115         const char *str = NULL;
4116         int i;
4117
4118         dbus_message_iter_get_basic(iter, &str);
4119         if (!str)
4120                 return;
4121
4122         for (i = 0; eap_method_map[i].str; i++)
4123                 if (strcmp(str, eap_method_map[i].str) == 0) {
4124                         eap_methods |= eap_method_map[i].val;
4125                         break;
4126                 }
4127 }
4128
4129 static void service_property(const char *key, DBusMessageIter *iter,
4130                                                         void *user_data)
4131 {
4132         if (!key) {
4133                 callback_system_ready();
4134                 return;
4135         }
4136
4137         if (g_strcmp0(key, "DebugLevel") == 0) {
4138                 const char *str = NULL;
4139                 int i;
4140
4141                 dbus_message_iter_get_basic(iter, &str);
4142                 for (i = 0; debug_strings[i]; i++)
4143                         if (g_strcmp0(debug_strings[i], str) == 0) {
4144                                 debug_level = i;
4145                                 break;
4146                         }
4147                 SUPPLICANT_DBG("Debug level %d", debug_level);
4148         } else if (g_strcmp0(key, "DebugTimestamp") == 0) {
4149                 dbus_message_iter_get_basic(iter, &debug_timestamp);
4150                 SUPPLICANT_DBG("Debug timestamp %u", debug_timestamp);
4151         } else if (g_strcmp0(key, "DebugShowKeys") == 0) {
4152                 dbus_message_iter_get_basic(iter, &debug_showkeys);
4153                 SUPPLICANT_DBG("Debug show keys %u", debug_showkeys);
4154         } else if (g_strcmp0(key, "Interfaces") == 0) {
4155                 supplicant_dbus_array_foreach(iter, interface_added, NULL);
4156         } else if (g_strcmp0(key, "EapMethods") == 0) {
4157                 supplicant_dbus_array_foreach(iter, eap_method, NULL);
4158                 debug_strvalmap("EAP method", eap_method_map, eap_methods);
4159         } else if (g_strcmp0(key, "Country") == 0) {
4160                 const char *country = NULL;
4161
4162                 dbus_message_iter_get_basic(iter, &country);
4163                 SUPPLICANT_DBG("Country %s", country);
4164         } else
4165                 SUPPLICANT_DBG("key %s type %c",
4166                                 key, dbus_message_iter_get_arg_type(iter));
4167 }
4168
4169 static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
4170 {
4171         const char *name = NULL, *old = NULL, *new = NULL;
4172
4173         SUPPLICANT_DBG("");
4174
4175         if (g_strcmp0(path, DBUS_PATH_DBUS) != 0)
4176                 return;
4177
4178         dbus_message_iter_get_basic(iter, &name);
4179         if (!name)
4180                 return;
4181
4182         if (g_strcmp0(name, SUPPLICANT_SERVICE) != 0)
4183                 return;
4184
4185         dbus_message_iter_next(iter);
4186         dbus_message_iter_get_basic(iter, &old);
4187         dbus_message_iter_next(iter);
4188         dbus_message_iter_get_basic(iter, &new);
4189
4190         if (!old || !new)
4191                 return;
4192
4193         if (strlen(old) > 0 && strlen(new) == 0) {
4194                 system_available = FALSE;
4195                 g_hash_table_remove_all(bss_mapping);
4196                 g_hash_table_remove_all(peer_mapping);
4197                 g_hash_table_remove_all(group_mapping);
4198                 g_hash_table_remove_all(config_file_table);
4199                 g_hash_table_remove_all(interface_table);
4200                 callback_system_killed();
4201         }
4202
4203         if (strlen(new) > 0 && strlen(old) == 0) {
4204                 system_available = TRUE;
4205                 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
4206                                                 SUPPLICANT_INTERFACE,
4207                                                 service_property, NULL, NULL);
4208         }
4209 }
4210
4211 static void signal_properties_changed(const char *path, DBusMessageIter *iter)
4212 {
4213         SUPPLICANT_DBG("");
4214
4215         if (g_strcmp0(path, SUPPLICANT_PATH) != 0)
4216                 return;
4217
4218         supplicant_dbus_property_foreach(iter, service_property, NULL);
4219 }
4220
4221 static void signal_interface_added(const char *path, DBusMessageIter *iter)
4222 {
4223         SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
4224
4225         if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
4226                 interface_added(iter, GUINT_TO_POINTER(true));
4227 }
4228
4229 static void signal_interface_removed(const char *path, DBusMessageIter *iter)
4230 {
4231         SUPPLICANT_DBG("");
4232
4233         if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
4234                 interface_removed(iter, NULL);
4235 }
4236
4237 static void signal_interface_changed(const char *path, DBusMessageIter *iter)
4238 {
4239         GSupplicantInterface *interface;
4240 #if defined TIZEN_EXT
4241         if (!simplified_log)
4242 #endif
4243         SUPPLICANT_DBG("");
4244
4245         interface = g_hash_table_lookup(interface_table, path);
4246         if (!interface)
4247                 return;
4248
4249         supplicant_dbus_property_foreach(iter, interface_property, interface);
4250 }
4251
4252 static void signal_scan_done(const char *path, DBusMessageIter *iter)
4253 {
4254         GSupplicantInterface *interface;
4255         dbus_bool_t success = FALSE;
4256
4257         SUPPLICANT_DBG("");
4258
4259         interface = g_hash_table_lookup(interface_table, path);
4260         if (!interface)
4261                 return;
4262
4263         dbus_message_iter_get_basic(iter, &success);
4264
4265         if (interface->scanning) {
4266                 callback_scan_finished(interface);
4267                 interface->scanning = FALSE;
4268         }
4269
4270         /*
4271          * If scan is unsuccessful return -EIO else get the scanned BSSs
4272          * and update the network details accordingly
4273          */
4274         if (!success) {
4275                 if (interface->scan_callback)
4276                         interface->scan_callback(-EIO, interface,
4277                                                 interface->scan_data);
4278
4279                 interface->scan_callback = NULL;
4280                 interface->scan_data = NULL;
4281
4282                 return;
4283         }
4284
4285         supplicant_dbus_property_get(path, SUPPLICANT_INTERFACE ".Interface",
4286                                 "BSSs", scan_bss_data, interface, interface);
4287 }
4288
4289 static void signal_bss_added(const char *path, DBusMessageIter *iter)
4290 {
4291         GSupplicantInterface *interface;
4292 #if defined TIZEN_EXT
4293         if (!simplified_log)
4294 #endif
4295         SUPPLICANT_DBG("");
4296
4297         interface = g_hash_table_lookup(interface_table, path);
4298         if (!interface)
4299                 return;
4300
4301         interface_bss_added_with_keys(iter, interface);
4302 }
4303
4304 static void signal_bss_removed(const char *path, DBusMessageIter *iter)
4305 {
4306         GSupplicantInterface *interface;
4307
4308         SUPPLICANT_DBG("");
4309
4310         interface = g_hash_table_lookup(interface_table, path);
4311         if (!interface)
4312                 return;
4313
4314         interface_bss_removed(iter, interface);
4315 }
4316
4317 static void signal_network_added(const char *path, DBusMessageIter *iter)
4318 {
4319         GSupplicantInterface *interface;
4320
4321         SUPPLICANT_DBG("");
4322
4323         interface = g_hash_table_lookup(interface_table, path);
4324         if (!interface)
4325                 return;
4326
4327         interface_network_added(iter, interface);
4328 }
4329
4330 static void signal_network_removed(const char *path, DBusMessageIter *iter)
4331 {
4332         GSupplicantInterface *interface;
4333
4334         SUPPLICANT_DBG("");
4335
4336         interface = g_hash_table_lookup(interface_table, path);
4337         if (!interface)
4338                 return;
4339
4340         interface_network_removed(iter, interface);
4341 }
4342 #if defined TIZEN_EXT
4343 void *copy_vsie_list(gconstpointer src, gpointer data)
4344 {
4345         return g_strdup(src);
4346 }
4347 #endif
4348
4349
4350 static void signal_sta_authorized(const char *path, DBusMessageIter *iter)
4351 {
4352         GSupplicantInterface *interface;
4353         const char *addr = NULL;
4354
4355         SUPPLICANT_DBG("");
4356
4357         interface = g_hash_table_lookup(interface_table, path);
4358         if (!interface)
4359                 return;
4360
4361         dbus_message_iter_get_basic(iter, &addr);
4362         if (!addr)
4363                 return;
4364
4365         callback_sta_authorized(interface, addr);
4366 }
4367
4368 static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter)
4369 {
4370         GSupplicantInterface *interface;
4371         const char *addr = NULL;
4372
4373         SUPPLICANT_DBG("");
4374
4375         interface = g_hash_table_lookup(interface_table, path);
4376         if (!interface)
4377                 return;
4378
4379         dbus_message_iter_get_basic(iter, &addr);
4380         if (!addr)
4381                 return;
4382
4383         callback_sta_deauthorized(interface, addr);
4384 }
4385
4386 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
4387 static void signal_eap(const char *path, DBusMessageIter *iter)
4388 {
4389         GSupplicantInterface *interface;
4390         const char *str = NULL;
4391
4392         SUPPLICANT_DBG("EAPOL_DEBUG callback eap signal");
4393
4394         interface = g_hash_table_lookup(interface_table, path);
4395         if (!interface)
4396                 return;
4397
4398         // TODO: Identify EAP fail condition, currently timeout is used for failure.
4399
4400         dbus_message_iter_get_basic(iter, &str);
4401         if (!str)
4402                 return;
4403
4404         if (g_strcmp0("completion", str))
4405                 return;
4406
4407         dbus_message_iter_next(iter);
4408
4409         dbus_message_iter_get_basic(iter, &str);
4410         if (!str)
4411                 return;
4412
4413         if (!g_strcmp0("success", str))
4414                 callback_eap(interface, true);
4415         else
4416                 callback_eap(interface, false);
4417 }
4418 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
4419
4420 static void signal_bss_changed(const char *path, DBusMessageIter *iter)
4421 {
4422         GSupplicantInterface *interface;
4423         GSupplicantNetwork *network;
4424         GSupplicantSecurity old_security;
4425         unsigned int old_wps_capabilities;
4426         struct g_supplicant_bss *bss;
4427
4428 #if defined TIZEN_EXT
4429         if (!simplified_log)
4430 #endif
4431         SUPPLICANT_DBG("");
4432
4433         interface = g_hash_table_lookup(bss_mapping, path);
4434         if (!interface)
4435                 return;
4436
4437         network = g_hash_table_lookup(interface->bss_mapping, path);
4438         if (!network)
4439                 return;
4440
4441         bss = g_hash_table_lookup(network->bss_table, path);
4442         if (!bss)
4443                 return;
4444
4445         supplicant_dbus_property_foreach(iter, bss_property, bss);
4446
4447 #if defined TIZEN_EXT
4448         if (network->interface->state != G_SUPPLICANT_STATE_COMPLETED) {
4449                 network->frequency = bss->frequency;
4450                 network->phy_mode = bss->phy_mode;
4451         }
4452 #endif
4453         old_security = network->security;
4454         bss_compute_security(bss);
4455
4456         if (old_security != bss->security) {
4457                 struct g_supplicant_bss *new_bss;
4458
4459                 SUPPLICANT_DBG("New network security for %s with path %s",
4460                                bss->ssid, bss->path);
4461
4462                 /*
4463                  * Security change policy:
4464                  * - We first copy the current bss into a new one with
4465                  *   its own pointer (path)
4466                  * - Clear the old bss pointer and remove the network completely
4467                  *   if there are no more BSSs in the bss table.
4468                  * - The new bss will be added either to an existing network
4469                  *   or an additional network will be created
4470                  */
4471
4472                 new_bss = g_try_new0(struct g_supplicant_bss, 1);
4473                 if (!new_bss)
4474                         return;
4475
4476                 memcpy(new_bss, bss, sizeof(struct g_supplicant_bss));
4477                 new_bss->path = g_strdup(bss->path);
4478 #if defined TIZEN_EXT
4479                 new_bss->vsie_list = g_slist_copy_deep(bss->vsie_list, copy_vsie_list, NULL);
4480 #endif
4481
4482                 if (network->best_bss == bss) {
4483                         network->best_bss = NULL;
4484                         network->signal = BSS_UNKNOWN_STRENGTH;
4485                 }
4486
4487                 g_hash_table_remove(bss_mapping, path);
4488
4489                 g_hash_table_remove(interface->bss_mapping, path);
4490                 g_hash_table_remove(network->bss_table, path);
4491
4492                 update_network_signal(network);
4493
4494                 if (g_hash_table_size(network->bss_table) == 0)
4495                         g_hash_table_remove(interface->network_table,
4496                                             network->group);
4497
4498                 if (add_or_replace_bss_to_network(new_bss) < 0) {
4499                         /*
4500                          * Prevent a memory leak on failure in
4501                          * add_or_replace_bss_to_network
4502                          */
4503                         SUPPLICANT_DBG("Failed to add bss %s to network table",
4504                                        new_bss->path);
4505                         g_free(new_bss->path);
4506                         g_free(new_bss);
4507                 }
4508
4509                 return;
4510         }
4511
4512         old_wps_capabilities = network->wps_capabilities;
4513
4514         if (old_wps_capabilities != bss->wps_capabilities) {
4515                 network->wps_capabilities = bss->wps_capabilities;
4516                 callback_network_changed(network, "WPSCapabilities");
4517         }
4518
4519 #if defined TIZEN_EXT
4520         if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
4521                 network->wps = TRUE;
4522                 network->wps_capabilities |= bss->wps_capabilities;
4523         } else
4524                 network->wps = FALSE;
4525 #endif
4526
4527         /* Consider only property changes of the connected BSS */
4528         if (network == interface->current_network && bss != network->best_bss)
4529                 return;
4530
4531         if (bss->signal == network->signal)
4532 #ifndef TIZEN_EXT
4533                 return;
4534 #else
4535         {
4536                 callback_network_changed(network, "");
4537                 return;
4538         }
4539 #endif
4540
4541         /*
4542          * If the new signal is lower than the SSID signal, we need
4543          * to check for the new maximum.
4544          */
4545 #if defined TIZEN_EXT
4546         if (!update_best_bss(network, bss, network->best_bss)) {
4547                 if (bss != network->best_bss) {
4548                         callback_network_changed(network, "");
4549                         return;
4550                 }
4551
4552                 network->signal = bss->signal;
4553                 update_network_signal(network);
4554         }
4555 #else
4556         if (bss->signal < network->signal) {
4557                 if (bss != network->best_bss)
4558                         return;
4559
4560                 network->signal = bss->signal;
4561                 update_network_signal(network);
4562         } else {
4563                 network->signal = bss->signal;
4564                 network->best_bss = bss;
4565         }
4566 #endif
4567
4568         SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid,
4569                         network->signal);
4570
4571         callback_network_changed(network, "Signal");
4572 }
4573
4574 static void wps_credentials(const char *key, DBusMessageIter *iter,
4575                         void *user_data)
4576 {
4577         GSupplicantInterface *interface = user_data;
4578
4579         if (!key)
4580                 return;
4581
4582         SUPPLICANT_DBG("key %s", key);
4583
4584         if (g_strcmp0(key, "Key") == 0) {
4585                 DBusMessageIter array;
4586                 unsigned char *key_val;
4587                 int key_len;
4588
4589                 dbus_message_iter_recurse(iter, &array);
4590                 dbus_message_iter_get_fixed_array(&array, &key_val, &key_len);
4591
4592                 g_free(interface->wps_cred.key);
4593                 interface->wps_cred.key = g_try_malloc0(
4594                                                 sizeof(char) * key_len + 1);
4595
4596                 if (!interface->wps_cred.key)
4597                         return;
4598
4599                 memcpy(interface->wps_cred.key, key_val,
4600                                                 sizeof(char) * key_len);
4601
4602                 SUPPLICANT_DBG("WPS key present");
4603         } else if (g_strcmp0(key, "SSID") == 0) {
4604                 DBusMessageIter array;
4605                 unsigned char *ssid;
4606                 int ssid_len;
4607
4608                 dbus_message_iter_recurse(iter, &array);
4609                 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
4610
4611                 if (ssid_len > 0 && ssid_len < 33) {
4612                         memcpy(interface->wps_cred.ssid, ssid, ssid_len);
4613                         interface->wps_cred.ssid_len = ssid_len;
4614                 } else {
4615                         memset(interface->wps_cred.ssid, 0, 32);
4616                         interface->wps_cred.ssid_len = 0;
4617                 }
4618         }
4619 }
4620
4621 static void signal_wps_credentials(const char *path, DBusMessageIter *iter)
4622 {
4623         GSupplicantInterface *interface;
4624
4625         SUPPLICANT_DBG("");
4626
4627         interface = g_hash_table_lookup(interface_table, path);
4628         if (!interface)
4629                 return;
4630
4631         supplicant_dbus_property_foreach(iter, wps_credentials, interface);
4632 }
4633
4634 static void wps_event_args(const char *key, DBusMessageIter *iter,
4635                         void *user_data)
4636 {
4637         GSupplicantInterface *interface = user_data;
4638
4639         if (!key || !interface)
4640                 return;
4641
4642         SUPPLICANT_DBG("Arg Key %s", key);
4643 }
4644
4645 static void signal_wps_event(const char *path, DBusMessageIter *iter)
4646 {
4647         GSupplicantInterface *interface;
4648         const char *name = NULL;
4649
4650         SUPPLICANT_DBG("");
4651
4652         interface = g_hash_table_lookup(interface_table, path);
4653         if (!interface)
4654                 return;
4655
4656         dbus_message_iter_get_basic(iter, &name);
4657
4658         SUPPLICANT_DBG("Name: %s", name);
4659
4660         if (g_strcmp0(name, "success") == 0)
4661                 interface->wps_state = G_SUPPLICANT_WPS_STATE_SUCCESS;
4662         else if (g_strcmp0(name, "fail") == 0)
4663                 interface->wps_state = G_SUPPLICANT_WPS_STATE_FAIL;
4664         else
4665                 interface->wps_state = G_SUPPLICANT_WPS_STATE_UNKNOWN;
4666
4667         if (!dbus_message_iter_has_next(iter))
4668                 return;
4669
4670         dbus_message_iter_next(iter);
4671
4672         supplicant_dbus_property_foreach(iter, wps_event_args, interface);
4673 }
4674
4675 #if defined TIZEN_EXT
4676 static void signal_power_off(const char *path, DBusMessageIter *iter)
4677 {
4678         int poweroff_state = 0;
4679
4680         dbus_message_iter_get_basic(iter, &poweroff_state);
4681
4682         SUPPLICANT_DBG("poweroff_state(%d)", poweroff_state);
4683
4684         /* POWER_OFF_DIRECT 2 && POWER_OFF_RESTART 3 */
4685         if (poweroff_state != 2 && poweroff_state != 3)
4686                 return;
4687
4688         if (callbacks_pointer == NULL)
4689                 return;
4690
4691         if (callbacks_pointer->system_power_off == NULL)
4692                 return;
4693
4694         callbacks_pointer->system_power_off();
4695 }
4696 #endif
4697
4698 static void create_peer_identifier(GSupplicantPeer *peer)
4699 {
4700         const unsigned char test[ETH_ALEN] = {};
4701
4702         if (!peer)
4703                 return;
4704
4705         if (!memcmp(peer->device_address, test, ETH_ALEN)) {
4706                 peer->identifier = g_strdup(peer->name);
4707                 return;
4708         }
4709
4710         peer->identifier = g_malloc0(19);
4711         snprintf(peer->identifier, 19, "%02x%02x%02x%02x%02x%02x",
4712                                                 peer->device_address[0],
4713                                                 peer->device_address[1],
4714                                                 peer->device_address[2],
4715                                                 peer->device_address[3],
4716                                                 peer->device_address[4],
4717                                                 peer->device_address[5]);
4718 }
4719
4720 struct peer_property_data {
4721         GSupplicantPeer *peer;
4722         GSList *old_groups;
4723         bool groups_changed;
4724         bool services_changed;
4725 };
4726
4727 static void peer_groups_relation(DBusMessageIter *iter, void *user_data)
4728 {
4729         struct peer_property_data *data = user_data;
4730         GSupplicantPeer *peer = data->peer;
4731         GSupplicantGroup *group;
4732         const char *str = NULL;
4733         GSList *elem;
4734
4735         dbus_message_iter_get_basic(iter, &str);
4736         if (!str)
4737                 return;
4738
4739         group = g_hash_table_lookup(group_mapping, str);
4740         if (!group)
4741                 return;
4742
4743         elem = g_slist_find_custom(data->old_groups, str, (GCompareFunc)g_strcmp0);
4744         if (elem) {
4745                 data->old_groups = g_slist_remove_link(data->old_groups, elem);
4746                 peer->groups = g_slist_concat(elem, peer->groups);
4747         } else {
4748                 peer->groups = g_slist_prepend(peer->groups, g_strdup(str));
4749                 data->groups_changed = true;
4750         }
4751 }
4752
4753 static void peer_property(const char *key, DBusMessageIter *iter,
4754                                                         void *user_data)
4755 {
4756         GSupplicantPeer *pending_peer;
4757         struct peer_property_data *data = user_data;
4758         GSupplicantPeer *peer = data->peer;
4759
4760         SUPPLICANT_DBG("key: %s", key);
4761
4762         if (!peer->interface)
4763                 return;
4764
4765         if (!key) {
4766                 if (peer->name) {
4767                         create_peer_identifier(peer);
4768                         callback_peer_found(peer);
4769                         pending_peer = g_hash_table_lookup(
4770                                         pending_peer_connection, peer->path);
4771
4772                         if (pending_peer && pending_peer == peer) {
4773                                 callback_peer_request(peer);
4774                                 g_hash_table_remove(pending_peer_connection,
4775                                                 peer->path);
4776                         }
4777
4778                         dbus_free(data);
4779                 }
4780
4781                 return;
4782         }
4783
4784         if (g_strcmp0(key, "DeviceAddress") == 0) {
4785                 unsigned char *dev_addr;
4786                 DBusMessageIter array;
4787                 int len;
4788
4789                 dbus_message_iter_recurse(iter, &array);
4790                 dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
4791
4792                 if (len == ETH_ALEN)
4793                         memcpy(peer->device_address, dev_addr, len);
4794         } else if (g_strcmp0(key, "DeviceName") == 0) {
4795                 const char *str = NULL;
4796
4797                 dbus_message_iter_get_basic(iter, &str);
4798                 if (str)
4799                         peer->name = g_strdup(str);
4800         } else if (g_strcmp0(key, "config_method") == 0) {
4801                 uint16_t wps_config;
4802
4803                 dbus_message_iter_get_basic(iter, &wps_config);
4804
4805                 if (wps_config & G_SUPPLICANT_WPS_CONFIG_PBC)
4806                         peer->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
4807                 if (wps_config & ~G_SUPPLICANT_WPS_CONFIG_PBC)
4808                         peer->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
4809         } else if (g_strcmp0(key, "Groups") == 0) {
4810                 data->old_groups = peer->groups;
4811                 peer->groups = NULL;
4812
4813                 supplicant_dbus_array_foreach(iter,
4814                                                 peer_groups_relation, data);
4815                 if (g_slist_length(data->old_groups) > 0) {
4816                         g_slist_free_full(data->old_groups, g_free);
4817                         data->groups_changed = true;
4818                 }
4819         } else if (g_strcmp0(key, "IEs") == 0) {
4820                 DBusMessageIter array;
4821                 unsigned char *ie;
4822                 int ie_len;
4823
4824                 dbus_message_iter_recurse(iter, &array);
4825                 dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
4826
4827                 if (!ie || ie_len < 2)
4828                         return;
4829
4830                 if (peer->widi_ies) {
4831                         if (memcmp(peer->widi_ies, ie, ie_len) == 0)
4832                                 return;
4833
4834                         g_free(peer->widi_ies);
4835                         peer->widi_ies_length = 0;
4836                 }
4837
4838                 peer->widi_ies = g_malloc0(ie_len * sizeof(unsigned char));
4839
4840                 memcpy(peer->widi_ies, ie, ie_len);
4841                 peer->widi_ies_length = ie_len;
4842                 data->services_changed = true;
4843         }
4844 }
4845
4846 static void signal_peer_found(const char *path, DBusMessageIter *iter)
4847 {
4848         struct peer_property_data *property_data;
4849         GSupplicantInterface *interface;
4850         const char *obj_path = NULL;
4851         GSupplicantPeer *peer;
4852
4853         SUPPLICANT_DBG("");
4854
4855         interface = g_hash_table_lookup(interface_table, path);
4856         if (!interface)
4857                 return;
4858
4859         dbus_message_iter_get_basic(iter, &obj_path);
4860         if (!obj_path || g_strcmp0(obj_path, "/") == 0)
4861                 return;
4862
4863         peer = g_hash_table_lookup(interface->peer_table, obj_path);
4864         if (peer)
4865                 return;
4866
4867         peer = g_try_new0(GSupplicantPeer, 1);
4868         if (!peer)
4869                 return;
4870
4871         peer->interface = interface;
4872         peer->path = g_strdup(obj_path);
4873         g_hash_table_insert(interface->peer_table, peer->path, peer);
4874         g_hash_table_replace(peer_mapping, peer->path, interface);
4875
4876         property_data = dbus_malloc0(sizeof(struct peer_property_data));
4877         property_data->peer = peer;
4878
4879         dbus_message_iter_next(iter);
4880         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
4881                 supplicant_dbus_property_foreach(iter, peer_property,
4882                                                         property_data);
4883                 peer_property(NULL, NULL, property_data);
4884                 return;
4885         }
4886
4887         supplicant_dbus_property_get_all(obj_path,
4888                                         SUPPLICANT_INTERFACE ".Peer",
4889                                         peer_property, property_data, NULL);
4890 }
4891
4892 static void signal_peer_lost(const char *path, DBusMessageIter *iter)
4893 {
4894         GSupplicantInterface *interface;
4895         const char *obj_path = NULL;
4896         GSupplicantPeer *peer;
4897
4898         SUPPLICANT_DBG("");
4899
4900         interface = g_hash_table_lookup(interface_table, path);
4901         if (!interface)
4902                 return;
4903
4904         dbus_message_iter_get_basic(iter, &obj_path);
4905         if (!obj_path || g_strcmp0(obj_path, "/") == 0)
4906                 return;
4907
4908         peer = g_hash_table_lookup(interface->peer_table, obj_path);
4909         if (!peer)
4910                 return;
4911
4912         g_hash_table_remove(interface->peer_table, obj_path);
4913 }
4914
4915 static void signal_peer_changed(const char *path, DBusMessageIter *iter)
4916 {
4917         struct peer_property_data *property_data;
4918         GSupplicantInterface *interface;
4919         GSupplicantPeer *peer;
4920
4921         SUPPLICANT_DBG("");
4922
4923         interface = g_hash_table_lookup(peer_mapping, path);
4924         if (!interface)
4925                 return;
4926
4927         peer = g_hash_table_lookup(interface->peer_table, path);
4928         if (!peer) {
4929                 g_hash_table_remove(peer_mapping, path);
4930                 return;
4931         }
4932
4933         property_data = dbus_malloc0(sizeof(struct peer_property_data));
4934         property_data->peer = peer;
4935
4936         supplicant_dbus_property_foreach(iter, peer_property, property_data);
4937         if (property_data->services_changed)
4938                 callback_peer_changed(peer,
4939                                         G_SUPPLICANT_PEER_SERVICES_CHANGED);
4940
4941         if (property_data->groups_changed)
4942                 callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_CHANGED);
4943
4944         dbus_free(property_data);
4945
4946         if (!g_supplicant_peer_is_in_a_group(peer))
4947                 peer->connection_requested = false;
4948 }
4949
4950 struct group_sig_data {
4951         const char *peer_obj_path;
4952         unsigned char iface_address[ETH_ALEN];
4953         const char *interface_obj_path;
4954         const char *group_obj_path;
4955         int role;
4956 };
4957
4958 static void group_sig_property(const char *key, DBusMessageIter *iter,
4959                                                         void *user_data)
4960 {
4961         struct group_sig_data *data = user_data;
4962
4963         if (!key)
4964                 return;
4965
4966         if (g_strcmp0(key, "peer_interface_addr") == 0) {
4967                 unsigned char *dev_addr;
4968                 DBusMessageIter array;
4969                 int len;
4970
4971                 dbus_message_iter_recurse(iter, &array);
4972                 dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
4973
4974                 if (len == ETH_ALEN)
4975                         memcpy(data->iface_address, dev_addr, len);
4976         } else if (g_strcmp0(key, "role") == 0) {
4977                 const char *str = NULL;
4978
4979                 dbus_message_iter_get_basic(iter, &str);
4980                 if (g_strcmp0(str, "GO") == 0)
4981                         data->role = G_SUPPLICANT_GROUP_ROLE_GO;
4982                 else
4983                         data->role = G_SUPPLICANT_GROUP_ROLE_CLIENT;
4984         } else if (g_strcmp0(key, "peer_object") == 0)
4985                 dbus_message_iter_get_basic(iter, &data->peer_obj_path);
4986         else if (g_strcmp0(key, "interface_object") == 0)
4987                 dbus_message_iter_get_basic(iter, &data->interface_obj_path);
4988         else if (g_strcmp0(key, "group_object") == 0)
4989                 dbus_message_iter_get_basic(iter, &data->group_obj_path);
4990
4991 }
4992
4993 static void signal_group_success(const char *path, DBusMessageIter *iter)
4994 {
4995         GSupplicantInterface *interface;
4996         struct group_sig_data data = {};
4997         GSupplicantPeer *peer;
4998
4999         SUPPLICANT_DBG("");
5000
5001         interface = g_hash_table_lookup(interface_table, path);
5002         if (!interface)
5003                 return;
5004
5005         supplicant_dbus_property_foreach(iter, group_sig_property, &data);
5006         if (!data.peer_obj_path)
5007                 return;
5008
5009         peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
5010         if (!peer)
5011                 return;
5012
5013         memcpy(peer->iface_address, data.iface_address, ETH_ALEN);
5014         interface->pending_peer_path = peer->path;
5015 }
5016
5017 static void signal_group_failure(const char *path, DBusMessageIter *iter)
5018 {
5019         GSupplicantInterface *interface;
5020         struct group_sig_data data = {};
5021         GSupplicantPeer *peer;
5022
5023         SUPPLICANT_DBG("");
5024
5025         interface = g_hash_table_lookup(interface_table, path);
5026         if (!interface)
5027                 return;
5028
5029         supplicant_dbus_property_foreach(iter, group_sig_property, &data);
5030         if (!data.peer_obj_path)
5031                 return;
5032
5033         peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
5034         if (!peer)
5035                 return;
5036
5037         callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_FAILED);
5038         peer->connection_requested = false;
5039 }
5040
5041 static void signal_group_started(const char *path, DBusMessageIter *iter)
5042 {
5043         GSupplicantInterface *interface, *g_interface;
5044         struct group_sig_data data = {};
5045         GSupplicantGroup *group;
5046         GSupplicantPeer *peer;
5047
5048         SUPPLICANT_DBG("");
5049
5050         interface = g_hash_table_lookup(interface_table, path);
5051         if (!interface)
5052                 return;
5053
5054         supplicant_dbus_property_foreach(iter, group_sig_property, &data);
5055         if (!data.interface_obj_path || !data.group_obj_path)
5056                 return;
5057
5058         peer = g_hash_table_lookup(interface->peer_table,
5059                                                 interface->pending_peer_path);
5060         interface->pending_peer_path = NULL;
5061         if (!peer)
5062                 return;
5063
5064         g_interface = g_hash_table_lookup(interface_table,
5065                                                 data.interface_obj_path);
5066         if (!g_interface)
5067                 return;
5068
5069         group = g_hash_table_lookup(interface->group_table,
5070                                                 data.group_obj_path);
5071         if (group)
5072                 return;
5073
5074         group = g_try_new0(GSupplicantGroup, 1);
5075         if (!group)
5076                 return;
5077
5078         group->interface = g_interface;
5079         group->orig_interface = interface;
5080         group->path = g_strdup(data.group_obj_path);
5081         group->role = data.role;
5082
5083         g_hash_table_insert(interface->group_table, group->path, group);
5084         g_hash_table_replace(group_mapping, group->path, group);
5085
5086         peer->current_group_iface = g_interface;
5087         callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_STARTED);
5088 }
5089
5090 static void remove_peer_group_interface(GHashTable *group_table,
5091                                 const char* path)
5092 {
5093         GSupplicantGroup *group;
5094         GHashTableIter iter;
5095         gpointer value, key;
5096
5097         if (!group_table)
5098                 return;
5099
5100         group = g_hash_table_lookup(group_table, path);
5101
5102         if (!group || !group->orig_interface)
5103                 return;
5104
5105         g_hash_table_iter_init(&iter, group->orig_interface->peer_table);
5106
5107         while (g_hash_table_iter_next(&iter, &key, &value)) {
5108                 GSupplicantPeer *peer = value;
5109
5110                 if (peer->current_group_iface == group->interface)
5111                         peer->current_group_iface = NULL;
5112         }
5113 }
5114
5115 static void signal_group_finished(const char *path, DBusMessageIter *iter)
5116 {
5117         GSupplicantInterface *interface;
5118         struct group_sig_data data = {};
5119
5120         SUPPLICANT_DBG("");
5121
5122         interface = g_hash_table_lookup(interface_table, path);
5123         if (!interface)
5124                 return;
5125
5126         supplicant_dbus_property_foreach(iter, group_sig_property, &data);
5127         if (!data.interface_obj_path || !data.group_obj_path)
5128                 return;
5129
5130         remove_peer_group_interface(interface->group_table, data.group_obj_path);
5131
5132         g_hash_table_remove(group_mapping, data.group_obj_path);
5133
5134         g_hash_table_remove(interface->group_table, data.group_obj_path);
5135 }
5136
5137 static void signal_group_request(const char *path, DBusMessageIter *iter)
5138 {
5139         GSupplicantInterface *interface;
5140         GSupplicantPeer *peer;
5141         const char *obj_path;
5142
5143         SUPPLICANT_DBG("");
5144
5145         interface = g_hash_table_lookup(interface_table, path);
5146         if (!interface)
5147                 return;
5148
5149         dbus_message_iter_get_basic(iter, &obj_path);
5150         if (!obj_path || !g_strcmp0(obj_path, "/"))
5151                 return;
5152
5153         peer = g_hash_table_lookup(interface->peer_table, obj_path);
5154         if (!peer)
5155                 return;
5156
5157         /*
5158          * Peer has been previously found and property set,
5159          * otherwise, defer connection to when peer property
5160          * is set.
5161          */
5162         if (peer->identifier)
5163                 callback_peer_request(peer);
5164         else
5165                 g_hash_table_replace(pending_peer_connection, peer->path, peer);
5166 }
5167
5168 static void signal_group_peer_joined(const char *path, DBusMessageIter *iter)
5169 {
5170         const char *peer_path = NULL;
5171         GSupplicantInterface *interface;
5172         GSupplicantGroup *group;
5173         GSupplicantPeer *peer;
5174
5175         SUPPLICANT_DBG("");
5176
5177         group = g_hash_table_lookup(group_mapping, path);
5178         if (!group)
5179                 return;
5180
5181         dbus_message_iter_get_basic(iter, &peer_path);
5182         if (!peer_path)
5183                 return;
5184
5185         interface = g_hash_table_lookup(peer_mapping, peer_path);
5186         if (!interface)
5187                 return;
5188
5189         peer = g_hash_table_lookup(interface->peer_table, peer_path);
5190         if (!peer)
5191                 return;
5192
5193         group->members = g_slist_prepend(group->members, g_strdup(peer_path));
5194
5195         callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_JOINED);
5196 }
5197
5198 static void signal_group_peer_disconnected(const char *path, DBusMessageIter *iter)
5199 {
5200         const char *peer_path = NULL;
5201         GSupplicantInterface *interface;
5202         GSupplicantGroup *group;
5203         GSupplicantPeer *peer;
5204         GSList *elem;
5205
5206         SUPPLICANT_DBG("");
5207
5208         group = g_hash_table_lookup(group_mapping, path);
5209         if (!group)
5210                 return;
5211
5212         dbus_message_iter_get_basic(iter, &peer_path);
5213         if (!peer_path)
5214                 return;
5215
5216         for (elem = group->members; elem; elem = elem->next) {
5217                 if (!g_strcmp0(elem->data, peer_path))
5218                         break;
5219         }
5220
5221         if (!elem)
5222                 return;
5223
5224         g_free(elem->data);
5225         group->members = g_slist_delete_link(group->members, elem);
5226
5227         interface = g_hash_table_lookup(peer_mapping, peer_path);
5228         if (!interface)
5229                 return;
5230
5231         peer = g_hash_table_lookup(interface->peer_table, peer_path);
5232         if (!peer)
5233                 return;
5234
5235         callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_DISCONNECTED);
5236         peer->connection_requested = false;
5237 }
5238
5239 #if defined TIZEN_EXT_WIFI_MESH
5240 const void *g_supplicant_interface_get_mesh_group_ssid(
5241                                                         GSupplicantInterface *interface,
5242                                                         unsigned int *ssid_len)
5243 {
5244         if (!ssid_len)
5245                 return NULL;
5246
5247         if (!interface || interface->group_info.ssid_len == 0) {
5248                 *ssid_len = 0;
5249                 return NULL;
5250         }
5251
5252         *ssid_len = interface->group_info.ssid_len;
5253         return interface->group_info.ssid;
5254 }
5255
5256 int g_supplicant_mesh_get_disconnect_reason(GSupplicantInterface *interface)
5257 {
5258         if (!interface)
5259                 return -EINVAL;
5260
5261         return interface->group_info.disconnect_reason;
5262 }
5263
5264 const char *g_supplicant_mesh_peer_get_address(GSupplicantMeshPeer *mesh_peer)
5265 {
5266         if (!mesh_peer || !mesh_peer->peer_address)
5267                 return NULL;
5268
5269         return mesh_peer->peer_address;
5270 }
5271
5272 int g_supplicant_mesh_peer_get_disconnect_reason(GSupplicantMeshPeer *mesh_peer)
5273 {
5274         if (!mesh_peer)
5275                 return -EINVAL;
5276
5277         return mesh_peer->disconnect_reason;
5278 }
5279
5280 static void callback_mesh_group_started(GSupplicantInterface *interface)
5281 {
5282         if (!callbacks_pointer)
5283                 return;
5284
5285         if (!callbacks_pointer->mesh_group_started)
5286                 return;
5287
5288         callbacks_pointer->mesh_group_started(interface);
5289 }
5290
5291 static void callback_mesh_group_removed(GSupplicantInterface *interface)
5292 {
5293         if (!callbacks_pointer)
5294                 return;
5295
5296         if (!callbacks_pointer->mesh_group_removed)
5297                 return;
5298
5299         callbacks_pointer->mesh_group_removed(interface);
5300 }
5301
5302 static void mesh_group_info(const char *key, DBusMessageIter *iter,
5303                                                         void *user_data)
5304 {
5305         GSupplicantInterface *interface = user_data;
5306         if (!key)
5307                 return;
5308
5309         if (g_strcmp0(key, "SSID") == 0) {
5310                 DBusMessageIter array;
5311                 unsigned char *ssid;
5312                 int ssid_len;
5313
5314                 dbus_message_iter_recurse(iter, &array);
5315                 dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
5316
5317                 if (ssid_len > 0 && ssid_len < 33) {
5318                         memcpy(interface->group_info.ssid, ssid, ssid_len);
5319                         interface->group_info.ssid_len = ssid_len;
5320                 } else {
5321                         memset(interface->group_info.ssid, 0, 32);
5322                         interface->group_info.ssid_len = 0;
5323                 }
5324         } else if (g_strcmp0(key, "DisconnectReason") == 0) {
5325                 int disconnect_reason = 0;
5326                 dbus_message_iter_get_basic(iter, &disconnect_reason);
5327                 interface->group_info.disconnect_reason = disconnect_reason;
5328         }
5329 }
5330
5331 static void signal_mesh_group_started(const char *path, DBusMessageIter *iter)
5332 {
5333         GSupplicantInterface *interface;
5334
5335         interface = g_hash_table_lookup(interface_table, path);
5336         if (!interface)
5337                 return;
5338
5339         supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
5340
5341         callback_mesh_group_started(interface);
5342 }
5343
5344 static void signal_mesh_group_removed(const char *path, DBusMessageIter *iter)
5345 {
5346         GSupplicantInterface *interface;
5347
5348         interface = g_hash_table_lookup(interface_table, path);
5349         if (!interface)
5350                 return;
5351
5352         supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
5353
5354         callback_mesh_group_removed(interface);
5355 }
5356
5357 static void callback_mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
5358 {
5359         if (!callbacks_pointer)
5360                 return;
5361
5362         if (!callbacks_pointer->mesh_peer_connected)
5363                 return;
5364
5365         callbacks_pointer->mesh_peer_connected(mesh_peer);
5366 }
5367
5368 static void callback_mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
5369 {
5370         if (!callbacks_pointer)
5371                 return;
5372
5373         if (!callbacks_pointer->mesh_peer_disconnected)
5374                 return;
5375
5376         callbacks_pointer->mesh_peer_disconnected(mesh_peer);
5377 }
5378
5379 static void mesh_peer_info(const char *key, DBusMessageIter *iter,
5380                                                         void *user_data)
5381 {
5382         GSupplicantMeshPeer *mesh_peer = user_data;
5383         if (!key)
5384                 return;
5385
5386         if (g_strcmp0(key, "PeerAddress") == 0) {
5387                 DBusMessageIter array;
5388                 unsigned char *addr;
5389                 int addr_len;
5390
5391                 dbus_message_iter_recurse(iter, &array);
5392                 dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
5393
5394                 if (addr_len == 6) {
5395                         mesh_peer->peer_address = g_malloc0(19);
5396                         snprintf(mesh_peer->peer_address, 19,
5397                                          "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1],
5398                                          addr[2], addr[3], addr[4], addr[5]);
5399                 }
5400         } else if (g_strcmp0(key, "DisconnectReason") == 0) {
5401                 int disconnect_reason = 0;
5402                 dbus_message_iter_get_basic(iter, &disconnect_reason);
5403                 mesh_peer->disconnect_reason = disconnect_reason;
5404         }
5405 }
5406
5407 static void signal_mesh_peer_connected(const char *path, DBusMessageIter *iter)
5408 {
5409         GSupplicantInterface *interface;
5410         GSupplicantMeshPeer *mesh_peer;
5411
5412         interface = g_hash_table_lookup(interface_table, path);
5413         if (!interface)
5414                 return;
5415
5416         mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
5417         mesh_peer->interface = interface;
5418
5419         supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
5420
5421         callback_mesh_peer_connected(mesh_peer);
5422         g_free(mesh_peer->peer_address);
5423         g_free(mesh_peer);
5424 }
5425
5426 static void signal_mesh_peer_disconnected(const char *path,
5427                                                                 DBusMessageIter *iter)
5428 {
5429         GSupplicantInterface *interface;
5430         GSupplicantMeshPeer *mesh_peer;
5431
5432         interface = g_hash_table_lookup(interface_table, path);
5433         if (!interface)
5434                 return;
5435
5436         mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
5437         mesh_peer->interface = interface;
5438
5439         supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
5440
5441         callback_mesh_peer_disconnected(mesh_peer);
5442         g_free(mesh_peer->peer_address);
5443         g_free(mesh_peer);
5444 }
5445 #endif
5446
5447 static struct {
5448         const char *interface;
5449         const char *member;
5450         void (*function) (const char *path, DBusMessageIter *iter);
5451 } signal_map[] = {
5452         { DBUS_INTERFACE_DBUS,  "NameOwnerChanged",  signal_name_owner_changed },
5453
5454         { SUPPLICANT_INTERFACE, "PropertiesChanged", signal_properties_changed },
5455         { SUPPLICANT_INTERFACE, "InterfaceAdded",    signal_interface_added    },
5456         { SUPPLICANT_INTERFACE, "InterfaceCreated",  signal_interface_added    },
5457         { SUPPLICANT_INTERFACE, "InterfaceRemoved",  signal_interface_removed  },
5458
5459         { SUPPLICANT_INTERFACE ".Interface", "PropertiesChanged", signal_interface_changed },
5460         { SUPPLICANT_INTERFACE ".Interface", "ScanDone",          signal_scan_done         },
5461         { SUPPLICANT_INTERFACE ".Interface", "BSSAdded",          signal_bss_added         },
5462         { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved",        signal_bss_removed       },
5463         { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded",      signal_network_added     },
5464         { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved",    signal_network_removed   },
5465         { SUPPLICANT_INTERFACE ".Interface", "StaAuthorized",     signal_sta_authorized    },
5466         { SUPPLICANT_INTERFACE ".Interface", "StaDeauthorized",   signal_sta_deauthorized  },
5467
5468         { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed   },
5469
5470         { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
5471         { SUPPLICANT_INTERFACE ".Interface.WPS", "Event",       signal_wps_event       },
5472 #if defined TIZEN_EXT
5473         { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
5474 #endif
5475
5476         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
5477         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost",  signal_peer_lost  },
5478
5479         { SUPPLICANT_INTERFACE ".Peer", "PropertiesChanged", signal_peer_changed },
5480
5481         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationSuccess", signal_group_success },
5482         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationFailure", signal_group_failure },
5483         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupStarted", signal_group_started },
5484         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupFinished", signal_group_finished },
5485         { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationRequest", signal_group_request },
5486
5487         { SUPPLICANT_INTERFACE ".Group", "PeerJoined", signal_group_peer_joined },
5488         { SUPPLICANT_INTERFACE ".Group", "PeerDisconnected", signal_group_peer_disconnected },
5489 #if defined TIZEN_EXT_WIFI_MESH
5490         { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupStarted",
5491                 signal_mesh_group_started },
5492         { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupRemoved",
5493                 signal_mesh_group_removed },
5494         { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerConnected",
5495                 signal_mesh_peer_connected },
5496         { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerDisconnected",
5497                 signal_mesh_peer_disconnected },
5498 #endif
5499
5500 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
5501         { SUPPLICANT_INTERFACE ".Interface", "EAP", signal_eap },
5502 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
5503
5504         { }
5505 };
5506
5507 static DBusHandlerResult g_supplicant_filter(DBusConnection *conn,
5508                                         DBusMessage *message, void *data)
5509 {
5510         DBusMessageIter iter;
5511         const char *path;
5512         int i;
5513
5514         path = dbus_message_get_path(message);
5515         if (!path)
5516                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
5517
5518         if (!dbus_message_iter_init(message, &iter))
5519                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
5520
5521         for (i = 0; signal_map[i].interface; i++) {
5522                 if (!dbus_message_has_interface(message, signal_map[i].interface))
5523                         continue;
5524
5525                 if (!dbus_message_has_member(message, signal_map[i].member))
5526                         continue;
5527
5528                 signal_map[i].function(path, &iter);
5529                 break;
5530         }
5531
5532         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
5533 }
5534
5535 void g_supplicant_interface_cancel(GSupplicantInterface *interface)
5536 {
5537         SUPPLICANT_DBG("Cancelling any pending DBus calls");
5538         supplicant_dbus_method_call_cancel_all(interface);
5539         supplicant_dbus_property_call_cancel_all(interface);
5540 }
5541
5542 struct supplicant_regdom {
5543         GSupplicantCountryCallback callback;
5544         const char *alpha2;
5545         const void *user_data;
5546 };
5547
5548 static void country_result(const char *error,
5549                                 DBusMessageIter *iter, void *user_data)
5550 {
5551         struct supplicant_regdom *regdom = user_data;
5552         int result = 0;
5553
5554         SUPPLICANT_DBG("Country setting result");
5555
5556         if (!user_data)
5557                 return;
5558
5559         if (error) {
5560                 SUPPLICANT_DBG("Country setting failure %s", error);
5561                 result = -EINVAL;
5562         }
5563
5564         if (regdom->callback)
5565                 regdom->callback(result, regdom->alpha2,
5566                                         (void *) regdom->user_data);
5567
5568         g_free(regdom);
5569 }
5570
5571 static void country_params(DBusMessageIter *iter, void *user_data)
5572 {
5573         struct supplicant_regdom *regdom = user_data;
5574
5575         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
5576                                                         &regdom->alpha2);
5577 }
5578
5579 int g_supplicant_set_country(const char *alpha2,
5580                                 GSupplicantCountryCallback callback,
5581                                         const void *user_data)
5582 {
5583         struct supplicant_regdom *regdom;
5584         int ret;
5585
5586         SUPPLICANT_DBG("Country setting %s", alpha2);
5587
5588         if (!system_available)
5589                 return -EFAULT;
5590
5591         regdom = dbus_malloc0(sizeof(*regdom));
5592         if (!regdom)
5593                 return -ENOMEM;
5594
5595         regdom->callback = callback;
5596         regdom->alpha2 = alpha2;
5597         regdom->user_data = user_data;
5598
5599         ret =  supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
5600                                         "Country", DBUS_TYPE_STRING_AS_STRING,
5601                                         country_params, country_result,
5602                                         regdom, NULL);
5603         if (ret < 0) {
5604                 dbus_free(regdom);
5605                 SUPPLICANT_DBG("Unable to set Country configuration");
5606         }
5607         return ret;
5608 }
5609
5610 int g_supplicant_interface_set_country(GSupplicantInterface *interface,
5611                                         GSupplicantCountryCallback callback,
5612                                                         const char *alpha2,
5613                                                         void *user_data)
5614 {
5615         struct supplicant_regdom *regdom;
5616         int ret;
5617
5618         regdom = dbus_malloc0(sizeof(*regdom));
5619         if (!regdom)
5620                 return -ENOMEM;
5621
5622         regdom->callback = callback;
5623         regdom->alpha2 = alpha2;
5624         regdom->user_data = user_data;
5625
5626         ret =  supplicant_dbus_property_set(interface->path,
5627                                 SUPPLICANT_INTERFACE ".Interface",
5628                                 "Country", DBUS_TYPE_STRING_AS_STRING,
5629                                 country_params, country_result,
5630                                         regdom, NULL);
5631         if (ret < 0) {
5632                 dbus_free(regdom);
5633                 SUPPLICANT_DBG("Unable to set Country configuration");
5634         }
5635
5636         return ret;
5637 }
5638
5639 bool g_supplicant_interface_has_p2p(GSupplicantInterface *interface)
5640 {
5641         if (!interface)
5642                 return false;
5643
5644         return interface->p2p_support;
5645 }
5646
5647 struct supplicant_p2p_dev_config {
5648         char *device_name;
5649         char *dev_type;
5650 };
5651
5652 static void p2p_device_config_result(const char *error,
5653                                         DBusMessageIter *iter, void *user_data)
5654 {
5655         struct supplicant_p2p_dev_config *config = user_data;
5656
5657         if (error)
5658                 SUPPLICANT_DBG("Unable to set P2P Device configuration: %s",
5659                                                                         error);
5660
5661         g_free(config->device_name);
5662         g_free(config->dev_type);
5663         dbus_free(config);
5664 }
5665
5666 static int dev_type_str2bin(const char *type, unsigned char dev_type[8])
5667 {
5668         int length, pos, end;
5669         char b[3] = {};
5670         char *e = NULL;
5671
5672         end = strlen(type);
5673         for (length = pos = 0; type[pos] != '\0' && length < 8; length++) {
5674                 if (pos+2 > end)
5675                         return 0;
5676
5677                 b[0] = type[pos];
5678                 b[1] = type[pos+1];
5679
5680                 dev_type[length] = strtol(b, &e, 16);
5681                 if (e && *e != '\0')
5682                         return 0;
5683
5684                 pos += 2;
5685         }
5686
5687         return 8;
5688 }
5689
5690 static void p2p_device_config_params(DBusMessageIter *iter, void *user_data)
5691 {
5692         struct supplicant_p2p_dev_config *config = user_data;
5693         DBusMessageIter dict;
5694
5695         supplicant_dbus_dict_open(iter, &dict);
5696
5697         supplicant_dbus_dict_append_basic(&dict, "DeviceName",
5698                                 DBUS_TYPE_STRING, &config->device_name);
5699
5700         if (config->dev_type) {
5701                 unsigned char dev_type[8] = {}, *type;
5702                 int len;
5703
5704                 len = dev_type_str2bin(config->dev_type, dev_type);
5705                 if (len) {
5706                         type = dev_type;
5707                         supplicant_dbus_dict_append_fixed_array(&dict,
5708                                         "PrimaryDeviceType",
5709                                         DBUS_TYPE_BYTE, &type, len);
5710                 }
5711         }
5712
5713         supplicant_dbus_dict_close(iter, &dict);
5714 }
5715
5716 int g_supplicant_interface_set_p2p_device_config(GSupplicantInterface *interface,
5717                                         const char *device_name,
5718                                         const char *primary_dev_type)
5719 {
5720         struct supplicant_p2p_dev_config *config;
5721         int ret;
5722
5723         SUPPLICANT_DBG("P2P Device settings %s/%s",
5724                                         device_name, primary_dev_type);
5725
5726         config = dbus_malloc0(sizeof(*config));
5727         if (!config)
5728                 return -ENOMEM;
5729
5730         config->device_name = g_strdup(device_name);
5731         config->dev_type = g_strdup(primary_dev_type);
5732
5733         ret = supplicant_dbus_property_set(interface->path,
5734                                 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
5735                                 "P2PDeviceConfig",
5736                                 DBUS_TYPE_ARRAY_AS_STRING
5737                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
5738                                 DBUS_TYPE_STRING_AS_STRING
5739                                 DBUS_TYPE_VARIANT_AS_STRING
5740                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
5741                                 p2p_device_config_params,
5742                                 p2p_device_config_result, config, NULL);
5743         if (ret < 0) {
5744                 g_free(config->device_name);
5745                 g_free(config->dev_type);
5746                 dbus_free(config);
5747                 SUPPLICANT_DBG("Unable to set P2P Device configuration");
5748         }
5749
5750         return ret;
5751 }
5752
5753 static gboolean peer_lookup_by_identifier(gpointer key, gpointer value,
5754                                                         gpointer user_data)
5755 {
5756         const GSupplicantPeer *peer = value;
5757         const char *identifier = user_data;
5758
5759         if (!g_strcmp0(identifier, peer->identifier))
5760                 return TRUE;
5761
5762         return FALSE;
5763 }
5764
5765 GSupplicantPeer *g_supplicant_interface_peer_lookup(GSupplicantInterface *interface,
5766                                                         const char *identifier)
5767 {
5768         GSupplicantPeer *peer;
5769
5770         peer = g_hash_table_find(interface->peer_table,
5771                                         peer_lookup_by_identifier,
5772                                         (void *) identifier);
5773         return peer;
5774 }
5775
5776 static void interface_create_data_free(struct interface_create_data *data)
5777 {
5778         g_free(data->ifname);
5779         g_free(data->driver);
5780         g_free(data->bridge);
5781 #if defined TIZEN_EXT_WIFI_MESH
5782         g_free(data->parent_ifname);
5783 #endif
5784         dbus_free(data);
5785 }
5786
5787 static bool interface_exists(GSupplicantInterface *interface,
5788                                 const char *path)
5789 {
5790         GSupplicantInterface *tmp;
5791
5792         tmp = g_hash_table_lookup(interface_table, path);
5793         if (tmp && tmp == interface)
5794                 return true;
5795
5796         return false;
5797 }
5798
5799 static void interface_create_property(const char *key, DBusMessageIter *iter,
5800                                                         void *user_data)
5801 {
5802         struct interface_create_data *data = user_data;
5803         GSupplicantInterface *interface = data->interface;
5804
5805         if (!key) {
5806                 if (data->callback) {
5807                         data->callback(0, data->interface, data->user_data);
5808 #if !defined TIZEN_EXT
5809                         callback_p2p_support(interface);
5810 #endif
5811 #if defined TIZEN_EXT_WIFI_MESH
5812                         callback_mesh_support(interface);
5813 #endif
5814                 }
5815
5816                 interface_create_data_free(data);
5817         }
5818
5819         interface_property(key, iter, interface);
5820 }
5821
5822 static void interface_create_result(const char *error,
5823                                 DBusMessageIter *iter, void *user_data)
5824 {
5825         struct interface_create_data *data = user_data;
5826         const char *path = NULL;
5827         int err;
5828
5829         SUPPLICANT_DBG("");
5830
5831         if (error) {
5832                 g_warning("error %s", error);
5833                 err = -EIO;
5834                 goto done;
5835         }
5836
5837         dbus_message_iter_get_basic(iter, &path);
5838         if (!path) {
5839                 err = -EINVAL;
5840                 goto done;
5841         }
5842
5843         if (!system_available) {
5844                 err = -EFAULT;
5845                 goto done;
5846         }
5847
5848         data->interface = g_hash_table_lookup(interface_table, path);
5849         if (!data->interface) {
5850                 data->interface = interface_alloc(path);
5851                 if (!data->interface) {
5852                         err = -ENOMEM;
5853                         goto done;
5854                 }
5855         }
5856
5857         err = supplicant_dbus_property_get_all(path,
5858                                         SUPPLICANT_INTERFACE ".Interface",
5859                                         interface_create_property, data,
5860                                         NULL);
5861         if (err == 0)
5862                 return;
5863
5864 done:
5865         if (data->callback)
5866                 data->callback(err, NULL, data->user_data);
5867
5868         interface_create_data_free(data);
5869 }
5870
5871 static void interface_create_params(DBusMessageIter *iter, void *user_data)
5872 {
5873         struct interface_create_data *data = user_data;
5874         DBusMessageIter dict;
5875         char *config_file = NULL;
5876
5877         SUPPLICANT_DBG("");
5878
5879         supplicant_dbus_dict_open(iter, &dict);
5880
5881         supplicant_dbus_dict_append_basic(&dict, "Ifname",
5882                                         DBUS_TYPE_STRING, &data->ifname);
5883
5884         if (data->driver)
5885                 supplicant_dbus_dict_append_basic(&dict, "Driver",
5886                                         DBUS_TYPE_STRING, &data->driver);
5887
5888         if (data->bridge)
5889                 supplicant_dbus_dict_append_basic(&dict, "BridgeIfname",
5890                                         DBUS_TYPE_STRING, &data->bridge);
5891
5892         config_file = g_hash_table_lookup(config_file_table, data->ifname);
5893         if (config_file) {
5894                 SUPPLICANT_DBG("[%s] ConfigFile %s", data->ifname, config_file);
5895
5896                 supplicant_dbus_dict_append_basic(&dict, "ConfigFile",
5897                                         DBUS_TYPE_STRING, &config_file);
5898         }
5899
5900 #ifdef TIZEN_EXT
5901         if (data->driver && g_strstr_len(data->driver, strlen(data->driver), "nl80211")) {
5902                 supplicant_dbus_dict_append_basic(&dict, "MacAddr",
5903                                 DBUS_TYPE_UINT32, &data->mac_addr);
5904
5905                 supplicant_dbus_dict_append_basic(&dict, "PreassocMacAddr",
5906                                 DBUS_TYPE_UINT32, &data->preassoc_mac_addr);
5907
5908                 supplicant_dbus_dict_append_basic(&dict, "RandAddrLifetime",
5909                                 DBUS_TYPE_UINT32, &data->random_mac_lifetime);
5910         }
5911 #endif /* TIZEN_EXT */
5912
5913 #if defined TIZEN_EXT_WIFI_MESH
5914         if (data->is_mesh_interface) {
5915                 if (data->parent_ifname)
5916                         supplicant_dbus_dict_append_basic(&dict, "ParentIfname",
5917                                         DBUS_TYPE_STRING, &data->parent_ifname);
5918
5919                 supplicant_dbus_dict_append_basic(&dict, "IsMeshInterface",
5920                                         DBUS_TYPE_BOOLEAN, &data->is_mesh_interface);
5921         }
5922 #endif
5923
5924         supplicant_dbus_dict_close(iter, &dict);
5925 }
5926
5927 #if defined TIZEN_EXT
5928 static void interface_get_state(const char *key, DBusMessageIter *iter,
5929                 void *user_data)
5930 {
5931         struct interface_create_data *data = user_data;
5932         GSupplicantInterface *interface = NULL;
5933         const char *str = NULL;
5934
5935         SUPPLICANT_DBG("key[%s]", key);
5936
5937         if (!data) {
5938                 SUPPLICANT_DBG("data is NULL");
5939                 return;
5940         }
5941
5942         interface = data->interface;
5943         if (!interface) {
5944                 SUPPLICANT_DBG("interface is NULL");
5945                 return;
5946         }
5947
5948         if (iter)
5949                 dbus_message_iter_get_basic(iter, &str);
5950
5951         if (str) {
5952                 if (string2state(str) != interface->state)
5953                         interface->state = string2state(str);
5954         }
5955
5956         if (interface->state == G_SUPPLICANT_STATE_DISABLED)
5957                 interface->ready = FALSE;
5958         else
5959                 interface->ready = TRUE;
5960
5961         SUPPLICANT_DBG("state %s (%d)", str, interface->state);
5962
5963         if (data->callback) {
5964                 data->callback(0, interface, data->user_data);
5965 #if defined TIZEN_EXT_WIFI_MESH
5966                 callback_mesh_support(interface);
5967 #endif
5968         }
5969
5970         interface_create_data_free(data);
5971 }
5972 #endif
5973
5974 static void interface_get_result(const char *error,
5975                                 DBusMessageIter *iter, void *user_data)
5976 {
5977         struct interface_create_data *data = user_data;
5978         GSupplicantInterface *interface;
5979         const char *path = NULL;
5980         int err;
5981
5982 #if defined TIZEN_EXT
5983         if (!simplified_log)
5984 #endif
5985         SUPPLICANT_DBG("");
5986
5987         if (error) {
5988                 SUPPLICANT_DBG("Interface not created yet");
5989                 goto create;
5990         }
5991
5992         dbus_message_iter_get_basic(iter, &path);
5993         if (!path) {
5994                 err = -EINVAL;
5995                 goto done;
5996         }
5997
5998         interface = g_hash_table_lookup(interface_table, path);
5999         if (!interface) {
6000                 err = -ENOENT;
6001                 goto done;
6002         }
6003
6004 #if defined TIZEN_EXT
6005         data->interface = interface;
6006         err = supplicant_dbus_property_get(path,
6007                         SUPPLICANT_INTERFACE ".Interface",
6008                         "State", interface_get_state, data, NULL);
6009
6010         if (err == 0)
6011                 return;
6012 #endif
6013
6014         if (data->callback) {
6015                 data->callback(0, interface, data->user_data);
6016 #if !defined TIZEN_EXT
6017                 callback_p2p_support(interface);
6018 #endif
6019 #if defined TIZEN_EXT_WIFI_MESH
6020                 callback_mesh_support(interface);
6021 #endif
6022         }
6023
6024         interface_create_data_free(data);
6025
6026         return;
6027
6028 create:
6029         if (!system_available) {
6030                 err = -EFAULT;
6031                 goto done;
6032         }
6033
6034         SUPPLICANT_DBG("Creating interface");
6035
6036         err = supplicant_dbus_method_call(SUPPLICANT_PATH,
6037                                                 SUPPLICANT_INTERFACE,
6038                                                 "CreateInterface",
6039                                                 interface_create_params,
6040                                                 interface_create_result, data,
6041                                                 NULL);
6042         if (err == 0)
6043                 return;
6044
6045 done:
6046         if (data->callback)
6047                 data->callback(err, NULL, data->user_data);
6048
6049         interface_create_data_free(data);
6050 }
6051
6052 static void interface_get_params(DBusMessageIter *iter, void *user_data)
6053 {
6054         struct interface_create_data *data = user_data;
6055 #if defined TIZEN_EXT
6056         if (!simplified_log)
6057 #endif
6058         SUPPLICANT_DBG("");
6059
6060         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
6061 }
6062
6063 #if defined TIZEN_EXT_WIFI_MESH
6064 int g_supplicant_mesh_interface_create(const char *ifname, const char *driver,
6065                                                 const char *bridge, const char *parent_ifname,
6066                                                 GSupplicantInterfaceCallback callback, void *user_data)
6067 {
6068         struct interface_create_data *data;
6069         int ret;
6070
6071         SUPPLICANT_DBG("ifname %s", ifname);
6072
6073         if (!ifname || !parent_ifname)
6074                 return -EINVAL;
6075
6076         if (!system_available)
6077                 return -EFAULT;
6078
6079         data = dbus_malloc0(sizeof(*data));
6080         if (!data)
6081                 return -ENOMEM;
6082
6083         data->ifname = g_strdup(ifname);
6084         data->driver = g_strdup(driver);
6085         data->bridge = g_strdup(bridge);
6086         data->is_mesh_interface = true;
6087         data->parent_ifname = g_strdup(parent_ifname);
6088         data->callback = callback;
6089         data->user_data = user_data;
6090
6091         ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
6092                                                 SUPPLICANT_INTERFACE,
6093                                                 "CreateInterface",
6094                                                 interface_create_params,
6095                                                 interface_create_result, data,
6096                                                 NULL);
6097         return ret;
6098 }
6099
6100 struct interface_mesh_peer_data {
6101         char *peer_address;
6102         char *method;
6103         GSupplicantInterface *interface;
6104         GSupplicantInterfaceCallback callback;
6105         void *user_data;
6106 };
6107
6108 static void interface_mesh_change_peer_params(DBusMessageIter *iter,
6109                                                 void *user_data)
6110 {
6111         struct interface_mesh_peer_data *data = user_data;
6112
6113         SUPPLICANT_DBG("");
6114
6115         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->peer_address);
6116 }
6117
6118 static void interface_mesh_change_peer_result(const char *error,
6119                                 DBusMessageIter *iter, void *user_data)
6120 {
6121         struct interface_mesh_peer_data *data = user_data;
6122         int err = 0;
6123
6124         SUPPLICANT_DBG("%s", data->method);
6125
6126         if (error) {
6127                 err = -EIO;
6128                 SUPPLICANT_DBG("error %s", error);
6129         }
6130
6131         if (data->callback)
6132                 data->callback(err, data->interface, data->user_data);
6133
6134         g_free(data->peer_address);
6135         g_free(data->method);
6136         dbus_free(data);
6137 }
6138
6139 int g_supplicant_interface_mesh_peer_change_status(
6140                                 GSupplicantInterface *interface,
6141                                 GSupplicantInterfaceCallback callback, const char *peer_address,
6142                                 const char *method, void *user_data)
6143 {
6144         struct interface_mesh_peer_data *data;
6145         int ret;
6146
6147         if (!peer_address)
6148                 return -EINVAL;
6149
6150         data = dbus_malloc0(sizeof(*data));
6151         if (!data)
6152                 return -ENOMEM;
6153
6154         data->peer_address = g_strdup(peer_address);
6155         data->method = g_strdup(method);
6156         data->interface = interface;
6157         data->callback = callback;
6158         data->user_data = user_data;
6159
6160         ret = supplicant_dbus_method_call(interface->path,
6161                                                 SUPPLICANT_INTERFACE ".Interface.Mesh",
6162                                                 method, interface_mesh_change_peer_params,
6163                                                 interface_mesh_change_peer_result, data, NULL);
6164         if (ret < 0) {
6165                 g_free(data->peer_address);
6166                 g_free(data->method);
6167                 dbus_free(data);
6168         }
6169
6170         return ret;
6171 }
6172 #endif
6173
6174 int g_supplicant_interface_create(const char *ifname, const char *driver,
6175                                         const char *bridge,
6176 #ifdef TIZEN_EXT
6177                                         unsigned int mac_policy,
6178                                         unsigned int preassoc_mac_policy,
6179                                         unsigned int random_mac_lifetime,
6180 #endif /* TIZEN_EXT */
6181                                         GSupplicantInterfaceCallback callback,
6182                                                         void *user_data)
6183 {
6184         struct interface_create_data *data;
6185         int ret;
6186
6187         SUPPLICANT_DBG("ifname %s", ifname);
6188
6189         if (!ifname)
6190                 return -EINVAL;
6191
6192         if (!system_available)
6193                 return -EFAULT;
6194
6195         data = dbus_malloc0(sizeof(*data));
6196         if (!data)
6197                 return -ENOMEM;
6198
6199         data->ifname = g_strdup(ifname);
6200         data->driver = g_strdup(driver);
6201         data->bridge = g_strdup(bridge);
6202         data->callback = callback;
6203 #ifdef TIZEN_EXT
6204         data->mac_addr = mac_policy;
6205         data->preassoc_mac_addr = preassoc_mac_policy;
6206         data->random_mac_lifetime = random_mac_lifetime;
6207 #endif /* TIZEN_EXT */
6208         data->user_data = user_data;
6209
6210         ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
6211                                                 SUPPLICANT_INTERFACE,
6212                                                 "GetInterface",
6213                                                 interface_get_params,
6214                                                 interface_get_result, data,
6215                                                 NULL);
6216         if (ret < 0)
6217                 interface_create_data_free(data);
6218
6219         return ret;
6220 }
6221
6222 static void interface_remove_result(const char *error,
6223                                 DBusMessageIter *iter, void *user_data)
6224 {
6225         struct interface_data *data = user_data;
6226         int err;
6227
6228         if (error) {
6229                 err = -EIO;
6230                 SUPPLICANT_DBG("error: %s", error);
6231                 goto done;
6232         }
6233
6234         if (!system_available) {
6235                 err = -EFAULT;
6236                 goto done;
6237         }
6238
6239         /*
6240          * The gsupplicant interface is already freed by the InterfaceRemoved
6241          * signal callback. Simply invoke the interface_data callback.
6242          */
6243         err = 0;
6244
6245 done:
6246         g_free(data->path);
6247
6248         if (data->callback)
6249                 data->callback(err, NULL, data->user_data);
6250
6251         dbus_free(data);
6252 }
6253
6254
6255 static void interface_remove_params(DBusMessageIter *iter, void *user_data)
6256 {
6257         struct interface_data *data = user_data;
6258
6259         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
6260                                                         &data->interface->path);
6261 }
6262
6263 int g_supplicant_interface_remove(GSupplicantInterface *interface,
6264                         GSupplicantInterfaceCallback callback,
6265                                                         void *user_data)
6266 {
6267         struct interface_data *data;
6268         int ret;
6269
6270         if (!interface)
6271                 return -EINVAL;
6272
6273         if (!system_available)
6274                 return -EFAULT;
6275
6276         g_supplicant_interface_cancel(interface);
6277
6278         data = dbus_malloc0(sizeof(*data));
6279         if (!data)
6280                 return -ENOMEM;
6281
6282         data->interface = interface;
6283         data->path = g_strdup(interface->path);
6284         data->callback = callback;
6285         data->user_data = user_data;
6286
6287         ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
6288                                                 SUPPLICANT_INTERFACE,
6289                                                 "RemoveInterface",
6290                                                 interface_remove_params,
6291                                                 interface_remove_result, data,
6292                                                 NULL);
6293         if (ret < 0) {
6294                 g_free(data->path);
6295                 dbus_free(data);
6296         }
6297         return ret;
6298 }
6299
6300 static void interface_scan_result(const char *error,
6301                                 DBusMessageIter *iter, void *user_data)
6302 {
6303         struct interface_scan_data *data = user_data;
6304         int err = 0;
6305
6306         if (error) {
6307                 SUPPLICANT_DBG("error %s", error);
6308                 err = -EIO;
6309         }
6310
6311         /* A non ready interface cannot send/receive anything */
6312         if (interface_exists(data->interface, data->path)) {
6313                 if (!data->interface->ready)
6314                         err = -ENOLINK;
6315         }
6316
6317         g_free(data->path);
6318
6319         if (err != 0) {
6320                 if (data->callback)
6321                         data->callback(err, data->interface, data->user_data);
6322         } else {
6323                 data->interface->scan_callback = data->callback;
6324                 data->interface->scan_data = data->user_data;
6325         }
6326
6327         if (data->scan_params)
6328                 g_supplicant_free_scan_params(data->scan_params);
6329
6330         dbus_free(data);
6331 }
6332
6333 static void add_scan_frequency(DBusMessageIter *iter, unsigned int freq)
6334 {
6335         DBusMessageIter data;
6336         unsigned int width = 0; /* Not used by wpa_supplicant atm */
6337
6338         dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &data);
6339
6340         dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &freq);
6341         dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &width);
6342
6343         dbus_message_iter_close_container(iter, &data);
6344 }
6345
6346 static void add_scan_frequencies(DBusMessageIter *iter,
6347                                                 void *user_data)
6348 {
6349         GSupplicantScanParams *scan_data = user_data;
6350         unsigned int freq;
6351         int i;
6352
6353         for (i = 0; i < scan_data->num_freqs; i++) {
6354                 freq = scan_data->freqs[i];
6355                 if (!freq)
6356                         break;
6357
6358                 add_scan_frequency(iter, freq);
6359         }
6360 }
6361
6362 static void append_ssid(DBusMessageIter *iter,
6363                         const void *ssid, unsigned int len)
6364 {
6365         DBusMessageIter array;
6366
6367         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
6368         DBUS_TYPE_BYTE_AS_STRING, &array);
6369
6370         dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
6371                                                                 &ssid, len);
6372         dbus_message_iter_close_container(iter, &array);
6373 }
6374
6375 static void append_ssids(DBusMessageIter *iter, void *user_data)
6376 {
6377         GSupplicantScanParams *scan_data = user_data;
6378         GSList *list;
6379
6380         for (list = scan_data->ssids; list; list = list->next) {
6381                 struct scan_ssid *scan_ssid = list->data;
6382
6383                 append_ssid(iter, scan_ssid->ssid, scan_ssid->ssid_len);
6384         }
6385 }
6386
6387 static void supplicant_add_scan_frequency(DBusMessageIter *dict,
6388                 supplicant_dbus_array_function function,
6389                                         void *user_data)
6390 {
6391         GSupplicantScanParams *scan_params = user_data;
6392         DBusMessageIter entry, value, array;
6393         const char *key = "Channels";
6394
6395         if (scan_params->freqs && scan_params->freqs[0] != 0) {
6396                 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
6397                                                 NULL, &entry);
6398
6399                 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
6400
6401                 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
6402                                         DBUS_TYPE_ARRAY_AS_STRING
6403                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
6404                                         DBUS_TYPE_UINT32_AS_STRING
6405                                         DBUS_TYPE_UINT32_AS_STRING
6406                                         DBUS_STRUCT_END_CHAR_AS_STRING,
6407                                         &value);
6408
6409                 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
6410                                         DBUS_STRUCT_BEGIN_CHAR_AS_STRING
6411                                         DBUS_TYPE_UINT32_AS_STRING
6412                                         DBUS_TYPE_UINT32_AS_STRING
6413                                         DBUS_STRUCT_END_CHAR_AS_STRING,
6414                                         &array);
6415
6416                 if (function)
6417                         function(&array, user_data);
6418
6419                 dbus_message_iter_close_container(&value, &array);
6420                 dbus_message_iter_close_container(&entry, &value);
6421                 dbus_message_iter_close_container(dict, &entry);
6422         }
6423 }
6424
6425 static void interface_scan_params(DBusMessageIter *iter, void *user_data)
6426 {
6427         DBusMessageIter dict;
6428         const char *type = "passive";
6429         struct interface_scan_data *data = user_data;
6430
6431         supplicant_dbus_dict_open(iter, &dict);
6432
6433         if (data && data->scan_params) {
6434                 type = "active";
6435
6436                 supplicant_dbus_dict_append_basic(&dict, "Type",
6437                                         DBUS_TYPE_STRING, &type);
6438
6439 #if defined TIZEN_EXT
6440                 SUPPLICANT_DBG("[specific_scan] num_ssids %d",
6441                                data->scan_params->num_ssids);
6442 #endif
6443
6444                 if (data->scan_params->ssids) {
6445                         supplicant_dbus_dict_append_array(&dict, "SSIDs",
6446                                                         DBUS_TYPE_STRING,
6447                                                         append_ssids,
6448                                                         data->scan_params);
6449                 }
6450                 supplicant_add_scan_frequency(&dict, add_scan_frequencies,
6451                                                 data->scan_params);
6452         } else
6453                 supplicant_dbus_dict_append_basic(&dict, "Type",
6454                                         DBUS_TYPE_STRING, &type);
6455
6456         supplicant_dbus_dict_close(iter, &dict);
6457 }
6458
6459 static int interface_ready_to_scan(GSupplicantInterface *interface)
6460 {
6461         if (!interface)
6462                 return -EINVAL;
6463
6464         if (!system_available)
6465                 return -EFAULT;
6466
6467         if (interface->scanning)
6468                 return -EALREADY;
6469
6470         switch (interface->state) {
6471         case G_SUPPLICANT_STATE_AUTHENTICATING:
6472         case G_SUPPLICANT_STATE_ASSOCIATING:
6473         case G_SUPPLICANT_STATE_ASSOCIATED:
6474         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
6475         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
6476                 return -EBUSY;
6477 #if defined TIZEN_EXT
6478         case G_SUPPLICANT_STATE_DISABLED:
6479                 return -ENOLINK;
6480         case G_SUPPLICANT_STATE_UNKNOWN:
6481 #else
6482         case G_SUPPLICANT_STATE_UNKNOWN:
6483         case G_SUPPLICANT_STATE_DISABLED:
6484 #endif
6485         case G_SUPPLICANT_STATE_DISCONNECTED:
6486         case G_SUPPLICANT_STATE_INACTIVE:
6487         case G_SUPPLICANT_STATE_SCANNING:
6488         case G_SUPPLICANT_STATE_COMPLETED:
6489                 break;
6490         }
6491
6492         return 0;
6493 }
6494
6495 #if defined TIZEN_EXT_WIFI_MESH
6496 static void interface_abort_scan_result(const char *error,
6497                                 DBusMessageIter *iter, void *user_data)
6498 {
6499         struct interface_scan_data *data = user_data;
6500         int err = 0;
6501
6502         if (error) {
6503                 SUPPLICANT_DBG("error %s", error);
6504                 err = -EIO;
6505         }
6506
6507         g_free(data->path);
6508
6509                 if (data->callback)
6510                         data->callback(err, data->interface, data->user_data);
6511
6512         dbus_free(data);
6513 }
6514
6515 int g_supplicant_interface_abort_scan(GSupplicantInterface *interface,
6516                                 GSupplicantInterfaceCallback callback, void *user_data)
6517 {
6518         struct interface_scan_data *data;
6519         int ret;
6520
6521         if (!interface->scanning)
6522                 return -EEXIST;
6523
6524         data = dbus_malloc0(sizeof(*data));
6525         if (!data)
6526                 return -ENOMEM;
6527
6528         data->interface = interface;
6529         data->path = g_strdup(interface->path);
6530         data->callback = callback;
6531         data->user_data = user_data;
6532
6533         ret = supplicant_dbus_method_call(interface->path,
6534                         SUPPLICANT_INTERFACE ".Interface", "AbortScan", NULL,
6535                         interface_abort_scan_result, data, interface);
6536
6537         if (ret < 0) {
6538                 g_free(data->path);
6539                 dbus_free(data);
6540         }
6541
6542         return ret;
6543 }
6544 #endif
6545
6546 int g_supplicant_interface_scan(GSupplicantInterface *interface,
6547                                 GSupplicantScanParams *scan_data,
6548                                 GSupplicantInterfaceCallback callback,
6549                                                         void *user_data)
6550 {
6551         struct interface_scan_data *data;
6552         int ret;
6553
6554         ret = interface_ready_to_scan(interface);
6555         if (ret)
6556                 return ret;
6557
6558         data = dbus_malloc0(sizeof(*data));
6559         if (!data)
6560                 return -ENOMEM;
6561
6562         data->interface = interface;
6563         data->path = g_strdup(interface->path);
6564 #if defined TIZEN_EXT
6565         data->interface->scan_callback = data->callback = callback;
6566         data->interface->scan_data = data->user_data = user_data;
6567 #else
6568         data->callback = callback;
6569         data->user_data = user_data;
6570 #endif
6571         data->scan_params = scan_data;
6572
6573         interface->scan_callback = callback;
6574         interface->scan_data = user_data;
6575
6576         ret = supplicant_dbus_method_call(interface->path,
6577                         SUPPLICANT_INTERFACE ".Interface", "Scan",
6578                         interface_scan_params, interface_scan_result, data,
6579                         interface);
6580
6581         if (ret < 0) {
6582                 g_free(data->path);
6583                 dbus_free(data);
6584         }
6585
6586         return ret;
6587 }
6588
6589 #if defined TIZEN_EXT
6590 static void interface_signalpoll_result(const char *error,
6591                                 DBusMessageIter *iter, void *user_data)
6592 {
6593         struct interface_signalpoll_data *data = user_data;
6594         int err = 0;
6595         dbus_int32_t maxspeed = 0;
6596         dbus_int32_t strength = 0;
6597         dbus_int32_t snr = 0;
6598         dbus_uint32_t est_throughput = 0;
6599         DBusMessageIter sub_iter, dict;
6600
6601         if (error) {
6602                 err = -EIO;
6603                 SUPPLICANT_DBG("error: %s", error);
6604                 goto out;
6605         }
6606
6607         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) {
6608                 err = -EINVAL;
6609                 SUPPLICANT_DBG("invalid reply");
6610                 goto out;
6611         }
6612
6613         dbus_message_iter_recurse(iter, &sub_iter);
6614         dbus_message_iter_recurse(&sub_iter, &dict);
6615
6616         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
6617                 DBusMessageIter entry, value;
6618                 const char *key;
6619
6620                 dbus_message_iter_recurse(&dict, &entry);
6621                 dbus_message_iter_get_basic(&entry, &key);
6622                 dbus_message_iter_next(&entry);
6623                 dbus_message_iter_recurse(&entry, &value);
6624
6625                 switch (dbus_message_iter_get_arg_type(&value)) {
6626                 case DBUS_TYPE_INT32:
6627                         if (g_strcmp0(key, "linkspeed") == 0) {
6628                                 dbus_message_iter_get_basic(&value, &maxspeed);
6629                                 SUPPLICANT_DBG("linkspeed = %d", maxspeed);
6630                         } else if (g_strcmp0(key, "rssi") == 0) {
6631                                 dbus_message_iter_get_basic(&value, &strength);
6632                                 SUPPLICANT_DBG("Strength = %d", strength);
6633                         } else if (g_strcmp0(key, "SNR") == 0) {
6634                                 dbus_message_iter_get_basic(&value, &snr);
6635                                 SUPPLICANT_DBG("SNR = %d", snr);
6636                         }
6637                         break;
6638                 case DBUS_TYPE_UINT32:
6639                         if (g_strcmp0(key, "est_throughput") == 0) {
6640                                 dbus_message_iter_get_basic(&value, &est_throughput);
6641                                 SUPPLICANT_DBG("est_throughput = %u", est_throughput);
6642                         }
6643                         break;
6644                 }
6645                 dbus_message_iter_next(&dict);
6646         }
6647
6648 out:
6649         if(data->callback)
6650                 data->callback(err, maxspeed, strength, snr, data->user_data, est_throughput);
6651
6652         g_free(data->path);
6653         dbus_free(data);
6654 }
6655
6656 int g_supplicant_interface_signalpoll(GSupplicantInterface *interface,
6657                                 GSupplicantMaxSpeedCallback callback,
6658                                 void *user_data)
6659 {
6660         struct interface_signalpoll_data *data;
6661         int ret;
6662
6663         if (!interface)
6664                 return -EINVAL;
6665
6666         if (!system_available)
6667                 return -EFAULT;
6668
6669         data = dbus_malloc0(sizeof(*data));
6670         if (!data)
6671                 return -ENOMEM;
6672
6673         data->interface = interface;
6674         data->path = g_strdup(interface->path);
6675         data->callback = callback;
6676         data->user_data = user_data;
6677
6678         ret = supplicant_dbus_method_call(interface->path,
6679                         SUPPLICANT_INTERFACE ".Interface", "SignalPoll",
6680                         NULL, interface_signalpoll_result, data,
6681                         interface);
6682
6683         if (ret < 0) {
6684                 g_free(data->path);
6685                 dbus_free(data);
6686         }
6687
6688         return ret;
6689 }
6690 #endif
6691
6692 static int parse_supplicant_error(DBusMessageIter *iter)
6693 {
6694         int err = -ECONNABORTED;
6695         char *key;
6696
6697         if (!iter)
6698                 return err;
6699
6700         /* If the given passphrase is malformed wpa_s returns
6701          * "invalid message format" but this error should be interpreted as
6702          * invalid-key.
6703          */
6704         while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
6705                 dbus_message_iter_get_basic(iter, &key);
6706                 if (strncmp(key, "psk", 3) == 0 ||
6707                                 strncmp(key, "wep_key", 7) == 0 ||
6708                                 strcmp(key, "invalid message format") == 0) {
6709                         err = -ENOKEY;
6710                         break;
6711                 }
6712                 dbus_message_iter_next(iter);
6713         }
6714
6715         return err;
6716 }
6717
6718 static void interface_select_network_result(const char *error,
6719                                 DBusMessageIter *iter, void *user_data)
6720 {
6721         struct interface_connect_data *data = user_data;
6722         int err;
6723
6724         SUPPLICANT_DBG("");
6725
6726         err = 0;
6727         if (error) {
6728 #if defined TIZEN_EXT
6729                 SUPPLICANT_DBG("SelectNetwork errorFreq %s", error);
6730 #else
6731                 SUPPLICANT_DBG("SelectNetwork error %s", error);
6732 #endif
6733                 err = parse_supplicant_error(iter);
6734         }
6735
6736         g_free(data->path);
6737
6738         if (data->callback)
6739                 data->callback(err, data->interface, data->user_data);
6740
6741 #if defined TIZEN_EXT
6742         g_free(data->ssid->ssid);
6743         if (data->ssid->is_passphrase_alloc)
6744                 g_free((char *)data->ssid->passphrase);
6745         if (data->ssid->is_connector_alloc)
6746                 g_free((char *)data->ssid->connector);
6747         if (data->ssid->is_c_sign_key_alloc)
6748                 g_free((char *)data->ssid->c_sign_key);
6749         if (data->ssid->is_net_access_key_alloc)
6750                 g_free((char *)data->ssid->net_access_key);
6751 #endif
6752         g_free(data->ssid);
6753         dbus_free(data);
6754 }
6755
6756 static void interface_select_network_params(DBusMessageIter *iter,
6757                                                         void *user_data)
6758 {
6759         struct interface_connect_data *data = user_data;
6760         GSupplicantInterface *interface = data->interface;
6761 #if defined TIZEN_EXT
6762         GSupplicantSSID *ssid = data->ssid;
6763 #endif
6764
6765         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
6766                                         &interface->network_path);
6767 #if defined TIZEN_EXT
6768         if (!ssid->bssid_for_connect_len)
6769                 dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
6770 #endif
6771 }
6772
6773 static void interface_add_network_result(const char *error,
6774                                 DBusMessageIter *iter, void *user_data)
6775 {
6776         struct interface_connect_data *data = user_data;
6777         GSupplicantInterface *interface = data->interface;
6778         const char *path;
6779         int err;
6780
6781         if (error)
6782                 goto error;
6783
6784         dbus_message_iter_get_basic(iter, &path);
6785         if (!path)
6786                 goto error;
6787
6788         SUPPLICANT_DBG("PATH: %s", path);
6789
6790 #if defined TIZEN_EXT
6791         if (interface->network_path)
6792                 g_free(interface->network_path);
6793 #endif
6794         interface->network_path = g_strdup(path);
6795
6796         store_network_information(interface, data->ssid);
6797
6798 #if defined TIZEN_EXT
6799         SUPPLICANT_DBG(".Interface.SelectNetworkFreq");
6800         GSupplicantSSID *ssid = data->ssid;
6801
6802         if (!ssid->bssid_for_connect_len)
6803                 supplicant_dbus_method_call(data->interface->path,
6804                                 SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq",
6805                                 interface_select_network_params,
6806                                 interface_select_network_result, data,
6807                                 interface);
6808         else
6809                 supplicant_dbus_method_call(data->interface->path,
6810                                 SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
6811                                 interface_select_network_params,
6812                                 interface_select_network_result, data,
6813                                 interface);
6814 #else
6815         supplicant_dbus_method_call(data->interface->path,
6816                         SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
6817                         interface_select_network_params,
6818                         interface_select_network_result, data,
6819                         interface);
6820 #endif
6821
6822         return;
6823
6824 error:
6825         SUPPLICANT_DBG("AddNetwork error %s", error);
6826
6827         if (interface_exists(data->interface, data->interface->path)) {
6828                 err = parse_supplicant_error(iter);
6829                 if (data->callback)
6830                         data->callback(err, data->interface, data->user_data);
6831
6832                 g_free(interface->network_path);
6833                 interface->network_path = NULL;
6834         }
6835
6836         g_free(data->path);
6837 #if defined TIZEN_EXT
6838         g_free(data->ssid->ssid);
6839         if (data->ssid->is_passphrase_alloc)
6840                 g_free((char *)data->ssid->passphrase);
6841         if (data->ssid->is_connector_alloc)
6842                 g_free((char *)data->ssid->connector);
6843         if (data->ssid->is_c_sign_key_alloc)
6844                 g_free((char *)data->ssid->c_sign_key);
6845         if (data->ssid->is_net_access_key_alloc)
6846                 g_free((char *)data->ssid->net_access_key);
6847 #endif
6848         g_free(data->ssid);
6849         g_free(data);
6850 }
6851
6852 static void add_network_security_none(DBusMessageIter *dict)
6853 {
6854         const char *auth_alg = "OPEN";
6855
6856         supplicant_dbus_dict_append_basic(dict, "auth_alg",
6857                                         DBUS_TYPE_STRING, &auth_alg);
6858 }
6859
6860 static void add_network_security_wep(DBusMessageIter *dict,
6861                                         GSupplicantSSID *ssid)
6862 {
6863         const char *auth_alg = "OPEN SHARED";
6864         dbus_uint32_t key_index = 0;
6865
6866         supplicant_dbus_dict_append_basic(dict, "auth_alg",
6867                                         DBUS_TYPE_STRING, &auth_alg);
6868
6869         if (ssid->passphrase) {
6870                 int size = strlen(ssid->passphrase);
6871                 if (size == 10 || size == 26) {
6872                         unsigned char *key = g_try_malloc(13);
6873                         char tmp[3];
6874                         int i;
6875
6876                         memset(tmp, 0, sizeof(tmp));
6877                         if (!key)
6878                                 size = 0;
6879
6880                         for (i = 0; i < size / 2; i++) {
6881                                 memcpy(tmp, ssid->passphrase + (i * 2), 2);
6882                                 key[i] = (unsigned char) strtol(tmp, NULL, 16);
6883                         }
6884
6885                         supplicant_dbus_dict_append_fixed_array(dict,
6886                                                         "wep_key0",
6887                                                         DBUS_TYPE_BYTE,
6888                                                         &key, size / 2);
6889                         g_free(key);
6890                 } else if (size == 5 || size == 13) {
6891                         unsigned char *key = g_try_malloc(13);
6892                         int i;
6893
6894                         if (!key)
6895                                 size = 0;
6896
6897                         for (i = 0; i < size; i++)
6898                                 key[i] = (unsigned char) ssid->passphrase[i];
6899
6900                         supplicant_dbus_dict_append_fixed_array(dict,
6901                                                                 "wep_key0",
6902                                                                 DBUS_TYPE_BYTE,
6903                                                                 &key, size);
6904                         g_free(key);
6905                 } else
6906                         supplicant_dbus_dict_append_basic(dict,
6907                                                         "wep_key0",
6908                                                         DBUS_TYPE_STRING,
6909                                                         &ssid->passphrase);
6910
6911                 supplicant_dbus_dict_append_basic(dict, "wep_tx_keyidx",
6912                                         DBUS_TYPE_UINT32, &key_index);
6913         }
6914 }
6915
6916 static dbus_bool_t is_psk_raw_key(const char *psk)
6917 {
6918         int i;
6919
6920         /* A raw key is always 64 bytes length... */
6921         if (strlen(psk) != 64)
6922                 return FALSE;
6923
6924         /* ... and its content is in hex representation */
6925         for (i = 0; i < 64; i++)
6926                 if (!isxdigit((unsigned char) psk[i]))
6927                         return FALSE;
6928
6929         return TRUE;
6930 }
6931
6932 static unsigned char hexchar2bin(char c)
6933 {
6934         if ((c >= '0') && (c <= '9'))
6935                 return c - '0';
6936         else if ((c >= 'A') && (c <= 'F'))
6937                 return c - 'A' + 10;
6938         else if ((c >= 'a') && (c <= 'f'))
6939                 return c - 'a' + 10;
6940         else
6941                 return c;
6942 }
6943
6944 static void hexstring2bin(const char *string, unsigned char *data,
6945                                 size_t data_len)
6946 {
6947         size_t i;
6948
6949         for (i = 0; i < data_len; i++)
6950                 data[i] = (hexchar2bin(string[i * 2 + 0]) << 4 |
6951                            hexchar2bin(string[i * 2 + 1]) << 0);
6952 }
6953
6954 static void add_network_security_psk(DBusMessageIter *dict,
6955                                         GSupplicantSSID *ssid)
6956 {
6957         if (ssid->passphrase && strlen(ssid->passphrase) > 0) {
6958                 const char *key = "psk";
6959
6960                 if (is_psk_raw_key(ssid->passphrase)) {
6961                         unsigned char data[32];
6962                         unsigned char *datap = data;
6963
6964                         /* The above pointer alias is required by D-Bus because
6965                          * with D-Bus and GCC, non-heap-allocated arrays cannot
6966                          * be passed directly by their base pointer. */
6967
6968                         hexstring2bin(ssid->passphrase, datap, sizeof(data));
6969
6970                         supplicant_dbus_dict_append_fixed_array(dict,
6971                                                         key, DBUS_TYPE_BYTE,
6972                                                         &datap, sizeof(data));
6973                 } else
6974                         supplicant_dbus_dict_append_basic(dict,
6975                                                         key, DBUS_TYPE_STRING,
6976                                                         &ssid->passphrase);
6977         }
6978 }
6979
6980 static void add_network_security_tls(DBusMessageIter *dict,
6981                                         GSupplicantSSID *ssid)
6982 {
6983         /*
6984          * For TLS, we at least need:
6985          *              The client certificate
6986          *              The client private key file
6987          *              The client private key file password
6988          *
6989          * The Authority certificate is optional.
6990          */
6991         if (!ssid->client_cert_path)
6992                 return;
6993
6994         if (!ssid->private_key_path)
6995                 return;
6996
6997         if (!ssid->private_key_passphrase)
6998                 return;
6999
7000         if (ssid->ca_cert_path)
7001                 supplicant_dbus_dict_append_basic(dict, "ca_cert",
7002                                         DBUS_TYPE_STRING, &ssid->ca_cert_path);
7003
7004         supplicant_dbus_dict_append_basic(dict, "private_key",
7005                                                 DBUS_TYPE_STRING,
7006                                                 &ssid->private_key_path);
7007         supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
7008                                                 DBUS_TYPE_STRING,
7009                                                 &ssid->private_key_passphrase);
7010         supplicant_dbus_dict_append_basic(dict, "client_cert",
7011                                                 DBUS_TYPE_STRING,
7012                                                 &ssid->client_cert_path);
7013 }
7014
7015 static void add_network_security_peap(DBusMessageIter *dict,
7016                                         GSupplicantSSID *ssid)
7017 {
7018         char *phase2_auth;
7019
7020         /*
7021          * For PEAP/TTLS, we at least need
7022          *              The authority certificate
7023          *              The 2nd phase authentication method
7024          *              The 2nd phase passphrase
7025          *
7026          * The Client certificate is optional although strongly recommended
7027          * When setting it, we need in addition
7028          *              The Client private key file
7029          *              The Client private key file password
7030          */
7031         if (!ssid->passphrase)
7032                 return;
7033
7034         if (!ssid->phase2_auth)
7035                 return;
7036
7037         if (ssid->client_cert_path) {
7038                 if (!ssid->private_key_path)
7039                         return;
7040
7041 #if !defined TIZEN_EXT
7042                 if (!ssid->private_key_passphrase)
7043                         return;
7044 #endif
7045
7046                 supplicant_dbus_dict_append_basic(dict, "client_cert",
7047                                                 DBUS_TYPE_STRING,
7048                                                 &ssid->client_cert_path);
7049
7050                 supplicant_dbus_dict_append_basic(dict, "private_key",
7051                                                 DBUS_TYPE_STRING,
7052                                                 &ssid->private_key_path);
7053
7054 #if !defined TIZEN_EXT
7055                 supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
7056                                                 DBUS_TYPE_STRING,
7057                                                 &ssid->private_key_passphrase);
7058 #endif
7059
7060         }
7061
7062         if(g_strcmp0(ssid->phase2_auth, "GTC") == 0 && g_strcmp0(ssid->eap, "ttls") == 0)
7063                 phase2_auth = g_strdup_printf("autheap=%s", ssid->phase2_auth);
7064         else if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) {
7065                 phase2_auth = g_strdup_printf("autheap=%s",
7066                                         ssid->phase2_auth + strlen("EAP-"));
7067         } else
7068                 phase2_auth = g_strdup_printf("auth=%s", ssid->phase2_auth);
7069
7070         supplicant_dbus_dict_append_basic(dict, "password",
7071                                                 DBUS_TYPE_STRING,
7072                                                 &ssid->passphrase);
7073
7074         if (ssid->ca_cert_path)
7075                 supplicant_dbus_dict_append_basic(dict, "ca_cert",
7076                                                 DBUS_TYPE_STRING,
7077                                                 &ssid->ca_cert_path);
7078
7079         supplicant_dbus_dict_append_basic(dict, "phase2",
7080                                                 DBUS_TYPE_STRING,
7081                                                 &phase2_auth);
7082
7083         g_free(phase2_auth);
7084 }
7085
7086 #if defined TIZEN_EXT
7087 static void add_network_security_aka_sim(DBusMessageIter *dict,
7088                                         GSupplicantSSID *ssid)
7089 {
7090         if (!ssid->passphrase)
7091                 return;
7092
7093         supplicant_dbus_dict_append_basic(dict, "password",
7094                         DBUS_TYPE_STRING,
7095                         &ssid->passphrase);
7096 }
7097
7098 static void add_network_security_fast(DBusMessageIter *dict,
7099                 GSupplicantSSID *ssid)
7100 {
7101         /*
7102          * For FAST, we at least need:
7103          *              id / password
7104          *              phase1 (provisiong information)
7105          *              pac_file
7106          */
7107
7108         /* Allow provisioing both authenticated and unauthenticated */
7109         const char *phase1 = "fast_provisioning=2";
7110         supplicant_dbus_dict_append_basic(dict, "phase1",
7111                         DBUS_TYPE_STRING,
7112                         &phase1);
7113
7114         SUPPLICANT_DBG("pac_file [%s]", ssid->pac_file);
7115         if(ssid->pac_file)
7116                 supplicant_dbus_dict_append_basic(dict, "pac_file",
7117                                 DBUS_TYPE_STRING,
7118                                 &ssid->pac_file);
7119
7120         supplicant_dbus_dict_append_basic(dict, "password",
7121                         DBUS_TYPE_STRING,
7122                         &ssid->passphrase);
7123 }
7124 #endif
7125
7126 static void add_network_security_eap(DBusMessageIter *dict,
7127                                         GSupplicantSSID *ssid)
7128 {
7129         char *eap_value;
7130
7131 #if defined TIZEN_EXT
7132         if (!ssid->eap)
7133 #else
7134         if (!ssid->eap || !ssid->identity)
7135 #endif
7136                 return;
7137
7138         if (g_strcmp0(ssid->eap, "tls") == 0) {
7139                 add_network_security_tls(dict, ssid);
7140         } else if (g_strcmp0(ssid->eap, "peap") == 0 ||
7141                                 g_strcmp0(ssid->eap, "ttls") == 0) {
7142 #if defined TIZEN_EXT
7143                 if (!ssid->identity)
7144                         return;
7145 #endif
7146                 add_network_security_peap(dict, ssid);
7147
7148 #if defined TIZEN_EXT
7149         } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
7150                         g_strcmp0(ssid->eap, "aka") == 0 ||
7151                         g_strcmp0(ssid->eap, "aka'") == 0) {
7152                 add_network_security_aka_sim(dict, ssid);
7153         } else if (g_strcmp0(ssid->eap, "pwd") == 0) {
7154                 if(!ssid->passphrase)
7155                         return;
7156                 supplicant_dbus_dict_append_basic(dict, "password",
7157                                 DBUS_TYPE_STRING,
7158                                 &ssid->passphrase);
7159         } else if (g_strcmp0(ssid->eap, "fast") == 0){
7160                 if (!ssid->identity || !ssid->passphrase)
7161                         return;
7162
7163                 add_network_security_fast(dict, ssid);
7164 #endif
7165         } else
7166                 return;
7167
7168         eap_value = g_ascii_strup(ssid->eap, -1);
7169
7170         supplicant_dbus_dict_append_basic(dict, "eap",
7171                                                 DBUS_TYPE_STRING,
7172                                                 &eap_value);
7173 #if defined TIZEN_EXT
7174         if (ssid->identity != NULL)
7175                 supplicant_dbus_dict_append_basic(dict, "identity",
7176                                                         DBUS_TYPE_STRING,
7177                                                         &ssid->identity);
7178 #else
7179         supplicant_dbus_dict_append_basic(dict, "identity",
7180                                                 DBUS_TYPE_STRING,
7181                                                 &ssid->identity);
7182 #endif
7183         if(ssid->anonymous_identity)
7184                 supplicant_dbus_dict_append_basic(dict, "anonymous_identity",
7185                                                      DBUS_TYPE_STRING,
7186                                                      &ssid->anonymous_identity);
7187
7188         if(ssid->subject_match)
7189                 supplicant_dbus_dict_append_basic(dict, "subject_match",
7190                                                      DBUS_TYPE_STRING,
7191                                                      &ssid->subject_match);
7192
7193         if(ssid->altsubject_match)
7194                 supplicant_dbus_dict_append_basic(dict, "altsubject_match",
7195                                                      DBUS_TYPE_STRING,
7196                                                      &ssid->altsubject_match);
7197
7198         if(ssid->domain_suffix_match)
7199                 supplicant_dbus_dict_append_basic(dict, "domain_suffix_match",
7200                                                      DBUS_TYPE_STRING,
7201                                                      &ssid->domain_suffix_match);
7202
7203         if(ssid->domain_match)
7204                 supplicant_dbus_dict_append_basic(dict, "domain_match",
7205                                                      DBUS_TYPE_STRING,
7206                                                      &ssid->domain_match);
7207
7208         g_free(eap_value);
7209 }
7210
7211 static void add_network_security_ciphers(DBusMessageIter *dict,
7212                                                 GSupplicantSSID *ssid)
7213 {
7214         unsigned int p_cipher, g_cipher, i;
7215         char *pairwise, *group;
7216         char *pair_ciphers[4];
7217         char *group_ciphers[5];
7218
7219         p_cipher = ssid->pairwise_cipher;
7220         g_cipher = ssid->group_cipher;
7221
7222         if (p_cipher == 0 && g_cipher == 0)
7223                 return;
7224
7225         i = 0;
7226
7227         if (p_cipher & G_SUPPLICANT_PAIRWISE_CCMP)
7228                 pair_ciphers[i++] = "CCMP";
7229
7230         if (p_cipher & G_SUPPLICANT_PAIRWISE_TKIP)
7231                 pair_ciphers[i++] = "TKIP";
7232
7233         if (p_cipher & G_SUPPLICANT_PAIRWISE_NONE)
7234                 pair_ciphers[i++] = "NONE";
7235
7236         pair_ciphers[i] = NULL;
7237
7238         i = 0;
7239
7240         if (g_cipher & G_SUPPLICANT_GROUP_CCMP)
7241                 group_ciphers[i++] = "CCMP";
7242
7243         if (g_cipher & G_SUPPLICANT_GROUP_TKIP)
7244                 group_ciphers[i++] = "TKIP";
7245
7246         if (g_cipher & G_SUPPLICANT_GROUP_WEP104)
7247                 group_ciphers[i++] = "WEP104";
7248
7249         if (g_cipher & G_SUPPLICANT_GROUP_WEP40)
7250                 group_ciphers[i++] = "WEP40";
7251
7252         group_ciphers[i] = NULL;
7253
7254         pairwise = g_strjoinv(" ", pair_ciphers);
7255         group = g_strjoinv(" ", group_ciphers);
7256
7257         SUPPLICANT_DBG("cipher %s %s", pairwise, group);
7258
7259         supplicant_dbus_dict_append_basic(dict, "pairwise",
7260                                                 DBUS_TYPE_STRING,
7261                                                 &pairwise);
7262         supplicant_dbus_dict_append_basic(dict, "group",
7263                                                 DBUS_TYPE_STRING,
7264                                                 &group);
7265
7266         g_free(pairwise);
7267         g_free(group);
7268 }
7269
7270 static void add_network_security_proto(DBusMessageIter *dict,
7271                                                 GSupplicantSSID *ssid)
7272 {
7273         unsigned int protocol, i;
7274         char *proto;
7275         char *protos[3];
7276
7277         protocol = ssid->protocol;
7278
7279         if (protocol == 0)
7280                 return;
7281
7282         i = 0;
7283
7284         if (protocol & G_SUPPLICANT_PROTO_RSN)
7285                 protos[i++] = "RSN";
7286
7287         if (protocol & G_SUPPLICANT_PROTO_WPA)
7288                 protos[i++] = "WPA";
7289
7290         protos[i] = NULL;
7291
7292         proto = g_strjoinv(" ", protos);
7293
7294         SUPPLICANT_DBG("proto %s", proto);
7295
7296         supplicant_dbus_dict_append_basic(dict, "proto",
7297                                                 DBUS_TYPE_STRING,
7298                                                 &proto);
7299
7300         g_free(proto);
7301 }
7302
7303 #if defined TIZEN_EXT
7304 static void add_network_security_connector(DBusMessageIter *dict, GSupplicantSSID *ssid)
7305 {
7306         if (ssid->connector && strlen(ssid->connector) > 0) {
7307                 const char *key = "dpp_connector";
7308
7309                 supplicant_dbus_dict_append_basic(dict,
7310                                 key, DBUS_TYPE_STRING,
7311                                 &ssid->connector);
7312         }
7313 }
7314
7315 static size_t convert_hexstr_to_bin(const char *hex_str, unsigned char **bin)
7316 {
7317         unsigned char *bin_res = NULL;
7318         unsigned int i, j, hex;
7319         size_t hex_str_len;
7320
7321         if (!hex_str || strlen(hex_str) == 0)
7322                 return 0;
7323
7324         hex_str_len = strlen(hex_str);
7325         bin_res = g_try_malloc0(hex_str_len / 2);
7326         if (!bin_res)
7327                 return 0;
7328
7329         j = 0;
7330         for (i = 0; i < hex_str_len; i+=2) {
7331                 sscanf(hex_str + i, "%02x", &hex);
7332                 bin_res[j++] = hex;
7333         }
7334
7335         *bin = bin_res;
7336         return hex_str_len / 2;
7337 }
7338
7339 static void add_network_security_c_sign_key(DBusMessageIter *dict, GSupplicantSSID *ssid)
7340 {
7341         if (ssid->c_sign_key && strlen(ssid->c_sign_key) > 0) {
7342                 const char *key = "dpp_csign";
7343                 unsigned char *bin_csign = NULL;
7344                 size_t bin_csign_len = convert_hexstr_to_bin(ssid->c_sign_key, &bin_csign);
7345                 if  (bin_csign_len != 0)
7346                         supplicant_dbus_dict_append_fixed_array(dict,
7347                                         key, DBUS_TYPE_BYTE,
7348                                         &bin_csign, bin_csign_len);
7349                 g_free(bin_csign);
7350         }
7351 }
7352
7353 static void add_network_security_net_access_key(DBusMessageIter *dict, GSupplicantSSID *ssid)
7354 {
7355         if (ssid->net_access_key && strlen(ssid->net_access_key) > 0) {
7356                 const char *key = "dpp_netaccesskey";
7357                 unsigned char *bin_netaccesskey = NULL;
7358                 size_t bin_netaccesskey_len = convert_hexstr_to_bin(ssid->net_access_key, &bin_netaccesskey);
7359                 if  (bin_netaccesskey_len != 0)
7360                         supplicant_dbus_dict_append_fixed_array(dict,
7361                                         key, DBUS_TYPE_BYTE,
7362                                         &bin_netaccesskey, bin_netaccesskey_len);
7363                 g_free(bin_netaccesskey);
7364         }
7365 }
7366
7367 #endif
7368
7369 static void add_network_ieee80211w(DBusMessageIter *dict, GSupplicantSSID *ssid,
7370                                    GSupplicantMfpOptions ieee80211w)
7371 {
7372 #if defined TIZEN_EXT
7373         if (ssid->security != G_SUPPLICANT_SECURITY_OWE
7374                         && ssid->security != G_SUPPLICANT_SECURITY_PSK_SHA256
7375                         && ssid->security != G_SUPPLICANT_SECURITY_DPP)
7376                 return;
7377 #endif
7378         supplicant_dbus_dict_append_basic(dict, "ieee80211w", DBUS_TYPE_UINT32,
7379                                           &ieee80211w);
7380 }
7381
7382 static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
7383 {
7384         GSupplicantMfpOptions ieee80211w;
7385         char *key_mgmt;
7386
7387         switch (ssid->security) {
7388         case G_SUPPLICANT_SECURITY_NONE:
7389                 key_mgmt = "NONE";
7390                 add_network_security_none(dict);
7391                 add_network_security_ciphers(dict, ssid);
7392                 break;
7393         case G_SUPPLICANT_SECURITY_UNKNOWN:
7394         case G_SUPPLICANT_SECURITY_WEP:
7395                 key_mgmt = "NONE";
7396                 add_network_security_wep(dict, ssid);
7397                 add_network_security_ciphers(dict, ssid);
7398                 break;
7399         case G_SUPPLICANT_SECURITY_PSK:
7400 #if defined TIZEN_EXT
7401                 if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
7402                         key_mgmt = "FT-PSK WPA-PSK";
7403                 else
7404                         key_mgmt = "WPA-PSK";
7405 #else
7406                 key_mgmt = "WPA-PSK";
7407 #endif
7408                 add_network_security_psk(dict, ssid);
7409                 add_network_security_ciphers(dict, ssid);
7410                 add_network_security_proto(dict, ssid);
7411                 break;
7412         case G_SUPPLICANT_SECURITY_IEEE8021X:
7413                 key_mgmt = "WPA-EAP";
7414                 add_network_security_eap(dict, ssid);
7415                 add_network_security_ciphers(dict, ssid);
7416                 add_network_security_proto(dict, ssid);
7417                 break;
7418 #if defined TIZEN_EXT
7419         case G_SUPPLICANT_SECURITY_PSK_SHA256:
7420                 if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK)
7421                         key_mgmt = "WPA-PSK-SHA256 WPA-PSK";
7422                 else
7423                         key_mgmt = "WPA-PSK-SHA256";
7424                 add_network_security_psk(dict, ssid);
7425                 add_network_security_ciphers(dict, ssid);
7426                 add_network_security_proto(dict, ssid);
7427                 break;
7428         case G_SUPPLICANT_SECURITY_FT_PSK:
7429                 key_mgmt = "FT-PSK";
7430                 add_network_security_psk(dict, ssid);
7431                 add_network_security_ciphers(dict, ssid);
7432                 add_network_security_proto(dict, ssid);
7433                 break;
7434         case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
7435                 key_mgmt = "FT-EAP";
7436                 add_network_security_eap(dict, ssid);
7437                 add_network_security_ciphers(dict, ssid);
7438                 add_network_security_proto(dict, ssid);
7439                 break;
7440         case G_SUPPLICANT_SECURITY_SAE:
7441                 if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_FT_SAE) {
7442                         if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
7443                                 key_mgmt = "FT-SAE SAE";
7444                         else
7445                                 key_mgmt = "FT-SAE";
7446                 } else {
7447                         if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK) {
7448                         key_mgmt = "SAE WPA-PSK";
7449                         ieee80211w = G_SUPPLICANT_MFP_OPTIONAL;
7450                         } else {
7451                                 key_mgmt = "SAE";
7452                                 ieee80211w = G_SUPPLICANT_MFP_REQUIRED;
7453                         }
7454                         add_network_ieee80211w(dict, ssid, ieee80211w);
7455                 }
7456                 add_network_security_psk(dict, ssid);
7457                 break;
7458         case G_SUPPLICANT_SECURITY_OWE:
7459                 key_mgmt = "OWE";
7460                 add_network_security_ciphers(dict, ssid);
7461                 add_network_security_proto(dict, ssid);
7462                 break;
7463         case G_SUPPLICANT_SECURITY_DPP:
7464                 key_mgmt = "DPP";
7465                 add_network_security_connector(dict, ssid);
7466                 add_network_security_c_sign_key(dict, ssid);
7467                 add_network_security_net_access_key(dict, ssid);
7468                 break;
7469 #endif
7470         }
7471
7472         supplicant_dbus_dict_append_basic(dict, "key_mgmt",
7473                                 DBUS_TYPE_STRING, &key_mgmt);
7474 }
7475
7476 static void add_network_mode(DBusMessageIter *dict, GSupplicantSSID *ssid)
7477 {
7478         dbus_uint32_t mode;
7479
7480         switch (ssid->mode) {
7481         case G_SUPPLICANT_MODE_UNKNOWN:
7482         case G_SUPPLICANT_MODE_INFRA:
7483                 mode = 0;
7484                 break;
7485         case G_SUPPLICANT_MODE_IBSS:
7486                 mode = 1;
7487                 break;
7488         case G_SUPPLICANT_MODE_MASTER:
7489                 mode = 2;
7490                 break;
7491 #if defined TIZEN_EXT_WIFI_MESH
7492         case G_SUPPLICANT_MODE_MESH:
7493                 mode = 5;
7494                 break;
7495 #endif
7496         }
7497
7498         supplicant_dbus_dict_append_basic(dict, "mode",
7499                                 DBUS_TYPE_UINT32, &mode);
7500 }
7501
7502 static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
7503 {
7504         DBusMessageIter dict;
7505         struct interface_connect_data *data = user_data;
7506         GSupplicantSSID *ssid = data->ssid;
7507 #if defined TIZEN_EXT
7508         GSupplicantInterface *interface = data->interface;
7509 #endif
7510
7511         supplicant_dbus_dict_open(iter, &dict);
7512
7513         if (ssid->scan_ssid)
7514                 supplicant_dbus_dict_append_basic(&dict, "scan_ssid",
7515                                          DBUS_TYPE_UINT32, &ssid->scan_ssid);
7516
7517         if (ssid->freq)
7518                 supplicant_dbus_dict_append_basic(&dict, "frequency",
7519                                          DBUS_TYPE_UINT32, &ssid->freq);
7520
7521         if (ssid->bgscan)
7522                 supplicant_dbus_dict_append_basic(&dict, "bgscan",
7523                                         DBUS_TYPE_STRING, &ssid->bgscan);
7524
7525         add_network_mode(&dict, ssid);
7526
7527         add_network_security(&dict, ssid);
7528
7529         supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
7530                                         DBUS_TYPE_BYTE, &ssid->ssid,
7531                                                 ssid->ssid_len);
7532
7533 #if defined TIZEN_EXT
7534         bool owe_transition_mode = FALSE;
7535         if ((ssid->security == G_SUPPLICANT_SECURITY_OWE) && !(ssid->keymgmt & G_SUPPLICANT_KEYMGMT_OWE))
7536                 owe_transition_mode = TRUE;
7537
7538         if (ssid->bssid && !owe_transition_mode) {
7539                 char *bssid = NULL;
7540                 bssid = g_try_malloc0(18);
7541                 if (bssid == NULL) {
7542                         SUPPLICANT_DBG("memory allocation error");
7543                         supplicant_dbus_dict_close(iter, &dict);
7544                         return;
7545                 }
7546
7547                 if (ssid->bssid_for_connect_len) {
7548                         snprintf(bssid, 18, MACSTR, MAC2STR(ssid->bssid_for_connect));
7549                         memcpy(interface->add_network_bssid, ssid->bssid_for_connect, WIFI_BSSID_LEN_MAX);
7550                 } else {
7551                         snprintf(bssid, 18, MACSTR, MAC2STR(ssid->bssid));
7552                         memcpy(interface->add_network_bssid, ssid->bssid, WIFI_BSSID_LEN_MAX);
7553                 }
7554
7555                 SUPPLICANT_DBG("bssid [" MACSTR "]", MAC2STR(interface->add_network_bssid));
7556
7557                 supplicant_dbus_dict_append_basic(&dict, "bssid",
7558                                         DBUS_TYPE_STRING, &bssid);
7559                 g_free(bssid);
7560         }
7561 #endif
7562
7563         supplicant_dbus_dict_close(iter, &dict);
7564 }
7565
7566 static void interface_wps_start_result(const char *error,
7567                                 DBusMessageIter *iter, void *user_data)
7568 {
7569         struct interface_connect_data *data = user_data;
7570         int err;
7571
7572         SUPPLICANT_DBG("");
7573
7574         err = 0;
7575         if (error) {
7576                 SUPPLICANT_DBG("error: %s", error);
7577                 err = parse_supplicant_error(iter);
7578         }
7579
7580         if(data->callback)
7581                 data->callback(err, data->interface, data->user_data);
7582
7583         g_free(data->path);
7584         g_free(data->ssid);
7585         dbus_free(data);
7586 }
7587
7588 static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
7589 {
7590         struct interface_connect_data *data = user_data;
7591         GSupplicantSSID *ssid = data->ssid;
7592         const char *role = "enrollee", *type;
7593         DBusMessageIter dict;
7594
7595         SUPPLICANT_DBG("");
7596
7597         supplicant_dbus_dict_open(iter, &dict);
7598
7599         supplicant_dbus_dict_append_basic(&dict, "Role",
7600                                                 DBUS_TYPE_STRING, &role);
7601
7602         type = "pbc";
7603         if (ssid->pin_wps) {
7604                 type = "pin";
7605                 supplicant_dbus_dict_append_basic(&dict, "Pin",
7606                                         DBUS_TYPE_STRING, &ssid->pin_wps);
7607         }
7608
7609         supplicant_dbus_dict_append_basic(&dict, "Type",
7610                                         DBUS_TYPE_STRING, &type);
7611
7612 #if defined TIZEN_EXT
7613         if (ssid->bssid)
7614                 supplicant_dbus_dict_append_fixed_array(&dict, "Bssid",
7615                                                 DBUS_TYPE_BYTE, &ssid->bssid, 6);
7616 #endif
7617
7618         supplicant_dbus_dict_close(iter, &dict);
7619 }
7620
7621 static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
7622 {
7623         struct interface_connect_data *data = user_data;
7624
7625         SUPPLICANT_DBG("");
7626
7627         if (error) {
7628                 SUPPLICANT_DBG("error: %s", error);
7629                 g_free(data->path);
7630                 g_free(data->ssid);
7631                 dbus_free(data);
7632                 return;
7633         }
7634
7635 #if defined TIZEN_EXT
7636         GSupplicantSSID *ssid = data->ssid;
7637         if (ssid->pin_wps != NULL) {
7638                 if (!g_utf8_validate(ssid->pin_wps, 8, NULL)) {
7639                         SUPPLICANT_DBG("Invalid characters in WPS_PIN");
7640                         g_free(data->ssid);
7641                         dbus_free(data);
7642                         return;
7643                 }
7644         }
7645 #endif
7646         supplicant_dbus_method_call(data->interface->path,
7647                         SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
7648                         interface_add_wps_params,
7649                         interface_wps_start_result, data, NULL);
7650 }
7651
7652 static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
7653 {
7654         dbus_bool_t credentials = TRUE;
7655
7656         SUPPLICANT_DBG("");
7657
7658         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
7659 }
7660
7661
7662 #if defined TIZEN_EXT
7663 #define NETCONFIG_SERVICE "net.netconfig"
7664 #define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
7665 #define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
7666
7667 struct dec_method_call_data {
7668         struct interface_connect_data *data;
7669         DBusPendingCall *pending_call;
7670 };
7671
7672 static struct dec_method_call_data decrypt_request_data;
7673
7674 static void crypt_method_call_cancel(void)
7675 {
7676         if (decrypt_request_data.pending_call) {
7677                 dbus_pending_call_cancel(decrypt_request_data.pending_call);
7678                 dbus_pending_call_unref(decrypt_request_data.pending_call);
7679                 decrypt_request_data.pending_call = NULL;
7680         }
7681
7682         g_free(decrypt_request_data.data->path);
7683         g_free(decrypt_request_data.data->ssid);
7684         dbus_free(decrypt_request_data.data);
7685         decrypt_request_data.data = NULL;
7686 }
7687
7688 static void decryption_request_reply(DBusPendingCall *call,
7689                                                 void *user_data)
7690 {
7691         DBusMessage *reply;
7692         DBusError error;
7693         DBusMessageIter args;
7694         char *out_data;
7695         int ret;
7696         struct interface_connect_data *data = user_data;
7697
7698         SUPPLICANT_DBG("");
7699
7700         reply = dbus_pending_call_steal_reply(call);
7701
7702         dbus_error_init(&error);
7703         if (dbus_set_error_from_message(&error, reply)) {
7704                 SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message);
7705                 dbus_error_free(&error);
7706                 ret = -EINVAL;
7707                 goto done;
7708         }
7709
7710         if (!g_str_has_prefix(data->interface->path, "/")) {
7711                 SUPPLICANT_DBG("Invalid path %s", data->interface->path);
7712                 ret = -EINVAL;
7713                 goto done;
7714         }
7715
7716         if (dbus_message_iter_init(reply, &args) == FALSE) {
7717                 SUPPLICANT_DBG("dbus_message_iter_init() failed");
7718                 ret = -EINVAL;
7719                 goto done;
7720         }
7721
7722         dbus_message_iter_get_basic(&args, &out_data);
7723         data->ssid->passphrase = g_strdup((const gchar *)out_data);
7724         data->ssid->is_passphrase_alloc = true;
7725
7726         ret = supplicant_dbus_method_call(data->interface->path,
7727                 SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
7728                 interface_add_network_params,
7729                 interface_add_network_result, data,
7730                 data->interface);
7731
7732 done:
7733         if (ret < 0) {
7734                 SUPPLICANT_DBG("AddNetwork failed %d", ret);
7735                 callback_assoc_failed(decrypt_request_data.data->user_data);
7736                 g_free(data->path);
7737                 g_free(data->ssid->ssid);
7738                 if (data->ssid->is_passphrase_alloc)
7739                         g_free((char *)data->ssid->passphrase);
7740                 if (data->ssid->is_connector_alloc)
7741                         g_free((char *)data->ssid->connector);
7742                 if (data->ssid->is_c_sign_key_alloc)
7743                         g_free((char *)data->ssid->c_sign_key);
7744                 if (data->ssid->is_net_access_key_alloc)
7745                         g_free((char *)data->ssid->net_access_key);
7746                 g_free(data->ssid);
7747                 dbus_free(data);
7748         }
7749
7750         dbus_message_unref(reply);
7751         dbus_pending_call_unref(call);
7752
7753         decrypt_request_data.pending_call = NULL;
7754         decrypt_request_data.data = NULL;
7755 }
7756
7757 static int send_decryption_request(const char *passphrase,
7758                         struct interface_connect_data *data)
7759 {
7760         DBusMessage *msg = NULL;
7761         DBusPendingCall *call;
7762
7763         SUPPLICANT_DBG("Decryption request");
7764
7765         if (!passphrase) {
7766                 SUPPLICANT_DBG("Invalid parameter");
7767                 return -EINVAL;
7768         }
7769
7770         if (!connection)
7771                 return -EINVAL;
7772
7773         msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
7774                         NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase");
7775         if (!msg)
7776                 return -EINVAL;
7777
7778 #if defined TIZEN_EXT
7779         if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
7780                                                         DBUS_TYPE_INVALID)) {
7781                 SUPPLICANT_DBG("Could not fulfill decryption request");
7782                 return -ENOMEM;
7783         }
7784 #else
7785         dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
7786                                                         DBUS_TYPE_INVALID);
7787 #endif
7788
7789         if (!dbus_connection_send_with_reply(connection, msg,
7790                                 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
7791                 dbus_message_unref(msg);
7792                 return -EIO;
7793         }
7794
7795         if (!call) {
7796                 dbus_message_unref(msg);
7797                 return -EIO;
7798         }
7799
7800         decrypt_request_data.pending_call = call;
7801         decrypt_request_data.data = data;
7802
7803         dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL);
7804         dbus_message_unref(msg);
7805
7806         SUPPLICANT_DBG("Decryption request succeeded");
7807
7808         return 0;
7809 }
7810
7811 static void decrypt_conf_obj_reply(DBusPendingCall *call,
7812                                                 void *user_data)
7813 {
7814         DBusMessage *reply;
7815         DBusError error;
7816         DBusMessageIter iter, dict;
7817         char *out_data;
7818         int ret;
7819         struct interface_connect_data *data = user_data;
7820
7821         reply = dbus_pending_call_steal_reply(call);
7822
7823         dbus_error_init(&error);
7824         if (dbus_set_error_from_message(&error, reply)) {
7825                 SUPPLICANT_DBG("decryption_conf_obj_reply() %s %s", error.name, error.message);
7826                 dbus_error_free(&error);
7827                 ret = -EINVAL;
7828                 goto done;
7829         }
7830
7831         if (dbus_message_iter_init(reply, &iter) == FALSE) {
7832                 SUPPLICANT_DBG("dbus_message_iter_init() failed");
7833                 ret = -EINVAL;
7834                 goto done;
7835         }
7836
7837         dbus_message_iter_recurse(&iter, &dict);
7838
7839         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
7840                 DBusMessageIter entry, value;
7841                 const char *key;
7842
7843                 dbus_message_iter_recurse(&dict, &entry);
7844                 dbus_message_iter_get_basic(&entry, &key);
7845                 dbus_message_iter_next(&entry);
7846                 dbus_message_iter_recurse(&entry, &value);
7847                 if (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) {
7848                         if (g_strcmp0(key, "connector") == 0) {
7849                                 dbus_message_iter_get_basic(&value, &out_data);
7850                                 data->ssid->connector = g_strdup((const gchar *)out_data);
7851                                 data->ssid->is_connector_alloc = true;
7852                                 SUPPLICANT_DBG("connector %s", data->ssid->connector);
7853                         } else if (g_strcmp0(key, "c_sign_key") == 0) {
7854                                 dbus_message_iter_get_basic(&value, &out_data);
7855                                 data->ssid->c_sign_key = g_strdup((const gchar *)out_data);
7856                                 data->ssid->is_c_sign_key_alloc = true;
7857                                 SUPPLICANT_DBG("c_sign_key %s", data->ssid->c_sign_key);
7858                         } else if (g_strcmp0(key, "net_access_key") == 0) {
7859                                 dbus_message_iter_get_basic(&value, &out_data);
7860                                 data->ssid->net_access_key = g_strdup((const gchar *)out_data);
7861                                 data->ssid->is_net_access_key_alloc = true;
7862                                 SUPPLICANT_DBG("net_access_key %s", data->ssid->net_access_key);
7863                         }
7864                 }
7865                 dbus_message_iter_next(&dict);
7866         }
7867
7868         ret = supplicant_dbus_method_call(data->interface->path,
7869                 SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
7870                 interface_add_network_params,
7871                 interface_add_network_result, data,
7872                 data->interface);
7873
7874 done:
7875         if (ret < 0) {
7876                 SUPPLICANT_DBG("AddNetwork failed %d", ret);
7877                 callback_assoc_failed(decrypt_request_data.data->user_data);
7878                 g_free(data->path);
7879                 g_free(data->ssid->ssid);
7880                 if (data->ssid->is_connector_alloc)
7881                         g_free((char *)data->ssid->connector);
7882                 if (data->ssid->is_c_sign_key_alloc)
7883                         g_free((char *)data->ssid->c_sign_key);
7884                 if (data->ssid->is_net_access_key_alloc)
7885                         g_free((char *)data->ssid->net_access_key);
7886                 g_free(data->ssid);
7887                 dbus_free(data);
7888         }
7889
7890         dbus_message_unref(reply);
7891         dbus_pending_call_unref(call);
7892
7893         decrypt_request_data.pending_call = NULL;
7894         decrypt_request_data.data = NULL;
7895 }
7896
7897 static int send_decryption_conf_obj_request(GSupplicantSSID *ssid,
7898                         struct interface_connect_data *data)
7899 {
7900         DBusMessage *msg = NULL;
7901         DBusPendingCall *call;
7902
7903         SUPPLICANT_DBG("Decryption configuration object request");
7904
7905         if (!ssid) {
7906                 SUPPLICANT_DBG("Invalid parameter");
7907                 return -EINVAL;
7908         }
7909
7910         if (!connection)
7911                 return -EINVAL;
7912
7913         msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
7914                         NETCONFIG_WIFI_INTERFACE, "DecryptConfObj");
7915         if (!msg)
7916                 return -EINVAL;
7917
7918         dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->connector,
7919                                                         DBUS_TYPE_INVALID);
7920         dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->c_sign_key,
7921                                                         DBUS_TYPE_INVALID);
7922         dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->net_access_key,
7923                                                         DBUS_TYPE_INVALID);
7924
7925         if (!dbus_connection_send_with_reply(connection, msg,
7926                                 &call, DBUS_TIMEOUT_USE_DEFAULT)) {
7927                 dbus_message_unref(msg);
7928                 return -EIO;
7929         }
7930
7931         if (!call) {
7932                 dbus_message_unref(msg);
7933                 return -EIO;
7934         }
7935
7936         decrypt_request_data.pending_call = call;
7937         decrypt_request_data.data = data;
7938
7939         dbus_pending_call_set_notify(call, decrypt_conf_obj_reply, data, NULL);
7940         dbus_message_unref(msg);
7941
7942         SUPPLICANT_DBG("Decrypt Conf Obj request succeeded");
7943
7944         return 0;
7945 }
7946
7947 static bool is_valid_config_object(GSupplicantSSID *ssid)
7948 {
7949         return ((ssid->connector &&
7950                         g_strcmp0(ssid->connector, "") != 0) &&
7951                         (ssid->c_sign_key &&
7952                         g_strcmp0(ssid->c_sign_key, "") != 0) &&
7953                         (ssid->net_access_key &&
7954                         g_strcmp0(ssid->net_access_key, "") != 0));
7955 }
7956 #endif
7957
7958 int g_supplicant_interface_connect(GSupplicantInterface *interface,
7959                                 GSupplicantSSID *ssid,
7960                                 GSupplicantInterfaceCallback callback,
7961                                                         void *user_data)
7962 {
7963         struct interface_connect_data *data;
7964         struct interface_data *intf_data;
7965         int ret = 0;
7966
7967         SUPPLICANT_DBG("");
7968
7969         if (!interface)
7970                 return -EINVAL;
7971
7972         if (!system_available)
7973                 return -EFAULT;
7974
7975         /* TODO: Check if we're already connected and switch */
7976
7977         data = dbus_malloc0(sizeof(*data));
7978         if (!data)
7979                 return -ENOMEM;
7980
7981         data->interface = interface;
7982         data->path = g_strdup(interface->path);
7983         data->callback = callback;
7984         data->ssid = ssid;
7985         data->user_data = user_data;
7986
7987         if (ssid->use_wps) {
7988                 g_free(interface->wps_cred.key);
7989                 memset(&interface->wps_cred, 0,
7990                                 sizeof(struct _GSupplicantWpsCredentials));
7991
7992                 ret = supplicant_dbus_property_set(interface->path,
7993                         SUPPLICANT_INTERFACE ".Interface.WPS",
7994                         "ProcessCredentials", DBUS_TYPE_BOOLEAN_AS_STRING,
7995                         wps_process_credentials, wps_start, data, interface);
7996         } else {
7997                 /* By the time there is a request for connect and the network
7998                  * path is not NULL it means that connman has not removed the
7999                  * previous network pointer. This can happen in the case AP
8000                  * deauthenticated client and connman does not remove the
8001                  * previously connected network pointer. This causes supplicant
8002                  * to reallocate the memory for struct wpa_ssid again even if it
8003                  * is the same SSID. This causes memory usage of wpa_supplicnat
8004                  * to go high. The idea here is that if the previously connected
8005                  * network is not removed at the time of next connection attempt
8006                  * check if the network path is not NULL. In case it is non-NULL
8007                  * first remove the network and then once removal is successful, add
8008                  * the network.
8009                  */
8010
8011                 if (interface->network_path != NULL) {
8012                         g_free(data->path);
8013                         dbus_free(data);
8014
8015                         /*
8016                          * If this add network is for the same network for
8017                          * which wpa_supplicant already has a profile then do
8018                          * not need to add another profile. Only if the
8019                          * profile that needs to get added is different from
8020                          * what is there in wpa_s delete the current one. A
8021                          * network is identified by its SSID, security_type
8022                          * and passphrase (private passphrase in case security
8023                          * type is 802.11x).
8024                          */
8025                         if (compare_network_parameters(interface, ssid)) {
8026                                 return -EALREADY;
8027                         }
8028
8029                         intf_data = dbus_malloc0(sizeof(*intf_data));
8030                         if (!intf_data)
8031                                 return -ENOMEM;
8032
8033                         intf_data->interface = interface;
8034                         intf_data->path = g_strdup(interface->path);
8035                         intf_data->callback = callback;
8036                         intf_data->ssid = ssid;
8037                         intf_data->user_data = user_data;
8038                         intf_data->network_remove_in_progress = TRUE;
8039                         network_remove(intf_data);
8040                 } else {
8041 #if defined TIZEN_EXT
8042                         if (ssid->passphrase &&
8043                             g_strcmp0(ssid->passphrase, "") != 0 &&
8044 #if defined TIZEN_EXT_WIFI_MESH
8045                             ssid->mode != G_SUPPLICANT_MODE_MESH &&
8046 #endif
8047                             !ssid->eap) {
8048                                 ret = send_decryption_request(ssid->passphrase, data);
8049                                 if (ret < 0)
8050                                         SUPPLICANT_DBG("Decryption request failed %d", ret);
8051                         } else if (is_valid_config_object(ssid)) {
8052                                 ret = send_decryption_conf_obj_request(ssid, data);
8053                                 if (ret < 0)
8054                                         SUPPLICANT_DBG("Decryption Conf Obj request failed %d", ret);
8055
8056                         } else
8057 #endif
8058                         ret = supplicant_dbus_method_call(interface->path,
8059                                         SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
8060                                         interface_add_network_params,
8061                                         interface_add_network_result, data,
8062                                         interface);
8063                 }
8064         }
8065
8066         if (ret < 0) {
8067                 g_free(data->path);
8068                 dbus_free(data);
8069                 return ret;
8070         }
8071
8072         return -EINPROGRESS;
8073 }
8074
8075 static void network_remove_result(const char *error,
8076                                 DBusMessageIter *iter, void *user_data)
8077 {
8078         struct interface_data *data = user_data;
8079         struct interface_connect_data *connect_data;
8080         int result = 0;
8081
8082         SUPPLICANT_DBG("");
8083
8084         if (error) {
8085                 result = -EIO;
8086                 SUPPLICANT_DBG("error: %s", error);
8087
8088                 if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
8089                                                 error) == 0)
8090                         result = -ECONNABORTED;
8091         }
8092
8093         g_free(data->interface->network_path);
8094         data->interface->network_path = NULL;
8095
8096         remove_network_information(data->interface);
8097
8098         if (data->network_remove_in_progress == TRUE) {
8099                 data->network_remove_in_progress = FALSE;
8100                 connect_data = dbus_malloc0(sizeof(*connect_data));
8101                 if (!connect_data)
8102                         return;
8103
8104                 connect_data->interface = data->interface;
8105                 connect_data->path = g_strdup(data->path);
8106                 connect_data->callback = data->callback;
8107                 connect_data->ssid = data->ssid;
8108                 connect_data->user_data = data->user_data;
8109
8110 #if defined TIZEN_EXT
8111                 int ret;
8112                 if (data->ssid->passphrase && g_strcmp0(data->ssid->passphrase, "") != 0
8113                         && !data->ssid->eap) {
8114                         ret = send_decryption_request(data->ssid->passphrase, connect_data);
8115                         if (ret < 0) {
8116                                 SUPPLICANT_DBG("Decryption request failed %d", ret);
8117                                 g_free(connect_data->ssid);
8118                                 g_free(connect_data->path);
8119                                 dbus_free(connect_data);
8120                         }
8121                 } else if (is_valid_config_object(data->ssid)) {
8122                         ret = send_decryption_conf_obj_request(data->ssid, connect_data);
8123                         if (ret < 0) {
8124                                 SUPPLICANT_DBG("Decryption Conf Obj request failed %d", ret);
8125                                 g_free(connect_data->ssid);
8126                                 g_free(connect_data->path);
8127                                 dbus_free(connect_data);
8128                         }
8129                 } else
8130 #endif
8131                 supplicant_dbus_method_call(data->interface->path,
8132                         SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
8133                         interface_add_network_params,
8134                         interface_add_network_result, connect_data,
8135                         connect_data->interface);
8136         } else {
8137                 if (data->callback)
8138                         data->callback(result, data->interface, data->user_data);
8139         }
8140         g_free(data->path);
8141         dbus_free(data);
8142 }
8143
8144 static void network_remove_params(DBusMessageIter *iter, void *user_data)
8145 {
8146         struct interface_data *data = user_data;
8147         const char *path = data->interface->network_path;
8148
8149         SUPPLICANT_DBG("path %s", path);
8150
8151         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
8152 }
8153
8154 static int network_remove(struct interface_data *data)
8155 {
8156         GSupplicantInterface *interface = data->interface;
8157
8158         SUPPLICANT_DBG("");
8159
8160 #if defined TIZEN_EXT
8161         GSupplicantInterface *intf = NULL;
8162         /*
8163          * Check if 'interface' is valid
8164          */
8165         intf = g_hash_table_lookup(interface_table, interface->path);
8166         if (intf == NULL)
8167                 return -EINVAL;
8168 #endif
8169
8170         return supplicant_dbus_method_call(interface->path,
8171                         SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork",
8172                         network_remove_params, network_remove_result, data,
8173                         interface);
8174 }
8175
8176 static void interface_disconnect_result(const char *error,
8177                                 DBusMessageIter *iter, void *user_data)
8178 {
8179         struct interface_data *data = user_data;
8180         int result = 0;
8181
8182         SUPPLICANT_DBG("");
8183
8184         if (error) {
8185                 result = -EIO;
8186                 SUPPLICANT_DBG("error: %s", error);
8187
8188                 if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
8189                                                 error) == 0)
8190                         result = -ECONNABORTED;
8191         }
8192
8193         /* If we are disconnecting from previous WPS successful
8194          * association. i.e.: it did not went through AddNetwork,
8195          * and interface->network_path was never set. */
8196         if (!data->interface->network_path) {
8197                 if (data->callback)
8198                         data->callback(result, data->interface,
8199                                                         data->user_data);
8200
8201                 g_free(data->path);
8202                 dbus_free(data);
8203                 return;
8204         }
8205
8206         if (result < 0 && data->callback) {
8207                 data->callback(result, data->interface, data->user_data);
8208                 data->callback = NULL;
8209         }
8210
8211         if (result != -ECONNABORTED) {
8212                 if (network_remove(data) < 0) {
8213                         g_free(data->path);
8214                         dbus_free(data);
8215                 }
8216         } else {
8217                 g_free(data->path);
8218                 dbus_free(data);
8219         }
8220 }
8221
8222 int g_supplicant_interface_disconnect(GSupplicantInterface *interface,
8223                                         GSupplicantInterfaceCallback callback,
8224                                                         void *user_data)
8225 {
8226         struct interface_data *data;
8227         int ret;
8228
8229         SUPPLICANT_DBG("");
8230
8231         if (!interface)
8232                 return -EINVAL;
8233
8234         if (!system_available)
8235                 return -EFAULT;
8236 #if defined TIZEN_EXT
8237         if (decrypt_request_data.pending_call &&
8238                         decrypt_request_data.data &&
8239                         decrypt_request_data.data->user_data == user_data) {
8240
8241                 callback_assoc_failed(decrypt_request_data.data->user_data);
8242                 crypt_method_call_cancel();
8243
8244                 return 0;
8245         }
8246 #endif
8247         data = dbus_malloc0(sizeof(*data));
8248         if (!data)
8249                 return -ENOMEM;
8250
8251         data->interface = interface;
8252         data->path = g_strdup(interface->path);
8253         data->callback = callback;
8254         data->user_data = user_data;
8255
8256         ret = supplicant_dbus_method_call(interface->path,
8257                         SUPPLICANT_INTERFACE ".Interface", "Disconnect",
8258                         NULL, interface_disconnect_result, data,
8259                         interface);
8260
8261         if (ret < 0) {
8262                 g_free(data->path);
8263                 dbus_free(data);
8264         }
8265
8266         return ret;
8267 }
8268
8269 #if defined TIZEN_EXT
8270 void g_supplicant_interface_remove_network(GSupplicantInterface *interface,
8271                                 GSupplicantSSID *ssid)
8272 {
8273         struct interface_data *data;
8274         int ret;
8275
8276         SUPPLICANT_DBG("");
8277
8278         if (!interface)
8279                 return;
8280
8281         if (interface->network_path == NULL)
8282                 return;
8283
8284         if (!interface->network_info.ssid)
8285                 return;
8286
8287         if (memcmp(interface->network_info.ssid, ssid->ssid, ssid->ssid_len))
8288                 return;
8289
8290         if (interface->network_info.security != ssid->security)
8291                 return;
8292
8293         data = dbus_malloc0(sizeof(*data));
8294         if (!data)
8295                 return;
8296
8297         data->interface = interface;
8298         data->path = g_strdup(interface->path);
8299
8300         ret = supplicant_dbus_method_call(interface->path,
8301                         SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork",
8302                         network_remove_params, network_remove_result, data,
8303                         interface);
8304
8305         if (ret < 0) {
8306                 g_free(data->path);
8307                 dbus_free(data);
8308         }
8309 }
8310 #endif
8311
8312 static void interface_p2p_find_result(const char *error,
8313                                         DBusMessageIter *iter, void *user_data)
8314 {
8315         struct interface_scan_data *data = user_data;
8316         int err = 0;
8317
8318         SUPPLICANT_DBG("error %s", error);
8319
8320         if (error)
8321                 err = -EIO;
8322
8323         if (interface_exists(data->interface, data->path)) {
8324                 if (!data->interface->ready)
8325                         err = -ENOLINK;
8326                 if (!err)
8327                         data->interface->p2p_finding = true;
8328         }
8329
8330         if (data->callback)
8331                 data->callback(err, data->interface, data->user_data);
8332
8333         g_free(data->path);
8334         dbus_free(data);
8335 }
8336
8337 static void interface_p2p_find_params(DBusMessageIter *iter, void *user_data)
8338 {
8339         DBusMessageIter dict;
8340
8341         supplicant_dbus_dict_open(iter, &dict);
8342         supplicant_dbus_dict_close(iter, &dict);
8343 }
8344
8345 int g_supplicant_interface_p2p_find(GSupplicantInterface *interface,
8346                                         GSupplicantInterfaceCallback callback,
8347                                                         void *user_data)
8348 {
8349         struct interface_scan_data *data;
8350         int ret;
8351
8352         if (!interface->p2p_support)
8353                 return -ENOTSUP;
8354
8355         ret = interface_ready_to_scan(interface);
8356         if (ret && ret != -EALREADY)
8357                 return ret;
8358
8359         data = dbus_malloc0(sizeof(*data));
8360         if (!data)
8361                 return -ENOMEM;
8362
8363         data->interface = interface;
8364         data->path = g_strdup(interface->path);
8365         data->callback = callback;
8366         data->user_data = user_data;
8367
8368         ret = supplicant_dbus_method_call(interface->path,
8369                         SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Find",
8370                         interface_p2p_find_params, interface_p2p_find_result,
8371                         data, interface);
8372         if (ret < 0) {
8373                 g_free(data->path);
8374                 dbus_free(data);
8375         }
8376
8377         return ret;
8378 }
8379
8380 bool g_supplicant_interface_is_p2p_finding(GSupplicantInterface *interface)
8381 {
8382         if (!interface)
8383                 return false;
8384
8385         return interface->p2p_finding;
8386 }
8387
8388 int g_supplicant_interface_p2p_stop_find(GSupplicantInterface *interface)
8389 {
8390         if (!interface->p2p_finding)
8391                 return 0;
8392
8393         SUPPLICANT_DBG("");
8394
8395         interface->p2p_finding = false;
8396
8397         return supplicant_dbus_method_call(interface->path,
8398                 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "StopFind",
8399                 NULL, NULL, NULL, NULL);
8400 }
8401
8402 static void interface_p2p_connect_result(const char *error,
8403                                         DBusMessageIter *iter, void *user_data)
8404 {
8405         struct interface_connect_data *data = user_data;
8406         int err = 0;
8407
8408         SUPPLICANT_DBG("");
8409
8410         if (error) {
8411                 SUPPLICANT_DBG("error: %s", error);
8412                 err = parse_supplicant_error(iter);
8413         }
8414
8415         if (data->callback)
8416                 data->callback(err, data->interface, data->user_data);
8417
8418         g_free(data->path);
8419         g_free(data->peer->wps_pin);
8420         g_free(data->peer->path);
8421         g_free(data->peer);
8422         g_free(data);
8423 }
8424
8425 static void interface_p2p_connect_params(DBusMessageIter *iter, void *user_data)
8426 {
8427         struct interface_connect_data *data = user_data;
8428         const char *wps = "pbc";
8429         DBusMessageIter dict;
8430         int go_intent = 7;
8431
8432         SUPPLICANT_DBG("");
8433
8434         supplicant_dbus_dict_open(iter, &dict);
8435
8436         if (data->peer->master)
8437                 go_intent = 15;
8438
8439         if (data->peer->wps_pin)
8440                 wps = "pin";
8441
8442         supplicant_dbus_dict_append_basic(&dict, "peer",
8443                                 DBUS_TYPE_OBJECT_PATH, &data->peer->path);
8444         supplicant_dbus_dict_append_basic(&dict, "wps_method",
8445                                 DBUS_TYPE_STRING, &wps);
8446         if (data->peer->wps_pin) {
8447                 supplicant_dbus_dict_append_basic(&dict, "pin",
8448                                 DBUS_TYPE_STRING, &data->peer->wps_pin);
8449         }
8450
8451         supplicant_dbus_dict_append_basic(&dict, "go_intent",
8452                                         DBUS_TYPE_INT32, &go_intent);
8453
8454         supplicant_dbus_dict_close(iter, &dict);
8455 }
8456
8457 int g_supplicant_interface_p2p_connect(GSupplicantInterface *interface,
8458                                         GSupplicantPeerParams *peer_params,
8459                                         GSupplicantInterfaceCallback callback,
8460                                         void *user_data)
8461 {
8462         struct interface_connect_data *data;
8463         int ret;
8464
8465         SUPPLICANT_DBG("");
8466
8467         if (!interface->p2p_support)
8468                 return -ENOTSUP;
8469
8470         data = dbus_malloc0(sizeof(*data));
8471         if (!data)
8472                 return -ENOMEM;
8473
8474         data->interface = interface;
8475         data->path = g_strdup(interface->path);
8476         data->peer = peer_params;
8477         data->callback = callback;
8478         data->user_data = user_data;
8479
8480         ret = supplicant_dbus_method_call(interface->path,
8481                 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Connect",
8482                 interface_p2p_connect_params, interface_p2p_connect_result,
8483                 data, interface);
8484         if (ret < 0) {
8485                 g_free(data->path);
8486                 dbus_free(data);
8487                 return ret;
8488         }
8489
8490         return -EINPROGRESS;
8491 }
8492
8493 int g_supplicant_interface_p2p_disconnect(GSupplicantInterface *interface,
8494                                         GSupplicantPeerParams *peer_params)
8495 {
8496         GSupplicantPeer *peer;
8497         int count = 0;
8498         GSList *list;
8499
8500         SUPPLICANT_DBG("");
8501
8502         if (!interface->p2p_support)
8503                 return -ENOTSUP;
8504
8505         peer = g_hash_table_lookup(interface->peer_table, peer_params->path);
8506         if (!peer)
8507                 return -ENODEV;
8508
8509         for (list = peer->groups; list; list = list->next, count++) {
8510                 const char *group_obj_path = list->data;
8511                 GSupplicantInterface *g_interface;
8512                 GSupplicantGroup *group;
8513
8514                 group = g_hash_table_lookup(group_mapping, group_obj_path);
8515                 if (!group || !group->interface)
8516                         continue;
8517
8518                 g_interface = group->interface;
8519                 supplicant_dbus_method_call(g_interface->path,
8520                                 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
8521                                 "Disconnect", NULL, NULL, NULL, g_interface);
8522         }
8523
8524         if (count == 0 && peer->current_group_iface) {
8525                 supplicant_dbus_method_call(peer->current_group_iface->path,
8526                                 SUPPLICANT_INTERFACE ".Interface.P2PDevice",
8527                                 "Disconnect", NULL, NULL, NULL,
8528                                 peer->current_group_iface->path);
8529         }
8530
8531         peer->current_group_iface = NULL;
8532
8533         return -EINPROGRESS;
8534 }
8535
8536 struct p2p_service_data {
8537         bool registration;
8538         GSupplicantInterface *interface;
8539         GSupplicantP2PServiceParams *service;
8540         GSupplicantInterfaceCallback callback;
8541         void *user_data;
8542 };
8543
8544 static void interface_p2p_service_result(const char *error,
8545                                         DBusMessageIter *iter, void *user_data)
8546 {
8547         struct p2p_service_data *data = user_data;
8548         int result = 0;
8549
8550         SUPPLICANT_DBG("%s result - %s", data->registration ?
8551                                 "Registration" : "Deletion",
8552                                 error ? error : "Success");
8553         if (error)
8554                 result = -EINVAL;
8555
8556         if (data->callback)
8557                 data->callback(result, data->interface, data->user_data);
8558
8559         g_free(data->service->query);
8560         g_free(data->service->response);
8561         g_free(data->service->service);
8562         g_free(data->service->wfd_ies);
8563         g_free(data->service);
8564         dbus_free(data);
8565 }
8566
8567 static void interface_p2p_service_params(DBusMessageIter *iter,
8568                                                         void *user_data)
8569 {
8570         struct p2p_service_data *data = user_data;
8571         GSupplicantP2PServiceParams *service;
8572         DBusMessageIter dict;
8573         const char *type;
8574
8575         SUPPLICANT_DBG("");
8576
8577         service = data->service;
8578
8579         supplicant_dbus_dict_open(iter, &dict);
8580
8581         if (service->query && service->response) {
8582                 type = "bonjour";
8583                 supplicant_dbus_dict_append_basic(&dict, "service_type",
8584                                                 DBUS_TYPE_STRING, &type);
8585                 supplicant_dbus_dict_append_fixed_array(&dict, "query",
8586                                         DBUS_TYPE_BYTE, &service->query,
8587                                         service->query_length);
8588                 supplicant_dbus_dict_append_fixed_array(&dict, "response",
8589                                         DBUS_TYPE_BYTE, &service->response,
8590                                         service->response_length);
8591         } else if (service->version && service->service) {
8592                 type = "upnp";
8593                 supplicant_dbus_dict_append_basic(&dict, "service_type",
8594                                                 DBUS_TYPE_STRING, &type);
8595                 supplicant_dbus_dict_append_basic(&dict, "version",
8596                                         DBUS_TYPE_INT32, &service->version);
8597                 supplicant_dbus_dict_append_basic(&dict, "service",
8598                                         DBUS_TYPE_STRING, &service->service);
8599         }
8600
8601         supplicant_dbus_dict_close(iter, &dict);
8602 }
8603
8604 int g_supplicant_interface_p2p_add_service(GSupplicantInterface *interface,
8605                                 GSupplicantInterfaceCallback callback,
8606                                 GSupplicantP2PServiceParams *p2p_service_params,
8607                                 void *user_data)
8608 {
8609         struct p2p_service_data *data;
8610         int ret;
8611
8612         SUPPLICANT_DBG("");
8613
8614         if (!interface->p2p_support)
8615                 return -ENOTSUP;
8616
8617         data = dbus_malloc0(sizeof(*data));
8618         if (!data)
8619                 return -ENOMEM;
8620
8621         data->registration = true;
8622         data->interface = interface;
8623         data->service = p2p_service_params;
8624         data->callback = callback;
8625         data->user_data = user_data;
8626
8627         ret = supplicant_dbus_method_call(interface->path,
8628                 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "AddService",
8629                 interface_p2p_service_params, interface_p2p_service_result,
8630                 data, interface);
8631         if (ret < 0) {
8632                 dbus_free(data);
8633                 return ret;
8634         }
8635
8636         return -EINPROGRESS;
8637 }
8638
8639 int g_supplicant_interface_p2p_del_service(GSupplicantInterface *interface,
8640                                 GSupplicantP2PServiceParams *p2p_service_params)
8641 {
8642         struct p2p_service_data *data;
8643         int ret;
8644
8645         SUPPLICANT_DBG("");
8646
8647         if (!interface->p2p_support)
8648                 return -ENOTSUP;
8649
8650         data = dbus_malloc0(sizeof(*data));
8651         if (!data)
8652                 return -ENOMEM;
8653
8654         data->interface = interface;
8655         data->service = p2p_service_params;
8656
8657         ret = supplicant_dbus_method_call(interface->path,
8658                 SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeleteService",
8659                 interface_p2p_service_params, interface_p2p_service_result,
8660                 data, interface);
8661         if (ret < 0) {
8662                 dbus_free(data);
8663                 return ret;
8664         }
8665
8666         return -EINPROGRESS;
8667 }
8668
8669 struct p2p_listen_data {
8670         int period;
8671         int interval;
8672 };
8673
8674 static void interface_p2p_listen_params(DBusMessageIter *iter, void *user_data)
8675 {
8676         struct p2p_listen_data *params = user_data;
8677         DBusMessageIter dict;
8678
8679         supplicant_dbus_dict_open(iter, &dict);
8680
8681         supplicant_dbus_dict_append_basic(&dict, "period",
8682                                         DBUS_TYPE_INT32, &params->period);
8683         supplicant_dbus_dict_append_basic(&dict, "interval",
8684                                         DBUS_TYPE_INT32, &params->interval);
8685         supplicant_dbus_dict_close(iter, &dict);
8686 }
8687
8688 int g_supplicant_interface_p2p_listen(GSupplicantInterface *interface,
8689                                                 int period, int interval)
8690 {
8691         struct p2p_listen_data params;
8692
8693         SUPPLICANT_DBG("");
8694
8695         if (!interface->p2p_support)
8696                 return -ENOTSUP;
8697
8698         params.period = period;
8699         params.interval = interval;
8700
8701         return supplicant_dbus_method_call(interface->path,
8702                         SUPPLICANT_INTERFACE ".Interface.P2PDevice",
8703                         "ExtendedListen", interface_p2p_listen_params,
8704                         NULL, &params, NULL);
8705 }
8706
8707 static void widi_ies_params(DBusMessageIter *iter, void *user_data)
8708 {
8709         struct p2p_service_data *data = user_data;
8710         GSupplicantP2PServiceParams *service = data->service;
8711         DBusMessageIter array;
8712
8713         SUPPLICANT_DBG("%p - %d", service->wfd_ies, service->wfd_ies_length);
8714
8715         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
8716                                         DBUS_TYPE_BYTE_AS_STRING, &array);
8717
8718         if (service->wfd_ies && service->wfd_ies_length > 0) {
8719                 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
8720                                 &service->wfd_ies, service->wfd_ies_length);
8721         }
8722
8723         dbus_message_iter_close_container(iter, &array);
8724 }
8725
8726 int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params,
8727                                         GSupplicantInterfaceCallback callback,
8728                                         void *user_data)
8729 {
8730         struct p2p_service_data *data;
8731         int ret;
8732
8733         SUPPLICANT_DBG("");
8734
8735         if (!system_available)
8736                 return -EFAULT;
8737
8738         data = dbus_malloc0(sizeof(*data));
8739         if (!data)
8740                 return -ENOMEM;
8741
8742         data->service = p2p_service_params;
8743         data->callback = callback;
8744         data->user_data = user_data;
8745
8746         if (p2p_service_params->wfd_ies)
8747                 data->registration = true;
8748
8749         ret = supplicant_dbus_property_set(SUPPLICANT_PATH,
8750                                         SUPPLICANT_INTERFACE, "WFDIEs",
8751                                         DBUS_TYPE_ARRAY_AS_STRING
8752                                         DBUS_TYPE_BYTE_AS_STRING,
8753                                         widi_ies_params,
8754                                         interface_p2p_service_result,
8755                                         data, NULL);
8756         if (ret < 0 && ret != -EINPROGRESS) {
8757                 dbus_free(data);
8758                 return ret;
8759         }
8760
8761         return -EINPROGRESS;
8762 }
8763
8764
8765 static const char *g_supplicant_rule0 = "type=signal,"
8766                                         "path=" DBUS_PATH_DBUS ","
8767                                         "sender=" DBUS_SERVICE_DBUS ","
8768                                         "interface=" DBUS_INTERFACE_DBUS ","
8769                                         "member=NameOwnerChanged,"
8770                                         "arg0=" SUPPLICANT_SERVICE;
8771 static const char *g_supplicant_rule1 = "type=signal,"
8772                         "interface=" SUPPLICANT_INTERFACE;
8773 static const char *g_supplicant_rule2 = "type=signal,"
8774                         "interface=" SUPPLICANT_INTERFACE ".Interface";
8775 static const char *g_supplicant_rule3 = "type=signal,"
8776                         "interface=" SUPPLICANT_INTERFACE ".Interface.WPS";
8777 static const char *g_supplicant_rule4 = "type=signal,"
8778                         "interface=" SUPPLICANT_INTERFACE ".BSS";
8779 static const char *g_supplicant_rule5 = "type=signal,"
8780                         "interface=" SUPPLICANT_INTERFACE ".Network";
8781 #if !defined TIZEN_EXT
8782 static const char *g_supplicant_rule6 = "type=signal,"
8783                 "interface=" SUPPLICANT_INTERFACE ".Interface.P2PDevice";
8784 static const char *g_supplicant_rule7 = "type=signal,"
8785                 "interface=" SUPPLICANT_INTERFACE ".Peer";
8786 static const char *g_supplicant_rule8 = "type=signal,"
8787                 "interface=" SUPPLICANT_INTERFACE ".Group";
8788 #endif
8789 #if defined TIZEN_EXT_WIFI_MESH
8790 static const char *g_supplicant_rule9 = "type=signal,"
8791                 "interface=" SUPPLICANT_INTERFACE ".Interface.Mesh";
8792 #endif
8793
8794 static void invoke_introspect_method(void)
8795 {
8796         DBusMessage *message;
8797
8798         message = dbus_message_new_method_call(SUPPLICANT_SERVICE,
8799                                         SUPPLICANT_PATH,
8800                                         DBUS_INTERFACE_INTROSPECTABLE,
8801                                         "Introspect");
8802
8803         if (!message)
8804                 return;
8805
8806         dbus_message_set_no_reply(message, TRUE);
8807         dbus_connection_send(connection, message, NULL);
8808         dbus_message_unref(message);
8809 }
8810
8811 #if defined TIZEN_EXT && defined TIZEN_EXT_INS
8812 void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
8813                 bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
8814                 unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
8815                 unsigned int assoc_reject_score, int signal_level3_5ghz, int signal_level3_24ghz)
8816 {
8817         ins_settings.preferred_freq_bssid = preferred_freq_bssid;
8818         ins_settings.last_connected_bssid = last_connected_bssid;
8819         ins_settings.assoc_reject = assoc_reject;
8820         ins_settings.signal_bssid = signal_bssid;
8821         ins_settings.preferred_freq_bssid_score = preferred_freq_bssid_score;
8822         ins_settings.last_connected_bssid_score = last_connected_bssid_score;
8823         ins_settings.assoc_reject_score = assoc_reject_score;
8824         ins_settings.signal_level3_5ghz = signal_level3_5ghz;
8825         ins_settings.signal_level3_24ghz = signal_level3_24ghz;
8826
8827         SUPPLICANT_DBG("preferred_freq_bssid [%s]", preferred_freq_bssid ? "true" : "false");
8828         SUPPLICANT_DBG("preferred_freq_bssid_score [%d]", preferred_freq_bssid_score);
8829         SUPPLICANT_DBG("last_connected_bssid [%s]", last_connected_bssid ? "true" : "false");
8830         SUPPLICANT_DBG("last_connected_bssid_score [%d]", last_connected_bssid_score);
8831         SUPPLICANT_DBG("assoc_reject [%s]", assoc_reject ? "true" : "false");
8832         SUPPLICANT_DBG("assoc_reject_score [%d]", assoc_reject_score);
8833         SUPPLICANT_DBG("signal_bssid [%s]", signal_bssid ? "true" : "false");
8834         SUPPLICANT_DBG("signal_level3_5ghz [%d]", signal_level3_5ghz);
8835         SUPPLICANT_DBG("signal_level3_24ghz [%d]", signal_level3_24ghz);
8836 }
8837 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
8838
8839 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
8840 void g_supplicant_register_eap_callback(g_supplicant_eap_callback cb)
8841 {
8842         SUPPLICANT_DBG("g_supplicant_register_eap_callback %p", cb);
8843
8844         if (!callbacks_pointer) {
8845                 SUPPLICANT_DBG("callbacks_pointer is NULL");
8846                 return;
8847         }
8848
8849         callbacks_pointer->eap = cb;
8850 }
8851
8852 void g_supplicant_unregister_eap_callback(void)
8853 {
8854         SUPPLICANT_DBG("g_supplicant_unregister_eap_callback");
8855
8856         if (!callbacks_pointer) {
8857                 SUPPLICANT_DBG("callbacks_pointer is NULL");
8858                 return;
8859         }
8860
8861         callbacks_pointer->eap = NULL;
8862 }
8863 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
8864
8865 #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
8866 int g_supplicant_register(GSupplicantCallbacks *callbacks)
8867 #else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
8868 int g_supplicant_register(const GSupplicantCallbacks *callbacks)
8869 #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
8870 {
8871         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
8872         if (!connection)
8873                 return -EIO;
8874
8875         if (!dbus_connection_add_filter(connection, g_supplicant_filter,
8876                                                 NULL, NULL)) {
8877                 dbus_connection_unref(connection);
8878                 connection = NULL;
8879                 return -EIO;
8880         }
8881 #if defined TIZEN_EXT
8882         simplified_log = connman_setting_get_bool("SimplifiedLog");
8883 #endif
8884         callbacks_pointer = callbacks;
8885         eap_methods = 0;
8886
8887         interface_table = g_hash_table_new_full(g_str_hash, g_str_equal,
8888                                                 NULL, remove_interface);
8889
8890         bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
8891                                                                 NULL, NULL);
8892         peer_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
8893                                                                 NULL, NULL);
8894         group_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
8895                                                                 NULL, NULL);
8896         pending_peer_connection = g_hash_table_new_full(g_str_hash, g_str_equal,
8897                                                                 NULL, NULL);
8898         config_file_table = g_hash_table_new_full(g_str_hash, g_str_equal,
8899                                                                 g_free, g_free);
8900
8901         supplicant_dbus_setup(connection);
8902
8903         dbus_bus_add_match(connection, g_supplicant_rule0, NULL);
8904         dbus_bus_add_match(connection, g_supplicant_rule1, NULL);
8905         dbus_bus_add_match(connection, g_supplicant_rule2, NULL);
8906         dbus_bus_add_match(connection, g_supplicant_rule3, NULL);
8907         dbus_bus_add_match(connection, g_supplicant_rule4, NULL);
8908         dbus_bus_add_match(connection, g_supplicant_rule5, NULL);
8909 #if defined TIZEN_EXT
8910         dbus_bus_add_match(connection,
8911                         "type=signal,interface=org.tizen.system.deviced.PowerOff,"
8912                         "member=ChangeState", NULL);
8913 #endif
8914 #if !defined TIZEN_EXT
8915         dbus_bus_add_match(connection, g_supplicant_rule6, NULL);
8916         dbus_bus_add_match(connection, g_supplicant_rule7, NULL);
8917         dbus_bus_add_match(connection, g_supplicant_rule8, NULL);
8918 #endif
8919 #if defined TIZEN_EXT_WIFI_MESH
8920         dbus_bus_add_match(connection, g_supplicant_rule9, NULL);
8921 #endif
8922         dbus_connection_flush(connection);
8923
8924         if (dbus_bus_name_has_owner(connection,
8925                                         SUPPLICANT_SERVICE, NULL)) {
8926                 system_available = TRUE;
8927                 supplicant_dbus_property_get_all(SUPPLICANT_PATH,
8928                                                 SUPPLICANT_INTERFACE,
8929                                                 service_property, NULL, NULL);
8930         } else
8931                 invoke_introspect_method();
8932
8933         SUPPLICANT_DBG("supplicant dbus setup completed");
8934         return 0;
8935 }
8936
8937 static void unregister_interface_remove_params(DBusMessageIter *iter,
8938                                                 void *user_data)
8939 {
8940         const char *path = user_data;
8941
8942         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
8943                                                         &path);
8944 }
8945
8946
8947 static void unregister_remove_interface(gpointer key, gpointer value,
8948                                                 gpointer user_data)
8949 {
8950         GSupplicantInterface *interface = value;
8951
8952         supplicant_dbus_method_call(SUPPLICANT_PATH,
8953                                         SUPPLICANT_INTERFACE,
8954                                         "RemoveInterface",
8955                                         unregister_interface_remove_params,
8956                                         NULL, interface->path, NULL);
8957 }
8958
8959 void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
8960 {
8961         SUPPLICANT_DBG("");
8962
8963         if (connection) {
8964 #if defined TIZEN_EXT_WIFI_MESH
8965                 dbus_bus_remove_match(connection, g_supplicant_rule9, NULL);
8966 #endif
8967 #if !defined TIZEN_EXT
8968                 dbus_bus_remove_match(connection, g_supplicant_rule8, NULL);
8969                 dbus_bus_remove_match(connection, g_supplicant_rule7, NULL);
8970                 dbus_bus_remove_match(connection, g_supplicant_rule6, NULL);
8971 #endif
8972                 dbus_bus_remove_match(connection, g_supplicant_rule5, NULL);
8973                 dbus_bus_remove_match(connection, g_supplicant_rule4, NULL);
8974                 dbus_bus_remove_match(connection, g_supplicant_rule3, NULL);
8975                 dbus_bus_remove_match(connection, g_supplicant_rule2, NULL);
8976                 dbus_bus_remove_match(connection, g_supplicant_rule1, NULL);
8977                 dbus_bus_remove_match(connection, g_supplicant_rule0, NULL);
8978                 dbus_connection_flush(connection);
8979
8980                 dbus_connection_remove_filter(connection,
8981                                                 g_supplicant_filter, NULL);
8982         }
8983
8984         if (config_file_table) {
8985                 g_hash_table_destroy(config_file_table);
8986                 config_file_table = NULL;
8987         }
8988
8989         if (bss_mapping) {
8990                 g_hash_table_destroy(bss_mapping);
8991                 bss_mapping = NULL;
8992         }
8993
8994         if (peer_mapping) {
8995                 g_hash_table_destroy(peer_mapping);
8996                 peer_mapping = NULL;
8997         }
8998
8999         if (group_mapping) {
9000                 g_hash_table_destroy(group_mapping);
9001                 group_mapping = NULL;
9002         }
9003
9004         if (interface_table) {
9005                 g_hash_table_foreach(interface_table,
9006                                         unregister_remove_interface, NULL);
9007                 g_hash_table_destroy(interface_table);
9008                 interface_table = NULL;
9009         }
9010
9011         if (system_available)
9012                 callback_system_killed();
9013
9014         if (connection) {
9015                 dbus_connection_unref(connection);
9016                 connection = NULL;
9017         }
9018
9019         callbacks_pointer = NULL;
9020         eap_methods = 0;
9021 }
9022
9023 #ifdef TIZEN_EXT
9024 struct supplicant_mac_policy {
9025         GSupplicantMacPolicyCallback callback;
9026         dbus_uint32_t policy;
9027         const void *user_data;
9028 };
9029
9030 static void mac_policy_result(const char *error,
9031                                 DBusMessageIter *iter, void *user_data)
9032 {
9033         struct supplicant_mac_policy *data = user_data;
9034         int result = 0;
9035
9036         if (!user_data)
9037                 return;
9038
9039         if (error) {
9040                 SUPPLICANT_DBG("Mac policy setting failure %s", error);
9041                 result = -EINVAL;
9042         }
9043
9044         if (data->callback)
9045                 data->callback(result, data->policy,
9046                                         (void *) data->user_data);
9047
9048         dbus_free(data);
9049 }
9050
9051 static void mac_policy_params(DBusMessageIter *iter, void *user_data)
9052 {
9053         struct supplicant_mac_policy *data = user_data;
9054
9055         dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &(data->policy));
9056 }
9057
9058 int g_supplicant_interface_set_mac_policy(GSupplicantInterface *interface,
9059                                         GSupplicantMacPolicyCallback callback,
9060                                                         unsigned int policy,
9061                                                         void *user_data)
9062 {
9063         struct supplicant_mac_policy *data = NULL;
9064         int ret;
9065
9066         if (!system_available)
9067                 return -EFAULT;
9068
9069         if (!interface)
9070                 return -EINVAL;
9071
9072         data = dbus_malloc0(sizeof(*data));
9073         if (!data)
9074                 return -ENOMEM;
9075
9076         data->callback = callback;
9077         data->policy = policy;
9078         data->user_data = user_data;
9079
9080         ret =  supplicant_dbus_property_set(interface->path,
9081                                 SUPPLICANT_INTERFACE ".Interface",
9082                                 "MacAddr", DBUS_TYPE_INT32_AS_STRING,
9083                                 mac_policy_params, mac_policy_result, data, NULL);
9084         if (ret < 0) {
9085                 SUPPLICANT_DBG("Unable to set MacAddr configuration");
9086                 dbus_free(data);
9087         }
9088
9089         return ret;
9090 }
9091
9092 int g_supplicant_interface_set_preassoc_mac_policy(GSupplicantInterface *interface,
9093                                         GSupplicantMacPolicyCallback callback,
9094                                                         unsigned int policy,
9095                                                         void *user_data)
9096 {
9097         struct supplicant_mac_policy *data;
9098         int ret;
9099
9100         if (!system_available)
9101                 return -EFAULT;
9102
9103         if (!interface)
9104                 return -EINVAL;
9105
9106         data = dbus_malloc0(sizeof(*data));
9107         if (!data)
9108                 return -ENOMEM;
9109
9110         data->callback = callback;
9111         data->policy = policy;
9112         data->user_data = user_data;
9113
9114         ret =  supplicant_dbus_property_set(interface->path,
9115                                 SUPPLICANT_INTERFACE ".Interface",
9116                                 "PreassocMacAddr", DBUS_TYPE_INT32_AS_STRING,
9117                                 mac_policy_params, mac_policy_result, data, NULL);
9118         if (ret < 0) {
9119                 SUPPLICANT_DBG("Unable to set PreassocMacAddr configuration");
9120                 dbus_free(data);
9121         }
9122
9123         return ret;
9124 }
9125
9126 struct supplicant_random_mac_lifetime {
9127         GSupplicantRandomMaclifetimeCallback callback;
9128         dbus_uint32_t lifetime;
9129         const void *user_data;
9130 };
9131
9132 static void random_mac_lifetime_result(const char *error,
9133                                 DBusMessageIter *iter, void *user_data)
9134 {
9135         struct supplicant_random_mac_lifetime *data = user_data;
9136         int result = 0;
9137
9138         if (!user_data)
9139                 return;
9140
9141         if (error) {
9142                 SUPPLICANT_DBG("Random Mac lifetime setting failure %s", error);
9143                 result = -EINVAL;
9144         }
9145
9146         if (data->callback)
9147                 data->callback(result, data->lifetime,
9148                                         (void *) data->user_data);
9149
9150         dbus_free(data);
9151 }
9152
9153 static void random_mac_lifetime_params(DBusMessageIter *iter, void *user_data)
9154 {
9155         struct supplicant_random_mac_lifetime *data = user_data;
9156
9157         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &(data->lifetime));
9158 }
9159
9160 int g_supplicant_interface_set_random_mac_lifetime(GSupplicantInterface *interface,
9161                                         GSupplicantRandomMaclifetimeCallback callback,
9162                                                         unsigned int lifetime,
9163                                                         void *user_data)
9164 {
9165         struct supplicant_random_mac_lifetime *data;
9166         int ret;
9167
9168         if (!system_available)
9169                 return -EFAULT;
9170
9171         if (!interface)
9172                 return -EINVAL;
9173
9174         data = dbus_malloc0(sizeof(*data));
9175         if (!data)
9176                 return -ENOMEM;
9177
9178         data->callback = callback;
9179         data->lifetime = lifetime;
9180         data->user_data = user_data;
9181
9182         ret =  supplicant_dbus_property_set(interface->path,
9183                                 SUPPLICANT_INTERFACE ".Interface",
9184                                 "RandAddrLifetime", DBUS_TYPE_UINT32_AS_STRING,
9185                                 random_mac_lifetime_params, random_mac_lifetime_result,
9186                                 data, NULL);
9187         if (ret < 0) {
9188                 SUPPLICANT_DBG("Unable to set RandAddrLifetime configuration");
9189                 dbus_free(data);
9190         }
9191
9192         return ret;
9193 }
9194 #endif