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