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