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