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