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