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