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