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