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