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