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