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