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