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