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