Added support of WPA3-SAE security mode.
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index dffc1d8..a7a7bd0 100644 (file)
@@ -2,7 +2,7 @@
  *
  *  WPA supplicant library with GLib integration
  *
- *  Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -30,6 +30,9 @@
 #include <stdint.h>
 #include <syslog.h>
 #include <ctype.h>
+#include <stdbool.h>
+#include <netinet/if_ether.h>
+#include <netinet/in.h>
 
 #include <glib.h>
 #include <gdbus.h>
 #include "dbus.h"
 #include "gsupplicant.h"
 
-#define TIMEOUT 5000
-
 #define IEEE80211_CAP_ESS      0x0001
 #define IEEE80211_CAP_IBSS     0x0002
 #define IEEE80211_CAP_PRIVACY  0x0010
 
+#if defined TIZEN_EXT
+#define WLAN_EID_HT_CAP 45
+#define WLAN_EID_VHT_CAP 191
+#define WLAN_EID_SUPP_RATES 1
+#define WLAN_EID_EXT_SUPP_RATES 50
+#define COUNTRY_CODE_LENGTH    2
+#define WIFI_BSSID_LEN_MAX 6
+#endif
+
+#define BSS_UNKNOWN_STRENGTH    -90
+
 static DBusConnection *connection;
 
 static const GSupplicantCallbacks *callbacks_pointer;
@@ -89,6 +101,9 @@ static struct strvalmap keymgmt_map[] = {
        { "wpa-eap",            G_SUPPLICANT_KEYMGMT_WPA_EAP    },
        { "wpa-eap-sha256",     G_SUPPLICANT_KEYMGMT_WPA_EAP_256        },
        { "wps",                G_SUPPLICANT_KEYMGMT_WPS                },
+#if defined TIZEN_EXT
+       { "sae",                G_SUPPLICANT_KEYMGMT_SAE                },
+#endif
        { }
 };
 
@@ -131,11 +146,19 @@ static struct strvalmap mode_capa_map[] = {
        { "infrastructure",     G_SUPPLICANT_CAPABILITY_MODE_INFRA      },
        { "ad-hoc",             G_SUPPLICANT_CAPABILITY_MODE_IBSS       },
        { "ap",                 G_SUPPLICANT_CAPABILITY_MODE_AP         },
+       { "p2p",                G_SUPPLICANT_CAPABILITY_MODE_P2P        },
+#if defined TIZEN_EXT_WIFI_MESH
+       { "mesh",               G_SUPPLICANT_CAPABILITY_MODE_MESH       },
+#endif
        { }
 };
 
 static GHashTable *interface_table;
 static GHashTable *bss_mapping;
+static GHashTable *peer_mapping;
+static GHashTable *group_mapping;
+static GHashTable *pending_peer_connection;
+static GHashTable *config_file_table;
 
 struct _GSupplicantWpsCredentials {
        unsigned char ssid[32];
@@ -143,6 +166,21 @@ struct _GSupplicantWpsCredentials {
        char *key;
 };
 
+struct added_network_information {
+       char * ssid;
+       GSupplicantSecurity security;
+       char * passphrase;
+       char * private_passphrase;
+};
+
+#if defined TIZEN_EXT_WIFI_MESH
+struct _GSupplicantMeshGroupInfo {
+       unsigned char ssid[32];
+       unsigned int ssid_len;
+       int disconnect_reason;
+};
+#endif
+
 struct _GSupplicantInterface {
        char *path;
        char *network_path;
@@ -154,6 +192,9 @@ struct _GSupplicantInterface {
        unsigned int scan_capa;
        unsigned int mode_capa;
        unsigned int max_scan_ssids;
+       bool p2p_support;
+       bool p2p_finding;
+       bool ap_create_in_progress;
        dbus_bool_t ready;
        GSupplicantState state;
        dbus_bool_t scanning;
@@ -166,9 +207,21 @@ struct _GSupplicantInterface {
        struct _GSupplicantWpsCredentials wps_cred;
        GSupplicantWpsState wps_state;
        GHashTable *network_table;
-       GHashTable *net_mapping;
+       GHashTable *peer_table;
+       GHashTable *group_table;
        GHashTable *bss_mapping;
        void *data;
+       const char *pending_peer_path;
+       GSupplicantNetwork *current_network;
+       struct added_network_information network_info;
+#if defined TIZEN_EXT
+       dbus_bool_t is_5_0_Ghz_supported;
+       int disconnect_reason;
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+       bool mesh_support;
+       struct _GSupplicantMeshGroupInfo group_info;
+#endif
 };
 
 struct g_supplicant_bss {
@@ -193,7 +246,18 @@ struct g_supplicant_bss {
        dbus_bool_t privacy;
        dbus_bool_t psk;
        dbus_bool_t ieee8021x;
+#if defined TIZEN_EXT
+       dbus_bool_t ft_psk;
+       dbus_bool_t ft_ieee8021x;
+       GSList *vsie_list;
+       dbus_bool_t hs20;
+       unsigned char country_code[COUNTRY_CODE_LENGTH];
+       GSupplicantPhy_mode phy_mode;
+#endif
        unsigned int wps_capabilities;
+#if defined TIZEN_EXT
+       dbus_bool_t sae;
+#endif
 };
 
 struct _GSupplicantNetwork {
@@ -212,14 +276,117 @@ struct _GSupplicantNetwork {
        unsigned int wps_capabilities;
        GHashTable *bss_table;
        GHashTable *config_table;
+#if defined TIZEN_EXT
+       bool isHS20AP;
+       char *eap;
+       char *identity;
+       char *phase2;
+       unsigned int keymgmt;
+       GSList *vsie_list;
+       unsigned char country_code[COUNTRY_CODE_LENGTH];
+       GSupplicantPhy_mode phy_mode;
+#endif
+};
+
+struct _GSupplicantPeer {
+       GSupplicantInterface *interface;
+       char *path;
+       unsigned char device_address[ETH_ALEN];
+       unsigned char iface_address[ETH_ALEN];
+       char *name;
+       unsigned char *widi_ies;
+       int widi_ies_length;
+       char *identifier;
+       unsigned int wps_capabilities;
+       GSList *groups;
+       const GSupplicantInterface *current_group_iface;
+       bool connection_requested;
+};
+
+struct _GSupplicantGroup {
+       GSupplicantInterface *interface;
+       GSupplicantInterface *orig_interface;
+       char *path;
+       int role;
+       GSList *members;
+};
+
+struct interface_data {
+       GSupplicantInterface *interface;
+       char *path; /* Interface path cannot be taken from interface (above) as
+                    * it might have been freed already.
+                    */
+       GSupplicantInterfaceCallback callback;
+       void *user_data;
+       bool network_remove_in_progress;
+       GSupplicantSSID *ssid;
+};
+
+#if defined TIZEN_EXT
+struct interface_signalpoll_data {
+       GSupplicantInterface *interface;
+       char *path;
+       GSupplicantMaxSpeedCallback callback;
+       void *user_data;
+};
+#endif
+
+struct interface_create_data {
+       char *ifname;
+       char *driver;
+       char *bridge;
+#if defined TIZEN_EXT_WIFI_MESH
+       char *parent_ifname;
+       bool is_mesh_interface;
+#endif
+       GSupplicantInterface *interface;
+       GSupplicantInterfaceCallback callback;
+       void *user_data;
+};
+
+struct interface_connect_data {
+       GSupplicantInterface *interface;
+       char *path;
+       GSupplicantInterfaceCallback callback;
+       void *user_data;
+       union {
+               GSupplicantSSID *ssid;
+               GSupplicantPeerParams *peer;
+       };
+};
+
+struct interface_scan_data {
+       GSupplicantInterface *interface;
+       char *path;
+       GSupplicantInterfaceCallback callback;
+       GSupplicantScanParams *scan_params;
+       void *user_data;
+};
+
+#if defined TIZEN_EXT
+struct g_connman_bssids {
+       unsigned char bssid[WIFI_BSSID_LEN_MAX];
+       uint16_t strength;
+       uint16_t frequency;
+};
+#endif
+
+static int network_remove(struct interface_data *data);
+
+#if defined TIZEN_EXT_WIFI_MESH
+struct _GSupplicantMeshPeer {
+       GSupplicantInterface *interface;
+       char *peer_address;
+       int disconnect_reason;
 };
+#endif
 
 static inline void debug(const char *format, ...)
 {
        char str[256];
        va_list ap;
 
-       if (callbacks_pointer->debug == NULL)
+       if (!callbacks_pointer || !callbacks_pointer->debug)
                return;
 
        va_start(ap, format);
@@ -235,13 +402,17 @@ static inline void debug(const char *format, ...)
 
 static GSupplicantMode string2mode(const char *mode)
 {
-       if (mode == NULL)
+       if (!mode)
                return G_SUPPLICANT_MODE_UNKNOWN;
 
-       if (g_str_equal(mode, "infrastructure") == TRUE)
+       if (g_str_equal(mode, "infrastructure"))
                return G_SUPPLICANT_MODE_INFRA;
-       else if (g_str_equal(mode, "ad-hoc") == TRUE)
+       else if (g_str_equal(mode, "ad-hoc"))
                return G_SUPPLICANT_MODE_IBSS;
+#if defined TIZEN_EXT_WIFI_MESH
+       else if (g_str_equal(mode, "mesh"))
+               return G_SUPPLICANT_MODE_MESH;
+#endif
 
        return G_SUPPLICANT_MODE_UNKNOWN;
 }
@@ -257,6 +428,10 @@ static const char *mode2string(GSupplicantMode mode)
                return "adhoc";
        case G_SUPPLICANT_MODE_MASTER:
                return "ap";
+#if defined TIZEN_EXT_WIFI_MESH
+       case G_SUPPLICANT_MODE_MESH:
+               return "mesh";
+#endif
        }
 
        return NULL;
@@ -275,6 +450,14 @@ static const char *security2string(GSupplicantSecurity security)
                return "psk";
        case G_SUPPLICANT_SECURITY_IEEE8021X:
                return "ieee8021x";
+#if defined TIZEN_EXT
+       case G_SUPPLICANT_SECURITY_FT_PSK:
+               return "ft_psk";
+       case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
+               return "ft_ieee8021x";
+       case G_SUPPLICANT_SECURITY_SAE:
+               return "sae";
+#endif
        }
 
        return NULL;
@@ -282,44 +465,115 @@ static const char *security2string(GSupplicantSecurity security)
 
 static GSupplicantState string2state(const char *state)
 {
-       if (state == NULL)
+       if (!state)
                return G_SUPPLICANT_STATE_UNKNOWN;
 
-       if (g_str_equal(state, "unknown") == TRUE)
+       if (g_str_equal(state, "unknown"))
                return G_SUPPLICANT_STATE_UNKNOWN;
-       else if (g_str_equal(state, "disconnected") == TRUE)
+       else if (g_str_equal(state, "interface_disabled"))
+               return G_SUPPLICANT_STATE_DISABLED;
+       else if (g_str_equal(state, "disconnected"))
                return G_SUPPLICANT_STATE_DISCONNECTED;
-       else if (g_str_equal(state, "inactive") == TRUE)
+       else if (g_str_equal(state, "inactive"))
                return G_SUPPLICANT_STATE_INACTIVE;
-       else if (g_str_equal(state, "scanning") == TRUE)
+       else if (g_str_equal(state, "scanning"))
                return G_SUPPLICANT_STATE_SCANNING;
-       else if (g_str_equal(state, "authenticating") == TRUE)
+       else if (g_str_equal(state, "authenticating"))
                return G_SUPPLICANT_STATE_AUTHENTICATING;
-       else if (g_str_equal(state, "associating") == TRUE)
+       else if (g_str_equal(state, "associating"))
                return G_SUPPLICANT_STATE_ASSOCIATING;
-       else if (g_str_equal(state, "associated") == TRUE)
+       else if (g_str_equal(state, "associated"))
                return G_SUPPLICANT_STATE_ASSOCIATED;
-       else if (g_str_equal(state, "group_handshake") == TRUE)
+       else if (g_str_equal(state, "group_handshake"))
                return G_SUPPLICANT_STATE_GROUP_HANDSHAKE;
-       else if (g_str_equal(state, "4way_handshake") == TRUE)
+       else if (g_str_equal(state, "4way_handshake"))
                return G_SUPPLICANT_STATE_4WAY_HANDSHAKE;
-       else if (g_str_equal(state, "completed") == TRUE)
+       else if (g_str_equal(state, "completed"))
                return G_SUPPLICANT_STATE_COMPLETED;
 
        return G_SUPPLICANT_STATE_UNKNOWN;
 }
 
+static bool compare_network_parameters(GSupplicantInterface *interface,
+                               GSupplicantSSID *ssid)
+{
+#if defined TIZEN_EXT
+       if (!interface->network_info.ssid)
+               return FALSE;
+#endif
+
+       if (memcmp(interface->network_info.ssid, ssid->ssid, ssid->ssid_len))
+               return FALSE;
+
+       if (interface->network_info.security != ssid->security)
+               return FALSE;
+
+       if (interface->network_info.passphrase &&
+                       g_strcmp0(interface->network_info.passphrase,
+                               ssid->passphrase) != 0) {
+               return FALSE;
+       }
+
+       if (interface->network_info.private_passphrase &&
+                       g_strcmp0(interface->network_info.private_passphrase,
+                               ssid->private_key_passphrase) != 0) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void remove_network_information(GSupplicantInterface * interface)
+{
+       g_free(interface->network_info.ssid);
+       g_free(interface->network_info.passphrase);
+       g_free(interface->network_info.private_passphrase);
+       interface->network_info.ssid = NULL;
+       interface->network_info.passphrase = NULL;
+       interface->network_info.private_passphrase = NULL;
+}
+
+static int store_network_information(GSupplicantInterface * interface,
+                               GSupplicantSSID *ssid)
+{
+       interface->network_info.ssid = g_malloc(ssid->ssid_len + 1);
+       if (interface->network_info.ssid != NULL) {
+               memcpy(interface->network_info.ssid, ssid->ssid,
+                       ssid->ssid_len);
+               interface->network_info.ssid[ssid->ssid_len] = '\0';
+       } else {
+               return -ENOMEM;
+       }
+
+       interface->network_info.security = ssid->security;
+
+       if ((ssid->security == G_SUPPLICANT_SECURITY_WEP ||
+               ssid->security == G_SUPPLICANT_SECURITY_PSK ||
+               ssid->security == G_SUPPLICANT_SECURITY_NONE) &&
+               ssid->passphrase) {
+               interface->network_info.passphrase = g_strdup(ssid->passphrase);
+       }
+
+       if (ssid->security == G_SUPPLICANT_SECURITY_IEEE8021X &&
+                       ssid->private_key_passphrase) {
+               interface->network_info.private_passphrase =
+                       g_strdup(ssid->private_key_passphrase);
+       }
+
+       return 0;
+}
+
 static void callback_system_ready(void)
 {
-       if (system_ready == TRUE)
+       if (system_ready)
                return;
 
        system_ready = TRUE;
 
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->system_ready == NULL)
+       if (!callbacks_pointer->system_ready)
                return;
 
        callbacks_pointer->system_ready();
@@ -329,10 +583,10 @@ static void callback_system_killed(void)
 {
        system_ready = FALSE;
 
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->system_killed == NULL)
+       if (!callbacks_pointer->system_killed)
                return;
 
        callbacks_pointer->system_killed();
@@ -342,10 +596,10 @@ static void callback_interface_added(GSupplicantInterface *interface)
 {
        SUPPLICANT_DBG("");
 
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->interface_added == NULL)
+       if (!callbacks_pointer->interface_added)
                return;
 
        callbacks_pointer->interface_added(interface);
@@ -353,10 +607,10 @@ static void callback_interface_added(GSupplicantInterface *interface)
 
 static void callback_interface_state(GSupplicantInterface *interface)
 {
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->interface_state == NULL)
+       if (!callbacks_pointer->interface_state)
                return;
 
        callbacks_pointer->interface_state(interface);
@@ -364,32 +618,77 @@ static void callback_interface_state(GSupplicantInterface *interface)
 
 static void callback_interface_removed(GSupplicantInterface *interface)
 {
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->interface_removed == NULL)
+       if (!callbacks_pointer->interface_removed)
                return;
 
        callbacks_pointer->interface_removed(interface);
 }
 
+#if !defined TIZEN_EXT
+static void callback_p2p_support(GSupplicantInterface *interface)
+{
+       SUPPLICANT_DBG("");
+
+       if (!interface->p2p_support)
+               return;
+
+       if (callbacks_pointer && callbacks_pointer->p2p_support)
+               callbacks_pointer->p2p_support(interface);
+}
+#endif
+
+#if defined TIZEN_EXT_WIFI_MESH
+static void callback_mesh_support(GSupplicantInterface *interface)
+{
+       SUPPLICANT_DBG("");
+
+       if (!interface->mesh_support)
+               return;
+
+       if (callbacks_pointer && callbacks_pointer->mesh_support)
+               callbacks_pointer->mesh_support(interface);
+}
+
+bool g_supplicant_interface_has_mesh(GSupplicantInterface *interface)
+{
+       if (!interface)
+               return false;
+
+       return interface->mesh_support;
+}
+#endif
+
 static void callback_scan_started(GSupplicantInterface *interface)
 {
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->scan_started == NULL)
+       if (!callbacks_pointer->scan_started)
                return;
 
        callbacks_pointer->scan_started(interface);
 }
 
+static void callback_ap_create_fail(GSupplicantInterface *interface)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->ap_create_fail)
+               return;
+
+       callbacks_pointer->ap_create_fail(interface);
+}
+
 static void callback_scan_finished(GSupplicantInterface *interface)
 {
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->scan_finished == NULL)
+       if (!callbacks_pointer->scan_finished)
                return;
 
        callbacks_pointer->scan_finished(interface);
@@ -397,10 +696,10 @@ static void callback_scan_finished(GSupplicantInterface *interface)
 
 static void callback_network_added(GSupplicantNetwork *network)
 {
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->network_added == NULL)
+       if (!callbacks_pointer->network_added)
                return;
 
        callbacks_pointer->network_added(network);
@@ -408,36 +707,157 @@ static void callback_network_added(GSupplicantNetwork *network)
 
 static void callback_network_removed(GSupplicantNetwork *network)
 {
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->network_removed == NULL)
+       if (!callbacks_pointer->network_removed)
                return;
 
        callbacks_pointer->network_removed(network);
 }
 
+#if defined TIZEN_EXT
+static void callback_network_merged(GSupplicantNetwork *network)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->network_merged)
+               return;
+
+       callbacks_pointer->network_merged(network);
+}
+
+static void callback_assoc_failed(void *user_data)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->assoc_failed)
+               return;
+
+       callbacks_pointer->assoc_failed(user_data);
+}
+#endif
+
 static void callback_network_changed(GSupplicantNetwork *network,
                                        const char *property)
 {
-       if (callbacks_pointer == NULL)
+       if (!callbacks_pointer)
                return;
 
-       if (callbacks_pointer->network_changed == NULL)
+       if (!callbacks_pointer->network_changed)
                return;
 
        callbacks_pointer->network_changed(network, property);
 }
 
+static void callback_network_associated(GSupplicantNetwork *network)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->network_associated)
+               return;
+
+       callbacks_pointer->network_associated(network);
+}
+
+static void callback_peer_found(GSupplicantPeer *peer)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->peer_found)
+               return;
+
+       callbacks_pointer->peer_found(peer);
+}
+
+static void callback_peer_lost(GSupplicantPeer *peer)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->peer_lost)
+               return;
+
+       callbacks_pointer->peer_lost(peer);
+}
+
+static void callback_peer_changed(GSupplicantPeer *peer,
+                                               GSupplicantPeerState state)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->peer_changed)
+               return;
+
+       callbacks_pointer->peer_changed(peer, state);
+}
+
+static void callback_peer_request(GSupplicantPeer *peer)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->peer_request)
+               return;
+
+       peer->connection_requested = true;
+
+       callbacks_pointer->peer_request(peer);
+}
+
+static void callback_disconnect_reason_code(GSupplicantInterface *interface,
+                                       int reason_code)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->disconnect_reasoncode)
+               return;
+
+       if (reason_code != 0)
+               callbacks_pointer->disconnect_reasoncode(interface,
+                                                       reason_code);
+}
+
+static void callback_assoc_status_code(GSupplicantInterface *interface,
+                               int status_code)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->assoc_status_code)
+               return;
+
+       callbacks_pointer->assoc_status_code(interface, status_code);
+
+}
+
+static void remove_group(gpointer data)
+{
+       GSupplicantGroup *group = data;
+
+       if (group->members)
+               g_slist_free_full(group->members, g_free);
+
+       g_free(group->path);
+       g_free(group);
+}
+
 static void remove_interface(gpointer data)
 {
        GSupplicantInterface *interface = data;
 
        g_hash_table_destroy(interface->bss_mapping);
-       g_hash_table_destroy(interface->net_mapping);
        g_hash_table_destroy(interface->network_table);
+       g_hash_table_destroy(interface->peer_table);
+       g_hash_table_destroy(interface->group_table);
 
-       if (interface->scan_callback != NULL) {
+       if (interface->scan_callback) {
                SUPPLICANT_DBG("call interface %p callback %p scanning %d",
                                interface, interface->scan_callback,
                                interface->scanning);
@@ -446,7 +866,7 @@ static void remove_interface(gpointer data)
                 interface->scan_callback = NULL;
                 interface->scan_data = NULL;
 
-               if (interface->scanning == TRUE) {
+               if (interface->scanning) {
                        interface->scanning = FALSE;
                        callback_scan_finished(interface);
                }
@@ -457,9 +877,13 @@ static void remove_interface(gpointer data)
        g_free(interface->wps_cred.key);
        g_free(interface->path);
        g_free(interface->network_path);
+#if defined TIZEN_EXT
+       interface->network_path = NULL;
+#endif
        g_free(interface->ifname);
        g_free(interface->driver);
        g_free(interface->bridge);
+       remove_network_information(interface);
        g_free(interface);
 }
 
@@ -476,6 +900,15 @@ static void remove_network(gpointer data)
        g_free(network->path);
        g_free(network->group);
        g_free(network->name);
+#if defined TIZEN_EXT
+       g_free(network->eap);
+       g_free(network->identity);
+       g_free(network->phase2);
+#endif
+#if defined TIZEN_EXT
+       g_slist_free_full(network->vsie_list, g_free);
+#endif
+
        g_free(network);
 }
 
@@ -484,15 +917,41 @@ static void remove_bss(gpointer data)
        struct g_supplicant_bss *bss = data;
 
        g_free(bss->path);
+#if defined TIZEN_EXT
+       g_slist_free_full(bss->vsie_list, g_free);
+#endif
        g_free(bss);
 }
 
+static void remove_peer(gpointer data)
+{
+       GSupplicantPeer *peer = data;
+
+       callback_peer_lost(peer);
+
+       if (peer->groups)
+               g_slist_free_full(peer->groups, g_free);
+
+       if (peer_mapping)
+               g_hash_table_remove(peer_mapping, peer->path);
+
+       if (pending_peer_connection)
+               g_hash_table_remove(pending_peer_connection, peer->path);
+
+       g_free(peer->path);
+       g_free(peer->name);
+       g_free(peer->identifier);
+       g_free(peer->widi_ies);
+
+       g_free(peer);
+}
+
 static void debug_strvalmap(const char *label, struct strvalmap *map,
                                                        unsigned int val)
 {
        int i;
 
-       for (i = 0; map[i].str != NULL; i++) {
+       for (i = 0; map[i].str; i++) {
                if (val & map[i].val)
                        SUPPLICANT_DBG("%s: %s", label, map[i].str);
        }
@@ -505,10 +964,10 @@ static void interface_capability_keymgmt(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; keymgmt_map[i].str != NULL; i++)
+       for (i = 0; keymgmt_map[i].str; i++)
                if (strcmp(str, keymgmt_map[i].str) == 0) {
                        interface->keymgmt_capa |= keymgmt_map[i].val;
                        break;
@@ -522,10 +981,10 @@ static void interface_capability_authalg(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; authalg_capa_map[i].str != NULL; i++)
+       for (i = 0; authalg_capa_map[i].str; i++)
                if (strcmp(str, authalg_capa_map[i].str) == 0) {
                        interface->authalg_capa |= authalg_capa_map[i].val;
                        break;
@@ -539,10 +998,10 @@ static void interface_capability_proto(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; proto_capa_map[i].str != NULL; i++)
+       for (i = 0; proto_capa_map[i].str; i++)
                if (strcmp(str, proto_capa_map[i].str) == 0) {
                        interface->proto_capa |= proto_capa_map[i].val;
                        break;
@@ -557,10 +1016,10 @@ static void interface_capability_pairwise(DBusMessageIter *iter,
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; pairwise_map[i].str != NULL; i++)
+       for (i = 0; pairwise_map[i].str; i++)
                if (strcmp(str, pairwise_map[i].str) == 0) {
                        interface->pairwise_capa |= pairwise_map[i].val;
                        break;
@@ -574,10 +1033,10 @@ static void interface_capability_group(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; group_map[i].str != NULL; i++)
+       for (i = 0; group_map[i].str; i++)
                if (strcmp(str, group_map[i].str) == 0) {
                        interface->group_capa |= group_map[i].val;
                        break;
@@ -591,10 +1050,10 @@ static void interface_capability_scan(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; scan_capa_map[i].str != NULL; i++)
+       for (i = 0; scan_capa_map[i].str; i++)
                if (strcmp(str, scan_capa_map[i].str) == 0) {
                        interface->scan_capa |= scan_capa_map[i].val;
                        break;
@@ -608,10 +1067,10 @@ static void interface_capability_mode(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; mode_capa_map[i].str != NULL; i++)
+       for (i = 0; mode_capa_map[i].str; i++)
                if (strcmp(str, mode_capa_map[i].str) == 0) {
                        interface->mode_capa |= mode_capa_map[i].val;
                        break;
@@ -623,7 +1082,7 @@ static void interface_capability(const char *key, DBusMessageIter *iter,
 {
        GSupplicantInterface *interface = user_data;
 
-       if (key == NULL)
+       if (!key)
                return;
 
        if (g_strcmp0(key, "KeyMgmt") == 0)
@@ -651,41 +1110,91 @@ static void interface_capability(const char *key, DBusMessageIter *iter,
                dbus_int32_t max_scan_ssid;
 
                dbus_message_iter_get_basic(iter, &max_scan_ssid);
+               if (max_scan_ssid < 2)
+                       max_scan_ssid = 0;
                interface->max_scan_ssids = max_scan_ssid;
+#if defined TIZEN_EXT
+       } else if (g_strcmp0(key, "Is5GhzSupported") == 0) {
+               dbus_bool_t is_5_0_Ghz_supported;
 
+               dbus_message_iter_get_basic(iter, &is_5_0_Ghz_supported);
+               interface->is_5_0_Ghz_supported = is_5_0_Ghz_supported;
+#endif
        } else
                SUPPLICANT_DBG("key %s type %c",
                                key, dbus_message_iter_get_arg_type(iter));
 }
 
+struct set_apscan_data
+{
+       unsigned int ap_scan;
+       GSupplicantInterface *interface;
+};
+
 static void set_apscan(DBusMessageIter *iter, void *user_data)
 {
-       unsigned int ap_scan = *(unsigned int *)user_data;
+       struct set_apscan_data *data = user_data;
+       unsigned int ap_scan = data->ap_scan;
 
        dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &ap_scan);
 }
 
-int g_supplicant_interface_set_apscan(GSupplicantInterface *interface,
-                                                       unsigned int ap_scan)
+static void set_apscan_complete(const char *error,
+               DBusMessageIter *iter, void *user_data)
 {
-       return supplicant_dbus_property_set(interface->path,
-                       SUPPLICANT_INTERFACE ".Interface",
-                               "ApScan", DBUS_TYPE_UINT32_AS_STRING,
-                                       set_apscan, NULL, &ap_scan);
-}
+       struct set_apscan_data *data = user_data;
+       GSupplicantInterface *interface = data->interface;
 
-void g_supplicant_interface_set_data(GSupplicantInterface *interface,
-                                                               void *data)
-{
-       if (interface == NULL)
-               return;
+       if (error) {
+               interface->ap_create_in_progress = false;
+               SUPPLICANT_DBG("Set AP scan error %s", error);
+               goto error;
+       }
 
-       interface->data = data;
+       interface->ap_create_in_progress = true;
+error:
+       dbus_free(data);
+}
+
+int g_supplicant_interface_set_apscan(GSupplicantInterface *interface,
+                                                       unsigned int ap_scan)
+{
+       struct set_apscan_data *data;
+       int ret;
+
+       data = dbus_malloc0(sizeof(*data));
+
+       if (!data)
+               return -ENOMEM;
+
+       data->ap_scan = ap_scan;
+       data->interface = interface;
+
+       ret = supplicant_dbus_property_set(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface",
+                       "ApScan", DBUS_TYPE_UINT32_AS_STRING,
+                       set_apscan, set_apscan_complete, data, NULL);
+       if (ret < 0)
+               dbus_free(data);
+
+       return ret;
+}
+
+void g_supplicant_interface_set_data(GSupplicantInterface *interface,
+                                                               void *data)
+{
+       if (!interface)
+               return;
+
+       interface->data = data;
+
+       if (!data)
+               interface->scan_callback = NULL;
 }
 
 void *g_supplicant_interface_get_data(GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return NULL;
 
        return interface->data;
@@ -693,15 +1202,25 @@ void *g_supplicant_interface_get_data(GSupplicantInterface *interface)
 
 const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return NULL;
 
        return interface->ifname;
 }
 
+#if defined TIZEN_EXT
+bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *interface)
+{
+       if (!interface)
+               return NULL;
+
+       return interface->is_5_0_Ghz_supported;
+}
+#endif
+
 const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return NULL;
 
        return interface->driver;
@@ -710,7 +1229,7 @@ const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface)
 GSupplicantState g_supplicant_interface_get_state(
                                        GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return G_SUPPLICANT_STATE_UNKNOWN;
 
        return interface->state;
@@ -718,7 +1237,7 @@ GSupplicantState g_supplicant_interface_get_state(
 
 const char *g_supplicant_interface_get_wps_key(GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return NULL;
 
        return (const char *)interface->wps_cred.key;
@@ -727,10 +1246,10 @@ const char *g_supplicant_interface_get_wps_key(GSupplicantInterface *interface)
 const void *g_supplicant_interface_get_wps_ssid(GSupplicantInterface *interface,
                                                        unsigned int *ssid_len)
 {
-       if (ssid_len == NULL)
+       if (!ssid_len)
                return NULL;
 
-       if (interface == NULL || interface->wps_cred.ssid == NULL) {
+       if (!interface || interface->wps_cred.ssid_len == 0) {
                *ssid_len = 0;
                return NULL;
        }
@@ -742,7 +1261,7 @@ const void *g_supplicant_interface_get_wps_ssid(GSupplicantInterface *interface,
 GSupplicantWpsState g_supplicant_interface_get_wps_state(
                                        GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return G_SUPPLICANT_WPS_STATE_UNKNOWN;
 
        return interface->wps_state;
@@ -750,7 +1269,7 @@ GSupplicantWpsState g_supplicant_interface_get_wps_state(
 
 unsigned int g_supplicant_interface_get_mode(GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return 0;
 
        return interface->mode_capa;
@@ -759,7 +1278,7 @@ unsigned int g_supplicant_interface_get_mode(GSupplicantInterface *interface)
 unsigned int g_supplicant_interface_get_max_scan_ssids(
                                GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return 0;
 
        if (interface->max_scan_ssids == 0)
@@ -778,22 +1297,22 @@ static void set_network_enabled(DBusMessageIter *iter, void *user_data)
 int g_supplicant_interface_enable_selected_network(GSupplicantInterface *interface,
                                                        dbus_bool_t enable)
 {
-       if (interface == NULL)
+       if (!interface)
                return -1;
 
-       if (interface->network_path == NULL)
+       if (!interface->network_path)
                return -1;
 
        SUPPLICANT_DBG(" ");
        return supplicant_dbus_property_set(interface->network_path,
                                SUPPLICANT_INTERFACE ".Network",
                                "Enabled", DBUS_TYPE_BOOLEAN_AS_STRING,
-                               set_network_enabled, NULL, &enable);
+                               set_network_enabled, NULL, &enable, NULL);
 }
 
 dbus_bool_t g_supplicant_interface_get_ready(GSupplicantInterface *interface)
 {
-       if (interface == NULL)
+       if (!interface)
                return FALSE;
 
        return interface->ready;
@@ -802,7 +1321,7 @@ dbus_bool_t g_supplicant_interface_get_ready(GSupplicantInterface *interface)
 GSupplicantInterface *g_supplicant_network_get_interface(
                                        GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return NULL;
 
        return network->interface;
@@ -810,7 +1329,7 @@ GSupplicantInterface *g_supplicant_network_get_interface(
 
 const char *g_supplicant_network_get_name(GSupplicantNetwork *network)
 {
-       if (network == NULL || network->name == NULL)
+       if (!network || !network->name)
                return "";
 
        return network->name;
@@ -818,7 +1337,7 @@ const char *g_supplicant_network_get_name(GSupplicantNetwork *network)
 
 const char *g_supplicant_network_get_identifier(GSupplicantNetwork *network)
 {
-       if (network == NULL || network->group == NULL)
+       if (!network || !network->group)
                return "";
 
        return network->group;
@@ -826,7 +1345,7 @@ const char *g_supplicant_network_get_identifier(GSupplicantNetwork *network)
 
 const char *g_supplicant_network_get_path(GSupplicantNetwork *network)
 {
-       if (network == NULL || network->path == NULL)
+       if (!network || !network->path)
                return NULL;
 
        return network->path;
@@ -834,7 +1353,7 @@ const char *g_supplicant_network_get_path(GSupplicantNetwork *network)
 
 const char *g_supplicant_network_get_mode(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return G_SUPPLICANT_MODE_UNKNOWN;
 
        return mode2string(network->mode);
@@ -842,7 +1361,7 @@ const char *g_supplicant_network_get_mode(GSupplicantNetwork *network)
 
 const char *g_supplicant_network_get_security(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return G_SUPPLICANT_SECURITY_UNKNOWN;
 
        return security2string(network->security);
@@ -851,7 +1370,7 @@ const char *g_supplicant_network_get_security(GSupplicantNetwork *network)
 const void *g_supplicant_network_get_ssid(GSupplicantNetwork *network,
                                                unsigned int *ssid_len)
 {
-       if (network == NULL || network->ssid == NULL) {
+       if (!network) {
                *ssid_len = 0;
                return NULL;
        }
@@ -862,7 +1381,7 @@ const void *g_supplicant_network_get_ssid(GSupplicantNetwork *network,
 
 dbus_int16_t g_supplicant_network_get_signal(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return 0;
 
        return network->signal;
@@ -870,7 +1389,7 @@ dbus_int16_t g_supplicant_network_get_signal(GSupplicantNetwork *network)
 
 dbus_uint16_t g_supplicant_network_get_frequency(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return 0;
 
        return network->frequency;
@@ -878,7 +1397,7 @@ dbus_uint16_t g_supplicant_network_get_frequency(GSupplicantNetwork *network)
 
 dbus_bool_t g_supplicant_network_get_wps(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return FALSE;
 
        return network->wps;
@@ -886,7 +1405,7 @@ dbus_bool_t g_supplicant_network_get_wps(GSupplicantNetwork *network)
 
 dbus_bool_t g_supplicant_network_is_wps_active(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return FALSE;
 
        if (network->wps_capabilities & G_SUPPLICANT_WPS_CONFIGURED)
@@ -897,7 +1416,7 @@ dbus_bool_t g_supplicant_network_is_wps_active(GSupplicantNetwork *network)
 
 dbus_bool_t g_supplicant_network_is_wps_pbc(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return FALSE;
 
        if (network->wps_capabilities & G_SUPPLICANT_WPS_PBC)
@@ -908,7 +1427,7 @@ dbus_bool_t g_supplicant_network_is_wps_pbc(GSupplicantNetwork *network)
 
 dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
 {
-       if (network == NULL)
+       if (!network)
                return FALSE;
 
        if (network->wps_capabilities & G_SUPPLICANT_WPS_REGISTRAR)
@@ -917,43 +1436,433 @@ dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
        return FALSE;
 }
 
+#ifdef TIZEN_EXT
+GSupplicantPhy_mode g_supplicant_network_get_phy_mode(GSupplicantNetwork *network)
+{
+       if (!network)
+               return G_SUPPLICANT_MODE_IEEE80211_UNKNOWN;
+
+       return network->phy_mode;
+}
+#endif
+
+GSupplicantInterface *g_supplicant_peer_get_interface(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return NULL;
+
+       return peer->interface;
+}
+
+const char *g_supplicant_peer_get_path(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return NULL;
+
+       return peer->path;
+}
+
+const char *g_supplicant_peer_get_identifier(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return NULL;
+
+       return peer->identifier;
+}
+
+const void *g_supplicant_peer_get_device_address(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return NULL;
+
+       return peer->device_address;
+}
+
+const void *g_supplicant_peer_get_iface_address(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return NULL;
+
+       return peer->iface_address;
+}
+
+const char *g_supplicant_peer_get_name(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return NULL;
+
+       return peer->name;
+}
+
+#if defined TIZEN_EXT
+bool g_supplicant_network_is_hs20AP(GSupplicantNetwork *network)
+{
+       if (!network)
+               return 0;
+
+       return network->isHS20AP;
+}
+
+const char *g_supplicant_network_get_eap(GSupplicantNetwork *network)
+{
+       if (!network || !network->eap)
+               return NULL;
+
+       return network->eap;
+}
+
+const char *g_supplicant_network_get_identity(GSupplicantNetwork *network)
+{
+       if (!network || !network->identity)
+               return NULL;
+
+       return network->identity;
+}
+
+const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network)
+{
+       if (!network || !network->phase2)
+               return NULL;
+
+       return network->phase2;
+}
+
+unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network)
+{
+       if (network == NULL)
+               return 0;
+
+       return network->keymgmt;
+}
+
+const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork
+                                                         *network)
+{
+       if (!network)
+               return NULL;
+
+       return network->country_code;
+}
+#endif
+
+const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer,
+                                                               int *length)
+{
+       if (!peer || !length)
+               return NULL;
+
+       *length = peer->widi_ies_length;
+       return peer->widi_ies;
+}
+
+bool g_supplicant_peer_is_wps_pbc(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return false;
+
+       if (peer->wps_capabilities & G_SUPPLICANT_WPS_PBC)
+               return true;
+
+       return false;
+}
+
+bool g_supplicant_peer_is_wps_pin(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return false;
+
+       if (peer->wps_capabilities & G_SUPPLICANT_WPS_PIN)
+               return true;
+
+       return false;
+}
+
+bool g_supplicant_peer_is_in_a_group(GSupplicantPeer *peer)
+{
+       if (!peer || !peer->groups)
+               return false;
+
+       return true;
+}
+
+GSupplicantInterface *g_supplicant_peer_get_group_interface(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return NULL;
+
+       return (GSupplicantInterface *) peer->current_group_iface;
+}
+
+bool g_supplicant_peer_is_client(GSupplicantPeer *peer)
+{
+       GSupplicantGroup *group;
+       GSList *list;
+
+       if (!peer)
+               return false;
+
+       for (list = peer->groups; list; list = list->next) {
+               const char *path = list->data;
+
+               group = g_hash_table_lookup(group_mapping, path);
+               if (!group)
+                       continue;
+
+               if (group->role != G_SUPPLICANT_GROUP_ROLE_CLIENT ||
+                               group->orig_interface != peer->interface)
+                       continue;
+
+               if (group->interface == peer->current_group_iface)
+                       return true;
+       }
+
+       return false;
+}
+
+bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer)
+{
+       if (!peer)
+               return false;
+
+       return peer->connection_requested;
+}
+
+#if defined TIZEN_EXT
+/*
+ * Description: Network client requires additional wifi specific info
+ */
+const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return NULL;
+
+       return (const unsigned char *)network->best_bss->bssid;
+}
+
+unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return 0;
+
+       return network->best_bss->maxrate;
+}
+
+const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return NULL;
+
+       if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
+#if defined TIZEN_EXT
+           network->best_bss->security == G_SUPPLICANT_SECURITY_SAE ||
+#endif /* TIZEN_EXT */
+           network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
+               unsigned int pairwise;
+
+               pairwise = network->best_bss->rsn_pairwise |
+                               network->best_bss->wpa_pairwise;
+
+               if ((pairwise & G_SUPPLICANT_PAIRWISE_CCMP) &&
+                   (pairwise & G_SUPPLICANT_PAIRWISE_TKIP))
+                       return "mixed";
+               else if (pairwise & G_SUPPLICANT_PAIRWISE_CCMP)
+                       return "aes";
+               else if (pairwise & G_SUPPLICANT_PAIRWISE_TKIP)
+                       return "tkip";
+
+       } else if (network->best_bss->security == G_SUPPLICANT_SECURITY_WEP)
+               return "wep";
+       else if (network->best_bss->security == G_SUPPLICANT_SECURITY_NONE)
+               return "none";
+
+       return NULL;
+}
+
+bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network)
+{
+       if (network == NULL || network->best_bss == NULL)
+               return 0;
+
+#if defined TIZEN_EXT
+       if (network->best_bss->security == G_SUPPLICANT_SECURITY_SAE)
+               return false;
+#endif /* TIZEN_EXT */
+
+       if (network->best_bss->rsn_selected) {
+               const char *mode = g_supplicant_network_get_enc_mode(network);
+               if (g_strcmp0(mode, "aes") == 0 ||
+                               g_strcmp0(mode, "mixed") == 0)
+                       return true;
+               else
+                       return false;
+       } else
+               return false;
+}
+
+void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network)
+{
+       GSList *vsie_list = NULL;
+
+       if (!network)
+               return NULL;
+
+       if (g_slist_length(network->vsie_list) > 0) {
+               GSList *list = NULL;
+               unsigned char *vsie = NULL;
+               for (list = network->vsie_list; list; list = list->next) {
+                       unsigned char *ie = (unsigned char *)list->data;
+                       if (ie == NULL)
+                               continue;
+                       vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1)
+
+                       if (vsie) {
+                               memcpy(vsie, ie, ie[1]+2);
+                               vsie_list = g_slist_append(vsie_list, vsie);
+                       } else
+                               SUPPLICANT_DBG("Failed to allocate memory");
+               }
+       }
+
+       return vsie_list;
+}
+
+static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
+{
+       struct g_supplicant_bss *bss = value;
+       struct g_connman_bssids *bssids = NULL;
+       GSList **list = (GSList **)user_data;
+
+       bssids = (struct g_connman_bssids *)g_try_malloc0(sizeof(struct g_connman_bssids));
+
+       if (bssids) {
+               memcpy(bssids->bssid, bss->bssid, WIFI_BSSID_LEN_MAX);
+
+               bssids->strength = bss->signal;
+               bssids->strength += 120;
+
+               if (bssids->strength > 100)
+                       bssids->strength = 100;
+
+               bssids->frequency = bss->frequency;
+               *list = g_slist_append(*list, bssids);
+       } else
+               SUPPLICANT_DBG("Failed to allocate memory");
+}
+
+static gint cmp_bss(gconstpointer a, gconstpointer b)
+{
+       struct g_connman_bssids *entry_a = (struct g_connman_bssids *)a;
+       struct g_connman_bssids *entry_b = (struct g_connman_bssids *)b;
+
+       if (entry_a->strength > entry_b->strength)
+               return -1;
+
+       if (entry_a->strength < entry_b->strength)
+               return 1;
+
+       return 0;
+}
+
+void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network)
+{
+       GSList *bssid_list = NULL;
+
+       if (g_hash_table_size(network->bss_table) < 1)
+               return NULL;
+
+       g_hash_table_foreach(network->bss_table, update_bssid_list, &bssid_list);
+       bssid_list = g_slist_sort(bssid_list, cmp_bss);
+
+       return bssid_list;
+}
+#endif
+
 static void merge_network(GSupplicantNetwork *network)
 {
        GString *str;
        const char *ssid, *mode, *key_mgmt;
+#if defined TIZEN_EXT
+       const char *isHS20AP;
+       const char *eap, *identity, *phase2;
+#endif
        unsigned int i, ssid_len;
        char *group;
 
        ssid = g_hash_table_lookup(network->config_table, "ssid");
        mode = g_hash_table_lookup(network->config_table, "mode");
        key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt");
+#if defined TIZEN_EXT
+       isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP");
+       eap = g_hash_table_lookup(network->config_table, "eap");
+       identity = g_hash_table_lookup(network->config_table, "identity");
+       phase2 = g_hash_table_lookup(network->config_table, "phase2");
+#endif
 
        SUPPLICANT_DBG("ssid %s mode %s", ssid, mode);
 
-       if (ssid != NULL)
+       if (ssid)
                ssid_len = strlen(ssid);
        else
                ssid_len = 0;
 
        str = g_string_sized_new((ssid_len * 2) + 24);
-       if (str == NULL)
+       if (!str)
                return;
 
        for (i = 0; i < ssid_len; i++)
+#if defined TIZEN_EXT
+       {
+               if (ssid[i] != '"')
+#endif
                g_string_append_printf(str, "%02x", ssid[i]);
+#if defined TIZEN_EXT
+       }
+#endif
 
        if (g_strcmp0(mode, "0") == 0)
                g_string_append_printf(str, "_managed");
        else if (g_strcmp0(mode, "1") == 0)
                g_string_append_printf(str, "_adhoc");
+#if defined TIZEN_EXT_WIFI_MESH
+       else if (g_strcmp0(mode, "5") == 0)
+               g_string_append_printf(str, "_mesh");
+#endif
 
        if (g_strcmp0(key_mgmt, "WPA-PSK") == 0)
                g_string_append_printf(str, "_psk");
+#if defined TIZEN_EXT
+       else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0)
+               g_string_append_printf(str, "_ieee8021x");
+       else
+               g_string_append_printf(str, "_none");
+#endif
 
        group = g_string_free(str, FALSE);
 
        SUPPLICANT_DBG("%s", group);
 
+#if defined TIZEN_EXT
+       if (g_strcmp0(isHS20AP, "1") == 0) {
+               network->isHS20AP = 1;
+               if (network->eap)
+                       g_free(network->eap);
+               network->eap = g_strdup(eap);
+
+               if (network->identity)
+                       g_free(network->identity);
+               network->identity = g_strdup(identity);
+
+               if (network->phase2)
+                       g_free(network->phase2);
+               network->phase2 = g_strdup(phase2);
+       } else
+               network->isHS20AP = 0;
+
+       network->group = g_strdup(group);
+       callback_network_merged(network);
+       g_free(network->group);
+#endif
+
        g_free(group);
 
        g_hash_table_destroy(network->config_table);
@@ -967,10 +1876,10 @@ static void network_property(const char *key, DBusMessageIter *iter,
 {
        GSupplicantNetwork *network = user_data;
 
-       if (network->interface == NULL)
+       if (!network->interface)
                return;
 
-       if (key == NULL) {
+       if (!key) {
                merge_network(network);
                return;
        }
@@ -983,7 +1892,7 @@ static void network_property(const char *key, DBusMessageIter *iter,
                const char *str = NULL;
 
                dbus_message_iter_get_basic(iter, &str);
-               if (str != NULL) {
+               if (str) {
                        g_hash_table_replace(network->config_table,
                                                g_strdup(key), g_strdup(str));
                }
@@ -1001,18 +1910,14 @@ static void interface_network_added(DBusMessageIter *iter, void *user_data)
        SUPPLICANT_DBG("");
 
        dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL)
+       if (!path)
                return;
 
        if (g_strcmp0(path, "/") == 0)
                return;
 
-       network = g_hash_table_lookup(interface->net_mapping, path);
-       if (network != NULL)
-               return;
-
        network = g_try_new0(GSupplicantNetwork, 1);
-       if (network == NULL)
+       if (!network)
                return;
 
        network->interface = interface;
@@ -1031,24 +1936,13 @@ static void interface_network_added(DBusMessageIter *iter, void *user_data)
 
        supplicant_dbus_property_get_all(path,
                                SUPPLICANT_INTERFACE ".Network",
-                                               network_property, network);
+                                       network_property, network, NULL);
 }
 
 static void interface_network_removed(DBusMessageIter *iter, void *user_data)
 {
-       GSupplicantInterface *interface = user_data;
-       GSupplicantNetwork *network;
-       const char *path = NULL;
-
-       dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL)
-               return;
-
-       network = g_hash_table_lookup(interface->net_mapping, path);
-       if (network == NULL)
-               return;
-
-       g_hash_table_remove(interface->net_mapping, path);
+       SUPPLICANT_DBG("");
+       return;
 }
 
 static char *create_name(unsigned char *ssid, int ssid_len)
@@ -1066,13 +1960,13 @@ static char *create_name(unsigned char *ssid, int ssid_len)
 
        while (remaining_bytes != 0) {
                if (g_utf8_validate(remainder, remaining_bytes,
-                                       &invalid) == TRUE) {
+                                       &invalid)) {
                        break;
                }
 
                valid_bytes = invalid - remainder;
 
-               if (string == NULL)
+               if (!string)
                        string = g_string_sized_new(remaining_bytes);
 
                g_string_append_len(string, remainder, valid_bytes);
@@ -1084,7 +1978,7 @@ static char *create_name(unsigned char *ssid, int ssid_len)
                remainder = invalid + 1;
        }
 
-       if (string == NULL)
+       if (!string)
                return g_strndup((const gchar *)ssid, ssid_len + 1);
 
        g_string_append(string, remainder);
@@ -1099,7 +1993,7 @@ static char *create_group(struct g_supplicant_bss *bss)
        const char *mode, *security;
 
        str = g_string_sized_new((bss->ssid_len * 2) + 24);
-       if (str == NULL)
+       if (!str)
                return NULL;
 
        if (bss->ssid_len > 0 && bss->ssid[0] != '\0') {
@@ -1109,17 +2003,17 @@ static char *create_group(struct g_supplicant_bss *bss)
                g_string_append_printf(str, "hidden");
 
        mode = mode2string(bss->mode);
-       if (mode != NULL)
+       if (mode)
                g_string_append_printf(str, "_%s", mode);
 
        security = security2string(bss->security);
-       if (security != NULL)
+       if (security)
                g_string_append_printf(str, "_%s", security);
 
        return g_string_free(str, FALSE);
 }
 
-static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
+static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
 {
        GSupplicantInterface *interface = bss->interface;
        GSupplicantNetwork *network;
@@ -1128,11 +2022,11 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        group = create_group(bss);
        SUPPLICANT_DBG("New group created: %s", group);
 
-       if (group == NULL)
-               return;
+       if (!group)
+               return -ENOMEM;
 
        network = g_hash_table_lookup(interface->network_table, group);
-       if (network != NULL) {
+       if (network) {
                g_free(group);
                SUPPLICANT_DBG("Network %s already exist", network->name);
 
@@ -1140,13 +2034,13 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        }
 
        network = g_try_new0(GSupplicantNetwork, 1);
-       if (network == NULL) {
+       if (!network) {
                g_free(group);
-               return;
+               return -ENOMEM;
        }
 
        network->interface = interface;
-       if (network->path == NULL)
+       if (!network->path)
                network->path = g_strdup(bss->path);
        network->group = group;
        network->name = create_name(bss->ssid, bss->ssid_len);
@@ -1158,6 +2052,29 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        network->frequency = bss->frequency;
        network->best_bss = bss;
 
+#if defined TIZEN_EXT
+       network->keymgmt = bss->keymgmt;
+
+       if (g_slist_length(bss->vsie_list) > 0) {
+               GSList *list = NULL;
+               unsigned char *vsie = NULL;
+               for (list = bss->vsie_list; list; list = list->next) {
+                       unsigned char *ie = (unsigned char *)list->data;
+                       vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1)
+
+                       if (vsie) {
+                               memcpy(vsie, ie, ie[1]+2);
+                               network->vsie_list = g_slist_append(network->vsie_list, vsie);
+                       } else
+                               SUPPLICANT_DBG("Failed to allocate memory.");
+               }
+       }
+
+       network->isHS20AP = bss->hs20;
+       memcpy(network->country_code, bss->country_code, COUNTRY_CODE_LENGTH);
+       network->phy_mode = bss->phy_mode;
+#endif
+
        SUPPLICANT_DBG("New network %s created", network->name);
 
        network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -1178,7 +2095,12 @@ done:
                network->wps_capabilities |= bss->wps_capabilities;
        }
 
-       if (bss->signal > network->signal) {
+       /*
+        * Do not change best BSS if we are connected. It will be done through
+        * CurrentBSS property in case of misalignment with wpa_s or roaming.
+        */
+       if (network != interface->current_network &&
+                               bss->signal > network->signal) {
                network->signal = bss->signal;
                network->best_bss = bss;
                callback_network_changed(network, "Signal");
@@ -1188,6 +2110,8 @@ done:
        g_hash_table_replace(network->bss_table, bss->path, bss);
 
        g_hash_table_replace(bss_mapping, bss->path, interface);
+
+       return 0;
 }
 
 static void bss_rates(DBusMessageIter *iter, void *user_data)
@@ -1210,10 +2134,10 @@ static void bss_keymgmt(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; keymgmt_map[i].str != NULL; i++)
+       for (i = 0; keymgmt_map[i].str; i++)
                if (strcmp(str, keymgmt_map[i].str) == 0) {
                        SUPPLICANT_DBG("Keymgmt: %s", str);
                        *keymgmt |= keymgmt_map[i].val;
@@ -1228,10 +2152,10 @@ static void bss_group(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; group_map[i].str != NULL; i++)
+       for (i = 0; group_map[i].str; i++)
                if (strcmp(str, group_map[i].str) == 0) {
                        SUPPLICANT_DBG("Group: %s", str);
                        *group |= group_map[i].val;
@@ -1246,10 +2170,10 @@ static void bss_pairwise(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; pairwise_map[i].str != NULL; i++)
+       for (i = 0; pairwise_map[i].str; i++)
                if (strcmp(str, pairwise_map[i].str) == 0) {
                        SUPPLICANT_DBG("Pairwise: %s", str);
                        *pairwise |= pairwise_map[i].val;
@@ -1268,21 +2192,21 @@ static void bss_wpa(const char *key, DBusMessageIter *iter,
        if (g_strcmp0(key, "KeyMgmt") == 0) {
                supplicant_dbus_array_foreach(iter, bss_keymgmt, &value);
 
-               if (bss->rsn_selected == TRUE)
+               if (bss->rsn_selected)
                        bss->rsn_keymgmt = value;
                else
                        bss->wpa_keymgmt = value;
        } else if (g_strcmp0(key, "Group") == 0) {
                supplicant_dbus_array_foreach(iter, bss_group, &value);
 
-               if (bss->rsn_selected == TRUE)
+               if (bss->rsn_selected)
                        bss->rsn_group = value;
                else
                        bss->wpa_group = value;
        } else if (g_strcmp0(key, "Pairwise") == 0) {
                supplicant_dbus_array_foreach(iter, bss_pairwise, &value);
 
-               if (bss->rsn_selected == TRUE)
+               if (bss->rsn_selected)
                        bss->rsn_pairwise = value;
                else
                        bss->wpa_pairwise = value;
@@ -1331,6 +2255,50 @@ static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size,
        return 0;
 }
 
+#if defined TIZEN_EXT
+static void get_bss_phy_mode(unsigned int max_rate,
+               unsigned int max_ext_rate, bool ht, bool vht, void *data)
+{
+       struct g_supplicant_bss *bss = data;
+       unsigned int freq = bss->frequency;
+
+       /* Following conditions are used to determine
+        * IEEE 802.11 Protocol Modes:-
+        *
+        * 1. If “Supported rates” is only till 11 Mbps,
+        *    and frequency is in 2.4GHz band, then protocol is 11B.
+        * 2. If “Supported rates” is till 54Mbps or
+        *    “Extended supported rates” are present,
+        *    and frequency is in 2.4GHz band, then protocol is 11G.
+        * 3. If “Supported rates” is only till 54 Mbps,
+        *    frequency is in 5GHz band , then protocol is 11A.
+        * 4. If “HT capabilities” is supported , then protocol is 11N.
+        * 5. If “HT capabilities” & “VHT” is supported and
+        *    frequency is in 5 GHz band, then protocol is 11AC.
+        * */
+
+       if (freq >= 2412 && freq <= 2484) { /* 2.4 Ghz Band */
+               if (max_rate <= 11 && max_ext_rate <= 0 && !ht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211B;
+               else if ((max_rate <= 54 || max_ext_rate > 0) && !ht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BG;
+               else if ((max_rate >= 54 || max_ext_rate > 0) && ht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BGN;
+               else
+                       bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
+       } else if (freq >= 5180 && freq <= 5825) { /* 5 Ghz Band */
+               if (max_rate <= 54 && !ht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211A;
+               else if ((max_rate >= 54 || max_ext_rate > 0) && ht && !vht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211AN;
+               else if ((max_rate >= 54 || max_ext_rate > 0) && ht && vht)
+                       bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211ANAC;
+               else
+                       bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
+       }
+}
+#endif
+
 static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 {
        struct g_supplicant_bss *bss = user_data;
@@ -1339,6 +2307,15 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
        DBusMessageIter array;
        unsigned int value;
        int ie_len;
+#if defined TIZEN_EXT
+       int r_len, j;
+       unsigned char *rates = NULL;
+       unsigned char *ext_rates = NULL;
+       unsigned int max_rate = 0;
+       unsigned int max_ext_rate = 0;
+       bool ht = false;
+       bool vht = false;
+#endif
 
 #define WMM_WPA1_WPS_INFO 221
 #define WPS_INFO_MIN_LEN  6
@@ -1350,19 +2327,86 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 #define WPS_PBC           0x04
 #define WPS_PIN           0x00
 #define WPS_CONFIGURED    0x02
+#if defined TIZEN_EXT
+#define VENDOR_SPECIFIC_INFO 0xDD
+#define WLAN_EID_COUNTRY 7
+#endif
 
        dbus_message_iter_recurse(iter, &array);
        dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
 
-       if (ie == NULL || ie_len < 2)
+       if (!ie || ie_len < 2)
                return;
 
        bss->wps_capabilities = 0;
        bss->keymgmt = 0;
+       memset(bss->country_code, 0, COUNTRY_CODE_LENGTH);
 
        for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
                                                        ie += ie[1] + 2) {
+#if defined TIZEN_EXT
+               unsigned char *vsie;
+               int vsie_len = 0;
+               if(ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) {
+                       SUPPLICANT_DBG("IE: match vendor specific data");
+
+                       vsie_len = ie[1]+2;     // tag number size(1), tag length size(1)
+                       vsie = (unsigned char *)g_try_malloc0(vsie_len);
+
+                       if (vsie) {
+                               memcpy(vsie, ie, vsie_len);
+                               bss->vsie_list = g_slist_append(bss->vsie_list, vsie);
+                       } else
+                               SUPPLICANT_DBG("Failed to allocate memory");
+                       continue;
+               }
+
+               if(ie[0] == WLAN_EID_COUNTRY && ie[1] >= 2) {
+                       /* Add country code only if it is a valid alphabet */
+                       if (ie[2] >= 65 && ie[2] <= 90 && ie[3] >= 65 && ie[3] <= 90) {
+                               memcpy(bss->country_code, ie+2, COUNTRY_CODE_LENGTH);
+                               continue;
+                       }
+               }
+
+               if (ie[0] == WLAN_EID_HT_CAP && ie[1]) {
+                       ht = true;
+                       continue;
+               }
+
+               if (ie[0] == WLAN_EID_VHT_CAP && ie[1]) {
+                       vht = true;
+                       continue;
+               }
+
+               if (ie[0] == WLAN_EID_SUPP_RATES && ie[1]) {
+                       r_len = ie[1];
+                       rates = g_malloc0(r_len);
+                       if (!rates)
+                               continue;
+
+                       for (j = 0; ie && j < r_len; j++) {
+                               rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
+                               if (max_rate < rates[j])
+                                       max_rate = rates[j];
+                       }
+                       continue;
+               }
+
+               if (ie[0] == WLAN_EID_EXT_SUPP_RATES && ie[1] > 0) {
+                       r_len = ie[1];
+                       ext_rates = g_malloc0(r_len);
+                       if (!ext_rates)
+                               continue;
 
+                       for (j = 0; ie && j < r_len; j++) {
+                               ext_rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
+                               if (max_ext_rate < ext_rates[j])
+                                       max_ext_rate = ext_rates[j];
+                       }
+                       continue;
+               }
+#endif
                if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
                        memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
                        continue;
@@ -1397,6 +2441,13 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 
                SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
        }
+#ifdef TIZEN_EXT
+       get_bss_phy_mode(max_rate, max_ext_rate, ht, vht, user_data);
+       if (rates)
+               g_free(rates);
+       if (ext_rates)
+               g_free(ext_rates);
+#endif
 }
 
 static void bss_compute_security(struct g_supplicant_bss *bss)
@@ -1408,24 +2459,61 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
 
        bss->ieee8021x = FALSE;
        bss->psk = FALSE;
+#if defined TIZEN_EXT
+       bss->ft_ieee8021x = FALSE;
+       bss->ft_psk = FALSE;
+#endif
 
+#if defined TIZEN_EXT
+       if (bss->keymgmt &
+                       (G_SUPPLICANT_KEYMGMT_WPA_EAP |
+                                       G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
+               bss->ieee8021x = TRUE;
+       else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
+               bss->ft_ieee8021x = TRUE;
+#else
        if (bss->keymgmt &
                        (G_SUPPLICANT_KEYMGMT_WPA_EAP |
                                G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
                                G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
                bss->ieee8021x = TRUE;
+#endif
 
+#if defined TIZEN_EXT
+       if (bss->keymgmt &
+                       (G_SUPPLICANT_KEYMGMT_WPA_PSK |
+                                       G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
+               bss->psk = TRUE;
+       else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
+               bss->ft_psk = TRUE;
+#else
        if (bss->keymgmt &
                        (G_SUPPLICANT_KEYMGMT_WPA_PSK |
                                G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
                                G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
                bss->psk = TRUE;
+#endif
 
-       if (bss->ieee8021x == TRUE)
+#if defined TIZEN_EXT
+       if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
+               bss->sae = TRUE;
+#endif
+
+       if (bss->ieee8021x)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
-       else if (bss->psk == TRUE)
+       else if (bss->psk)
                bss->security = G_SUPPLICANT_SECURITY_PSK;
-       else if (bss->privacy == TRUE)
+#if defined TIZEN_EXT
+       else if (bss->ft_psk)
+               bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
+       else if (bss->ft_ieee8021x == TRUE)
+               bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
+#endif
+#if defined TIZEN_EXT
+       else if (bss->sae)
+               bss->security = G_SUPPLICANT_SECURITY_SAE;
+#endif
+       else if (bss->privacy)
                bss->security = G_SUPPLICANT_SECURITY_WEP;
        else
                bss->security = G_SUPPLICANT_SECURITY_NONE;
@@ -1437,12 +2525,12 @@ static void bss_property(const char *key, DBusMessageIter *iter,
 {
        struct g_supplicant_bss *bss = user_data;
 
-       if (bss->interface == NULL)
+       if (!bss->interface)
                return;
 
        SUPPLICANT_DBG("key %s", key);
 
-       if (key == NULL)
+       if (!key)
                return;
 
        if (g_strcmp0(key, "BSSID") == 0) {
@@ -1498,6 +2586,9 @@ static void bss_property(const char *key, DBusMessageIter *iter,
                dbus_message_iter_get_basic(iter, &signal);
 
                bss->signal = signal;
+               if (!bss->signal)
+                       bss->signal = BSS_UNKNOWN_STRENGTH;
+
        } else if (g_strcmp0(key, "Level") == 0) {
                dbus_int32_t level = 0;
 
@@ -1523,6 +2614,12 @@ static void bss_property(const char *key, DBusMessageIter *iter,
                bss->rsn_selected = FALSE;
 
                supplicant_dbus_property_foreach(iter, bss_wpa, bss);
+#if defined TIZEN_EXT
+       } else if (g_strcmp0(key, "HS20") == 0) {
+               dbus_bool_t hs20 = FALSE;
+               dbus_message_iter_get_basic(iter, &hs20);
+               bss->hs20 = hs20;
+#endif
        } else if (g_strcmp0(key, "IEs") == 0)
                bss_process_ies(iter, bss);
        else
@@ -1541,7 +2638,7 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
        SUPPLICANT_DBG("");
 
        dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL)
+       if (!path)
                return NULL;
 
        if (g_strcmp0(path, "/") == 0)
@@ -1550,18 +2647,19 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
        SUPPLICANT_DBG("%s", path);
 
        network = g_hash_table_lookup(interface->bss_mapping, path);
-       if (network != NULL) {
+       if (network) {
                bss = g_hash_table_lookup(network->bss_table, path);
-               if (bss != NULL)
+               if (bss)
                        return NULL;
        }
 
        bss = g_try_new0(struct g_supplicant_bss, 1);
-       if (bss == NULL)
+       if (!bss)
                return NULL;
 
        bss->interface = interface;
        bss->path = g_strdup(path);
+       bss->signal = BSS_UNKNOWN_STRENGTH;
 
        return bss;
 }
@@ -1574,7 +2672,7 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter,
        SUPPLICANT_DBG("");
 
        bss = interface_bss_added(iter, user_data);
-       if (bss == NULL)
+       if (!bss)
                return;
 
        dbus_message_iter_next(iter);
@@ -1585,7 +2683,8 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter,
        supplicant_dbus_property_foreach(iter, bss_property, bss);
 
        bss_compute_security(bss);
-       add_or_replace_bss_to_network(bss);
+       if (add_or_replace_bss_to_network(bss) < 0)
+               SUPPLICANT_DBG("add_or_replace_bss_to_network failed");
 }
 
 static void interface_bss_added_without_keys(DBusMessageIter *iter,
@@ -1596,15 +2695,16 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter,
        SUPPLICANT_DBG("");
 
        bss = interface_bss_added(iter, user_data);
-       if (bss == NULL)
+       if (!bss)
                return;
 
        supplicant_dbus_property_get_all(bss->path,
                                        SUPPLICANT_INTERFACE ".BSS",
-                                                       bss_property, bss);
+                                       bss_property, bss, NULL);
 
        bss_compute_security(bss);
-       add_or_replace_bss_to_network(bss);
+       if (add_or_replace_bss_to_network(bss) < 0)
+                       SUPPLICANT_DBG("add_or_replace_bss_to_network failed");
 }
 
 static void update_signal(gpointer key, gpointer value,
@@ -1621,7 +2721,7 @@ static void update_signal(gpointer key, gpointer value,
 
 static void update_network_signal(GSupplicantNetwork *network)
 {
-       if (g_hash_table_size(network->bss_table) <= 1)
+       if (g_hash_table_size(network->bss_table) <= 1 && network->best_bss)
                return;
 
        g_hash_table_foreach(network->bss_table,
@@ -1630,20 +2730,98 @@ static void update_network_signal(GSupplicantNetwork *network)
        SUPPLICANT_DBG("New network signal %d", network->signal);
 }
 
+static void interface_current_bss(GSupplicantInterface *interface,
+                                               DBusMessageIter *iter)
+{
+       GSupplicantNetwork *network;
+       struct g_supplicant_bss *bss;
+       const char *path;
+
+       dbus_message_iter_get_basic(iter, &path);
+       if (g_strcmp0(path, "/") == 0) {
+               interface->current_network = NULL;
+               return;
+       }
+
+       interface_bss_added_without_keys(iter, interface);
+
+       network = g_hash_table_lookup(interface->bss_mapping, path);
+       if (!network)
+               return;
+
+       bss = g_hash_table_lookup(network->bss_table, path);
+       if (!bss)
+               return;
+
+       interface->current_network = network;
+
+       if (bss != network->best_bss) {
+               /*
+                * This is the case where either wpa_s got associated
+                * to a BSS different than the one ConnMan considers
+                * the best, or we are roaming.
+                */
+               SUPPLICANT_DBG("Update best BSS for %s", network->name);
+
+               network->best_bss = bss;
+
+               if (network->signal != bss->signal) {
+                       SUPPLICANT_DBG("New network signal %d dBm",
+                                               bss->signal);
+
+                       network->signal = bss->signal;
+                       callback_network_changed(network, "Signal");
+               }
+       }
+
+       /*
+        * wpa_s could notify about CurrentBSS in any state once
+        * it got associated. It is not sure such notification will
+        * arrive together with transition to ASSOCIATED state.
+        * In fact, for networks with security WEP or OPEN, it
+        * always arrives together with transition to COMPLETED.
+        */
+       switch (interface->state) {
+       case G_SUPPLICANT_STATE_UNKNOWN:
+       case G_SUPPLICANT_STATE_DISABLED:
+       case G_SUPPLICANT_STATE_DISCONNECTED:
+       case G_SUPPLICANT_STATE_INACTIVE:
+       case G_SUPPLICANT_STATE_SCANNING:
+       case G_SUPPLICANT_STATE_AUTHENTICATING:
+       case G_SUPPLICANT_STATE_ASSOCIATING:
+               return;
+       case G_SUPPLICANT_STATE_ASSOCIATED:
+       case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
+       case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
+       case G_SUPPLICANT_STATE_COMPLETED:
+               callback_network_associated(network);
+               break;
+       }
+}
+
 static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
 {
        GSupplicantInterface *interface = user_data;
        GSupplicantNetwork *network;
+       struct g_supplicant_bss *bss = NULL;
        const char *path = NULL;
+       bool is_current_network_bss = false;
 
        dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL)
+       if (!path)
                return;
 
        network = g_hash_table_lookup(interface->bss_mapping, path);
-       if (network == NULL)
+       if (!network)
                return;
 
+       bss = g_hash_table_lookup(network->bss_table, path);
+       if (network->best_bss == bss) {
+               network->best_bss = NULL;
+               network->signal = BSS_UNKNOWN_STRENGTH;
+               is_current_network_bss = true;
+       }
+
        g_hash_table_remove(bss_mapping, path);
 
        g_hash_table_remove(interface->bss_mapping, path);
@@ -1651,8 +2829,51 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
 
        update_network_signal(network);
 
-       if (g_hash_table_size(network->bss_table) == 0)
+       if (g_hash_table_size(network->bss_table) == 0) {
                g_hash_table_remove(interface->network_table, network->group);
+       } else {
+               if (is_current_network_bss && network->best_bss)
+#if defined TIZEN_EXT
+                       callback_network_changed(network, "CheckMultiBssidConnect");
+#else
+                       callback_network_changed(network, "");
+#endif
+       }
+}
+
+static void set_config_methods(DBusMessageIter *iter, void *user_data)
+{
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, user_data);
+}
+
+static void wps_property(const char *key, DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       GSupplicantInterface *interface = user_data;
+
+       if (!interface)
+               return;
+
+       SUPPLICANT_DBG("key: %s", key);
+
+       if (g_strcmp0(key, "ConfigMethods") == 0) {
+               const char *config_methods = "push_button", *str = NULL;
+
+               dbus_message_iter_get_basic(iter, &str);
+               if (str && strlen(str) > 0) {
+                       /* It was already set at wpa_s level, don't modify it. */
+                       SUPPLICANT_DBG("%s", str);
+                       return;
+               }
+
+               supplicant_dbus_property_set(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface.WPS",
+                       "ConfigMethods", DBUS_TYPE_STRING_AS_STRING,
+                       set_config_methods, NULL, &config_methods, NULL);
+
+               SUPPLICANT_DBG("No value. Set %s", config_methods);
+       }
+
 }
 
 static void interface_property(const char *key, DBusMessageIter *iter,
@@ -1660,12 +2881,12 @@ static void interface_property(const char *key, DBusMessageIter *iter,
 {
        GSupplicantInterface *interface = user_data;
 
-       if (interface == NULL)
+       if (!interface)
                return;
 
        SUPPLICANT_DBG("%s", key);
 
-       if (key == NULL) {
+       if (!key) {
                debug_strvalmap("KeyMgmt capability", keymgmt_map,
                                                interface->keymgmt_capa);
                debug_strvalmap("AuthAlg capability", authalg_capa_map,
@@ -1681,24 +2902,49 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                debug_strvalmap("Mode capability", mode_capa_map,
                                                interface->mode_capa);
 
-               interface->ready = TRUE;
-               callback_interface_added(interface);
+               supplicant_dbus_property_get_all(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface.WPS",
+                               wps_property, interface, interface);
+
+               if (interface->ready)
+                       callback_interface_added(interface);
+
                return;
        }
 
        if (g_strcmp0(key, "Capabilities") == 0) {
                supplicant_dbus_property_foreach(iter, interface_capability,
                                                                interface);
+#if !defined TIZEN_EXT
+               if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_P2P)
+                       interface->p2p_support = true;
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+               if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_MESH)
+                       interface->mesh_support = true;
+#endif
        } else if (g_strcmp0(key, "State") == 0) {
                const char *str = NULL;
 
                dbus_message_iter_get_basic(iter, &str);
-               if (str != NULL)
+               if (str)
                        if (string2state(str) != interface->state) {
                                interface->state = string2state(str);
                                callback_interface_state(interface);
                        }
 
+               if (interface->ap_create_in_progress) {
+                       if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED)
+                               callback_ap_create_fail(interface);
+
+                       interface->ap_create_in_progress = false;
+               }
+
+               if (interface->state == G_SUPPLICANT_STATE_DISABLED)
+                       interface->ready = FALSE;
+               else
+                       interface->ready = TRUE;
+
                SUPPLICANT_DBG("state %s (%d)", str, interface->state);
        } else if (g_strcmp0(key, "Scanning") == 0) {
                dbus_bool_t scanning = FALSE;
@@ -1706,8 +2952,8 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                dbus_message_iter_get_basic(iter, &scanning);
                interface->scanning = scanning;
 
-               if (interface->ready == TRUE) {
-                       if (interface->scanning == TRUE)
+               if (interface->ready) {
+                       if (interface->scanning)
                                callback_scan_started(interface);
                        else
                                callback_scan_finished(interface);
@@ -1721,7 +2967,7 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                const char *str = NULL;
 
                dbus_message_iter_get_basic(iter, &str);
-               if (str != NULL) {
+               if (str) {
                        g_free(interface->ifname);
                        interface->ifname = g_strdup(str);
                }
@@ -1729,7 +2975,7 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                const char *str = NULL;
 
                dbus_message_iter_get_basic(iter, &str);
-               if (str != NULL) {
+               if (str) {
                        g_free(interface->driver);
                        interface->driver = g_strdup(str);
                }
@@ -1737,25 +2983,51 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                const char *str = NULL;
 
                dbus_message_iter_get_basic(iter, &str);
-               if (str != NULL) {
+               if (str) {
                        g_free(interface->bridge);
                        interface->bridge = g_strdup(str);
                }
+       } else if (g_strcmp0(key, "ConfigFile") == 0) {
+               const char *str = NULL;
+
+               dbus_message_iter_get_basic(iter, &str);
+               if (str && strlen(str) > 0 && interface->ifname) {
+                       SUPPLICANT_DBG("New {%s, %s}", interface->ifname, str);
+                       g_hash_table_replace(config_file_table,
+                               g_strdup(interface->ifname), g_strdup(str));
+               }
        } else if (g_strcmp0(key, "CurrentBSS") == 0) {
-               interface_bss_added_without_keys(iter, interface);
+               interface_current_bss(interface, iter);
        } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
+#if defined TIZEN_EXT
+               if (interface->state != G_SUPPLICANT_STATE_COMPLETED)
+#endif
                interface_network_added(iter, interface);
        } else if (g_strcmp0(key, "BSSs") == 0) {
-               supplicant_dbus_array_foreach(iter, interface_bss_added_without_keys,
-                                                               interface);
+               supplicant_dbus_array_foreach(iter,
+                                       interface_bss_added_without_keys,
+                                       interface);
        } else if (g_strcmp0(key, "Blobs") == 0) {
                /* Nothing */
        } else if (g_strcmp0(key, "Networks") == 0) {
                supplicant_dbus_array_foreach(iter, interface_network_added,
                                                                interface);
-       } else
+       } else if (g_strcmp0(key, "DisconnectReason") == 0) {
+               int reason_code;
+               if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
+                       dbus_message_iter_get_basic(iter, &reason_code);
+                       callback_disconnect_reason_code(interface, reason_code);
+               }
+       } else if (g_strcmp0(key, "AssocStatusCode") == 0) {
+               int status_code;
+               if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
+                       dbus_message_iter_get_basic(iter, &status_code);
+                       callback_assoc_status_code(interface, status_code);
+               }
+       } else {
                SUPPLICANT_DBG("key %s type %c",
                                key, dbus_message_iter_get_arg_type(iter));
+       }
 }
 
 static void scan_network_update(DBusMessageIter *iter, void *user_data)
@@ -1764,12 +3036,12 @@ static void scan_network_update(DBusMessageIter *iter, void *user_data)
        GSupplicantNetwork *network;
        char *path;
 
-       if (iter == NULL)
+       if (!iter)
                return;
 
        dbus_message_iter_get_basic(iter, &path);
 
-       if (path == NULL)
+       if (!path)
                return;
 
        if (g_strcmp0(path, "/") == 0)
@@ -1777,7 +3049,7 @@ static void scan_network_update(DBusMessageIter *iter, void *user_data)
 
        /* Update the network details based on scan BSS data */
        network = g_hash_table_lookup(interface->bss_mapping, path);
-       if (network != NULL)
+       if (network)
                callback_network_added(network);
 }
 
@@ -1786,15 +3058,30 @@ static void scan_bss_data(const char *key, DBusMessageIter *iter,
 {
        GSupplicantInterface *interface = user_data;
 
+/*Fixed : stucking in scanning state when scan failed*/
+#if defined TIZEN_EXT
+               GSupplicantInterfaceCallback scan_callback;
+#endif
+
        if (iter)
                supplicant_dbus_array_foreach(iter, scan_network_update,
                                                interface);
 
-       if (interface->scan_callback != NULL)
+#if defined TIZEN_EXT
+               scan_callback = interface->scan_callback;
+#endif
+
+       if (interface->scan_callback)
                interface->scan_callback(0, interface, interface->scan_data);
 
+#if defined TIZEN_EXT
+               if (interface->scan_callback == scan_callback) {
+#endif
        interface->scan_callback = NULL;
        interface->scan_data = NULL;
+#if defined TIZEN_EXT
+       }
+#endif
 }
 
 static GSupplicantInterface *interface_alloc(const char *path)
@@ -1802,16 +3089,17 @@ static GSupplicantInterface *interface_alloc(const char *path)
        GSupplicantInterface *interface;
 
        interface = g_try_new0(GSupplicantInterface, 1);
-       if (interface == NULL)
+       if (!interface)
                return NULL;
 
        interface->path = g_strdup(path);
 
        interface->network_table = g_hash_table_new_full(g_str_hash,
                                        g_str_equal, NULL, remove_network);
-
-       interface->net_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
-                                                               NULL, NULL);
+       interface->peer_table = g_hash_table_new_full(g_str_hash,
+                                       g_str_equal, NULL, remove_peer);
+       interface->group_table = g_hash_table_new_full(g_str_hash,
+                                       g_str_equal, NULL, remove_group);
        interface->bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                                NULL, NULL);
 
@@ -1824,45 +3112,53 @@ static void interface_added(DBusMessageIter *iter, void *user_data)
 {
        GSupplicantInterface *interface;
        const char *path = NULL;
+       bool properties_appended = GPOINTER_TO_UINT(user_data);
 
        SUPPLICANT_DBG("");
 
        dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL)
+       if (!path)
                return;
 
        if (g_strcmp0(path, "/") == 0)
                return;
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface != NULL)
+       if (interface)
                return;
 
        interface = interface_alloc(path);
-       if (interface == NULL)
+       if (!interface)
+               return;
+
+       if (!properties_appended) {
+               supplicant_dbus_property_get_all(path,
+                                               SUPPLICANT_INTERFACE ".Interface",
+                                               interface_property, interface,
+                                               interface);
                return;
+       }
 
        dbus_message_iter_next(iter);
        if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
                supplicant_dbus_property_foreach(iter, interface_property,
                                                                interface);
                interface_property(NULL, NULL, interface);
-               return;
        }
-
-       supplicant_dbus_property_get_all(path,
-                                       SUPPLICANT_INTERFACE ".Interface",
-                                               interface_property, interface);
 }
 
 static void interface_removed(DBusMessageIter *iter, void *user_data)
 {
        const char *path = NULL;
+       GSupplicantInterface *interface = user_data;
 
        dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL)
+       if (!path)
                return;
 
+       interface = g_hash_table_lookup(interface_table, path);
+       g_supplicant_interface_cancel(interface);
+
        g_hash_table_remove(interface_table, path);
 }
 
@@ -1872,10 +3168,10 @@ static void eap_method(DBusMessageIter *iter, void *user_data)
        int i;
 
        dbus_message_iter_get_basic(iter, &str);
-       if (str == NULL)
+       if (!str)
                return;
 
-       for (i = 0; eap_method_map[i].str != NULL; i++)
+       for (i = 0; eap_method_map[i].str; i++)
                if (strcmp(str, eap_method_map[i].str) == 0) {
                        eap_methods |= eap_method_map[i].val;
                        break;
@@ -1885,7 +3181,7 @@ static void eap_method(DBusMessageIter *iter, void *user_data)
 static void service_property(const char *key, DBusMessageIter *iter,
                                                        void *user_data)
 {
-       if (key == NULL) {
+       if (!key) {
                callback_system_ready();
                return;
        }
@@ -1895,7 +3191,7 @@ static void service_property(const char *key, DBusMessageIter *iter,
                int i;
 
                dbus_message_iter_get_basic(iter, &str);
-               for (i = 0; debug_strings[i] != NULL; i++)
+               for (i = 0; debug_strings[i]; i++)
                        if (g_strcmp0(debug_strings[i], str) == 0) {
                                debug_level = i;
                                break;
@@ -1932,7 +3228,7 @@ static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
                return;
 
        dbus_message_iter_get_basic(iter, &name);
-       if (name == NULL)
+       if (!name)
                return;
 
        if (g_strcmp0(name, SUPPLICANT_SERVICE) != 0)
@@ -1943,12 +3239,15 @@ static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
        dbus_message_iter_next(iter);
        dbus_message_iter_get_basic(iter, &new);
 
-       if (old == NULL || new == NULL)
+       if (!old || !new)
                return;
 
        if (strlen(old) > 0 && strlen(new) == 0) {
                system_available = FALSE;
                g_hash_table_remove_all(bss_mapping);
+               g_hash_table_remove_all(peer_mapping);
+               g_hash_table_remove_all(group_mapping);
+               g_hash_table_remove_all(config_file_table);
                g_hash_table_remove_all(interface_table);
                callback_system_killed();
        }
@@ -1956,8 +3255,8 @@ static void signal_name_owner_changed(const char *path, DBusMessageIter *iter)
        if (strlen(new) > 0 && strlen(old) == 0) {
                system_available = TRUE;
                supplicant_dbus_property_get_all(SUPPLICANT_PATH,
-                                                       SUPPLICANT_INTERFACE,
-                                                       service_property, NULL);
+                                               SUPPLICANT_INTERFACE,
+                                               service_property, NULL, NULL);
        }
 }
 
@@ -1976,7 +3275,7 @@ static void signal_interface_added(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
 
        if (g_strcmp0(path, SUPPLICANT_PATH) == 0)
-               interface_added(iter, NULL);
+               interface_added(iter, GUINT_TO_POINTER(true));
 }
 
 static void signal_interface_removed(const char *path, DBusMessageIter *iter)
@@ -1994,7 +3293,7 @@ static void signal_interface_changed(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        supplicant_dbus_property_foreach(iter, interface_property, interface);
@@ -2008,17 +3307,22 @@ static void signal_scan_done(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        dbus_message_iter_get_basic(iter, &success);
 
+       if (interface->scanning) {
+               callback_scan_finished(interface);
+               interface->scanning = FALSE;
+       }
+
        /*
         * If scan is unsuccessful return -EIO else get the scanned BSSs
         * and update the network details accordingly
         */
-       if (success == FALSE) {
-               if (interface->scan_callback != NULL)
+       if (!success) {
+               if (interface->scan_callback)
                        interface->scan_callback(-EIO, interface,
                                                interface->scan_data);
 
@@ -2029,7 +3333,7 @@ static void signal_scan_done(const char *path, DBusMessageIter *iter)
        }
 
        supplicant_dbus_property_get(path, SUPPLICANT_INTERFACE ".Interface",
-                                       "BSSs", scan_bss_data, interface);
+                               "BSSs", scan_bss_data, interface, interface);
 }
 
 static void signal_bss_added(const char *path, DBusMessageIter *iter)
@@ -2039,7 +3343,7 @@ static void signal_bss_added(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        interface_bss_added_with_keys(iter, interface);
@@ -2052,7 +3356,7 @@ static void signal_bss_removed(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        interface_bss_removed(iter, interface);
@@ -2065,7 +3369,7 @@ static void signal_network_added(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        interface_network_added(iter, interface);
@@ -2078,11 +3382,18 @@ static void signal_network_removed(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        interface_network_removed(iter, interface);
 }
+#if defined TIZEN_EXT
+void *copy_vsie_list(gconstpointer src, gpointer data)
+{
+       return g_strdup(src);
+}
+#endif
+
 
 static void signal_bss_changed(const char *path, DBusMessageIter *iter)
 {
@@ -2094,19 +3405,22 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(bss_mapping, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        network = g_hash_table_lookup(interface->bss_mapping, path);
-       if (network == NULL)
+       if (!network)
                return;
 
        bss = g_hash_table_lookup(network->bss_table, path);
-       if (bss == NULL)
+       if (!bss)
                return;
 
        supplicant_dbus_property_foreach(iter, bss_property, bss);
-
+#if defined TIZEN_EXT
+       network->frequency = bss->frequency;
+       network->phy_mode = bss->phy_mode;
+#endif
        old_security = network->security;
        bss_compute_security(bss);
 
@@ -2127,21 +3441,50 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
                 * plugin about it. */
 
                new_bss = g_try_new0(struct g_supplicant_bss, 1);
-               if (new_bss == NULL)
+               if (!new_bss)
                        return;
 
                memcpy(new_bss, bss, sizeof(struct g_supplicant_bss));
                new_bss->path = g_strdup(bss->path);
+#if defined TIZEN_EXT
+               new_bss->vsie_list = g_slist_copy_deep(bss->vsie_list, copy_vsie_list, NULL);
+#endif
 
                g_hash_table_remove(interface->network_table, network->group);
 
-               add_or_replace_bss_to_network(new_bss);
+               if (add_or_replace_bss_to_network(new_bss) < 0) {
+                       /* Remove entries in hash tables to handle the
+                        * failure in add_or_replace_bss_to_network
+                        */
+                       g_hash_table_remove(bss_mapping, path);
+                       g_hash_table_remove(interface->bss_mapping, path);
+                       g_hash_table_remove(network->bss_table, path);
+               }
 
                return;
        }
 
+#if defined TIZEN_EXT
+       if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
+               network->wps = TRUE;
+               network->wps_capabilities |= bss->wps_capabilities;
+       } else
+               network->wps = FALSE;
+#endif
+
+       /* Consider only property changes of the connected BSS */
+       if (network == interface->current_network && bss != network->best_bss)
+               return;
+
        if (bss->signal == network->signal)
+#ifndef TIZEN_EXT
+               return;
+#else
+       {
+               callback_network_changed(network, "");
                return;
+       }
+#endif
 
        /*
         * If the new signal is lower than the SSID signal, we need
@@ -2149,7 +3492,14 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
         */
        if (bss->signal < network->signal) {
                if (bss != network->best_bss)
+#ifndef TIZEN_EXT
                        return;
+#else
+               {
+                       callback_network_changed(network, "");
+                       return;
+               }
+#endif
                network->signal = bss->signal;
                update_network_signal(network);
        } else {
@@ -2157,7 +3507,8 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
                network->best_bss = bss;
        }
 
-       SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid, network->signal);
+       SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid,
+                       network->signal);
 
        callback_network_changed(network, "Signal");
 }
@@ -2167,27 +3518,28 @@ static void wps_credentials(const char *key, DBusMessageIter *iter,
 {
        GSupplicantInterface *interface = user_data;
 
-       if (key == NULL)
+       if (!key)
                return;
 
        SUPPLICANT_DBG("key %s", key);
 
        if (g_strcmp0(key, "Key") == 0) {
                DBusMessageIter array;
-               unsigned char *key;
+               unsigned char *key_val;
                int key_len;
 
                dbus_message_iter_recurse(iter, &array);
-               dbus_message_iter_get_fixed_array(&array, &key, &key_len);
+               dbus_message_iter_get_fixed_array(&array, &key_val, &key_len);
 
                g_free(interface->wps_cred.key);
                interface->wps_cred.key = g_try_malloc0(
-                                               sizeof(char) * key_len+1);
+                                               sizeof(char) * key_len + 1);
 
-               if (interface->wps_cred.key == NULL)
+               if (!interface->wps_cred.key)
                        return;
 
-               memcpy(interface->wps_cred.key, key, sizeof(char) * key_len);
+               memcpy(interface->wps_cred.key, key_val,
+                                               sizeof(char) * key_len);
 
                SUPPLICANT_DBG("WPS key present");
        } else if (g_strcmp0(key, "SSID") == 0) {
@@ -2215,7 +3567,7 @@ static void signal_wps_credentials(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        supplicant_dbus_property_foreach(iter, wps_credentials, interface);
@@ -2226,7 +3578,7 @@ static void wps_event_args(const char *key, DBusMessageIter *iter,
 {
        GSupplicantInterface *interface = user_data;
 
-       if (key == NULL || interface == NULL)
+       if (!key || !interface)
                return;
 
        SUPPLICANT_DBG("Arg Key %s", key);
@@ -2240,7 +3592,7 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter)
        SUPPLICANT_DBG("");
 
        interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
+       if (!interface)
                return;
 
        dbus_message_iter_get_basic(iter, &name);
@@ -2262,1393 +3614,3687 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter)
        supplicant_dbus_property_foreach(iter, wps_event_args, interface);
 }
 
-static struct {
-       const char *interface;
-       const char *member;
-       void (*function) (const char *path, DBusMessageIter *iter);
-} signal_map[] = {
-       { DBUS_INTERFACE_DBUS,  "NameOwnerChanged",  signal_name_owner_changed },
+#if defined TIZEN_EXT
+static void signal_power_off(const char *path, DBusMessageIter *iter)
+{
+       int poweroff_state = 0;
 
-       { SUPPLICANT_INTERFACE, "PropertiesChanged", signal_properties_changed },
-       { SUPPLICANT_INTERFACE, "InterfaceAdded",    signal_interface_added    },
-       { SUPPLICANT_INTERFACE, "InterfaceCreated",  signal_interface_added    },
-       { SUPPLICANT_INTERFACE, "InterfaceRemoved",  signal_interface_removed  },
+       dbus_message_iter_get_basic(iter, &poweroff_state);
 
-       { SUPPLICANT_INTERFACE ".Interface", "PropertiesChanged", signal_interface_changed },
-       { SUPPLICANT_INTERFACE ".Interface", "ScanDone",          signal_scan_done         },
-       { SUPPLICANT_INTERFACE ".Interface", "BSSAdded",          signal_bss_added         },
-       { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved",        signal_bss_removed       },
-       { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded",      signal_network_added     },
-       { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved",    signal_network_removed   },
+       SUPPLICANT_DBG("poweroff_state(%d)", poweroff_state);
 
-       { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed   },
+       /* POWER_OFF_DIRECT 2 && POWER_OFF_RESTART 3 */
+       if (poweroff_state != 2 && poweroff_state != 3)
+               return;
 
-       { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
-       { SUPPLICANT_INTERFACE ".Interface.WPS", "Event",       signal_wps_event       },
+       if (callbacks_pointer == NULL)
+               return;
 
-       { }
-};
+       if (callbacks_pointer->system_power_off == NULL)
+               return;
 
-static DBusHandlerResult g_supplicant_filter(DBusConnection *conn,
-                                       DBusMessage *message, void *data)
+       callbacks_pointer->system_power_off();
+}
+#endif
+
+static void signal_station_connected(const char *path, DBusMessageIter *iter)
 {
-       DBusMessageIter iter;
-       const char *path;
-       int i;
+       GSupplicantInterface *interface;
+       const char *sta_mac = NULL;
 
-       path = dbus_message_get_path(message);
-       if (path == NULL)
-               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
 
-       if (dbus_message_iter_init(message, &iter) == FALSE)
-               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       if (callbacks_pointer->add_station == NULL)
+               return;
 
-       for (i = 0; signal_map[i].interface != NULL; i++) {
-               if (dbus_message_has_interface(message,
-                                       signal_map[i].interface) == FALSE)
-                       continue;
+       if (g_strcmp0(path, "/") == 0)
+               return;
 
-               if (dbus_message_has_member(message,
-                                       signal_map[i].member) == FALSE)
-                       continue;
+       interface = g_hash_table_lookup(interface_table, path);
+       if (interface == NULL)
+               return;
 
-               signal_map[i].function(path, &iter);
-               break;
-       }
+       dbus_message_iter_get_basic(iter, &sta_mac);
+       if (sta_mac == NULL)
+               return;
 
-       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       SUPPLICANT_DBG("New station %s connected", sta_mac);
+       callbacks_pointer->add_station(sta_mac);
 }
 
-struct supplicant_regdom {
-       GSupplicantCountryCallback callback;
-       const char *alpha2;
-       const void *user_data;
-};
-
-static void country_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+static void signal_station_disconnected(const char *path, DBusMessageIter *iter)
 {
-       struct supplicant_regdom *regdom = user_data;
-       int result = 0;
+       GSupplicantInterface *interface;
+       const char *sta_mac = NULL;
 
-       SUPPLICANT_DBG("Country setting result");
+       SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
 
-       if (user_data == NULL)
+       if (callbacks_pointer->remove_station == NULL)
                return;
 
-       if (error != NULL) {
-               SUPPLICANT_DBG("Country setting failure %s", error);
-               result = -EINVAL;
-       }
+       if (g_strcmp0(path, "/") == 0)
+               return;
 
-       if (regdom->callback)
-               regdom->callback(result, regdom->alpha2,
-                                       (void *) regdom->user_data);
+       interface = g_hash_table_lookup(interface_table, path);
+       if (interface == NULL)
+               return;
 
-       g_free(regdom);
+       dbus_message_iter_get_basic(iter, &sta_mac);
+       if (sta_mac == NULL)
+               return;
+
+       SUPPLICANT_DBG("Station %s disconnected", sta_mac);
+       callbacks_pointer->remove_station(sta_mac);
 }
 
-static void country_params(DBusMessageIter *iter, void *user_data)
+static void create_peer_identifier(GSupplicantPeer *peer)
 {
-       struct supplicant_regdom *regdom = user_data;
+       const unsigned char test[ETH_ALEN] = {};
 
-       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
-                                                       &regdom->alpha2);
-}
+       if (!peer)
+               return;
 
-int g_supplicant_set_country(const char *alpha2,
-                               GSupplicantCountryCallback callback,
-                                       const void *user_data)
-{
-       struct supplicant_regdom *regdom;
+       if (!memcmp(peer->device_address, test, ETH_ALEN)) {
+               peer->identifier = g_strdup(peer->name);
+               return;
+       }
 
-       SUPPLICANT_DBG("Country setting %s", alpha2);
+       peer->identifier = g_malloc0(19);
+       snprintf(peer->identifier, 19, "%02x%02x%02x%02x%02x%02x",
+                                               peer->device_address[0],
+                                               peer->device_address[1],
+                                               peer->device_address[2],
+                                               peer->device_address[3],
+                                               peer->device_address[4],
+                                               peer->device_address[5]);
+}
+
+struct peer_property_data {
+       GSupplicantPeer *peer;
+       GSList *old_groups;
+       bool groups_changed;
+       bool services_changed;
+};
 
-       if (system_available == FALSE)
-               return -EFAULT;
+static void peer_groups_relation(DBusMessageIter *iter, void *user_data)
+{
+       struct peer_property_data *data = user_data;
+       GSupplicantPeer *peer = data->peer;
+       GSupplicantGroup *group;
+       const char *str = NULL;
+       GSList *elem;
 
-       regdom = dbus_malloc0(sizeof(*regdom));
-       if (regdom == NULL)
-               return -ENOMEM;
+       dbus_message_iter_get_basic(iter, &str);
+       if (!str)
+               return;
 
-       regdom->callback = callback;
-       regdom->alpha2 = alpha2;
-       regdom->user_data = user_data;
+       group = g_hash_table_lookup(group_mapping, str);
+       if (!group)
+               return;
 
-       return supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
-                                       "Country", DBUS_TYPE_STRING_AS_STRING,
-                                       country_params, country_result,
-                                               regdom);
+       elem = g_slist_find_custom(data->old_groups, str, (GCompareFunc)g_strcmp0);
+       if (elem) {
+               data->old_groups = g_slist_remove_link(data->old_groups, elem);
+               peer->groups = g_slist_concat(elem, peer->groups);
+       } else {
+               peer->groups = g_slist_prepend(peer->groups, g_strdup(str));
+               data->groups_changed = true;
+       }
 }
 
-int g_supplicant_interface_set_country(GSupplicantInterface *interface,
-                                       GSupplicantCountryCallback callback,
-                                                       const char *alpha2,
+static void peer_property(const char *key, DBusMessageIter *iter,
                                                        void *user_data)
 {
-       struct supplicant_regdom *regdom;
+       GSupplicantPeer *pending_peer;
+       struct peer_property_data *data = user_data;
+       GSupplicantPeer *peer = data->peer;
 
-       regdom = dbus_malloc0(sizeof(*regdom));
-       if (regdom == NULL)
-               return -ENOMEM;
+       SUPPLICANT_DBG("key: %s", key);
 
-       regdom->callback = callback;
-       regdom->alpha2 = alpha2;
-       regdom->user_data = user_data;
+       if (!peer->interface)
+               return;
 
-       return supplicant_dbus_property_set(interface->path,
-                               SUPPLICANT_INTERFACE ".Interface",
-                               "Country", DBUS_TYPE_STRING_AS_STRING,
-                               country_params, country_result,
-                                       regdom);
-}
+       if (!key) {
+               if (peer->name) {
+                       create_peer_identifier(peer);
+                       callback_peer_found(peer);
+                       pending_peer = g_hash_table_lookup(
+                                       pending_peer_connection, peer->path);
+
+                       if (pending_peer && pending_peer == peer) {
+                               callback_peer_request(peer);
+                               g_hash_table_remove(pending_peer_connection,
+                                               peer->path);
+                       }
 
-struct interface_data {
-       GSupplicantInterface *interface;
-       GSupplicantInterfaceCallback callback;
-       void *user_data;
-};
+                       dbus_free(data);
+               }
 
-struct interface_create_data {
-       const char *ifname;
-       const char *driver;
-       const char *bridge;
-       GSupplicantInterface *interface;
-       GSupplicantInterfaceCallback callback;
-       void *user_data;
-};
+               return;
+       }
 
-struct interface_connect_data {
-       GSupplicantInterface *interface;
-       GSupplicantInterfaceCallback callback;
-       GSupplicantSSID *ssid;
-       void *user_data;
-};
+       if (g_strcmp0(key, "DeviceAddress") == 0) {
+               unsigned char *dev_addr;
+               DBusMessageIter array;
+               int len;
 
-struct interface_scan_data {
-       GSupplicantInterface *interface;
-       GSupplicantInterfaceCallback callback;
-       GSupplicantScanParams *scan_params;
-       void *user_data;
-};
+               dbus_message_iter_recurse(iter, &array);
+               dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
 
-struct interface_autoscan_data {
-       GSupplicantInterface *interface;
-       GSupplicantInterfaceCallback callback;
-       const char *autoscan_params;
-       void *user_data;
-};
+               if (len == ETH_ALEN)
+                       memcpy(peer->device_address, dev_addr, len);
+       } else if (g_strcmp0(key, "DeviceName") == 0) {
+               const char *str = NULL;
 
-static void interface_create_property(const char *key, DBusMessageIter *iter,
-                                                       void *user_data)
-{
-       struct interface_create_data *data = user_data;
-       GSupplicantInterface *interface = data->interface;
+               dbus_message_iter_get_basic(iter, &str);
+               if (str)
+                       peer->name = g_strdup(str);
+       } else if (g_strcmp0(key, "config_method") == 0) {
+               uint16_t wps_config;
 
-       if (key == NULL) {
-               if (data->callback != NULL)
-                       data->callback(0, data->interface, data->user_data);
+               dbus_message_iter_get_basic(iter, &wps_config);
 
-               dbus_free(data);
-       }
+               if (wps_config & G_SUPPLICANT_WPS_CONFIG_PBC)
+                       peer->wps_capabilities |= G_SUPPLICANT_WPS_PBC;
+               if (wps_config & ~G_SUPPLICANT_WPS_CONFIG_PBC)
+                       peer->wps_capabilities |= G_SUPPLICANT_WPS_PIN;
+       } else if (g_strcmp0(key, "Groups") == 0) {
+               data->old_groups = peer->groups;
+               peer->groups = NULL;
 
-       interface_property(key, iter, interface);
+               supplicant_dbus_array_foreach(iter,
+                                               peer_groups_relation, data);
+               if (g_slist_length(data->old_groups) > 0) {
+                       g_slist_free_full(data->old_groups, g_free);
+                       data->groups_changed = true;
+               }
+       } else if (g_strcmp0(key, "IEs") == 0) {
+               DBusMessageIter array;
+               unsigned char *ie;
+               int ie_len;
+
+               dbus_message_iter_recurse(iter, &array);
+               dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
+
+               if (!ie || ie_len < 2)
+                       return;
+
+               if (peer->widi_ies) {
+                       if (memcmp(peer->widi_ies, ie, ie_len) == 0)
+                               return;
+
+                       g_free(peer->widi_ies);
+                       peer->widi_ies_length = 0;
+               }
+
+               peer->widi_ies = g_malloc0(ie_len * sizeof(unsigned char));
+
+               memcpy(peer->widi_ies, ie, ie_len);
+               peer->widi_ies_length = ie_len;
+               data->services_changed = true;
+       }
 }
 
-static void interface_create_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+static void signal_peer_found(const char *path, DBusMessageIter *iter)
 {
-       struct interface_create_data *data = user_data;
-       const char *path = NULL;
-       int err;
+       struct peer_property_data *property_data;
+       GSupplicantInterface *interface;
+       const char *obj_path = NULL;
+       GSupplicantPeer *peer;
 
        SUPPLICANT_DBG("");
 
-       if (error != NULL) {
-               g_warning("error %s", error);
-               err = -EIO;
-               goto done;
-       }
-
-       dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL) {
-               err = -EINVAL;
-               goto done;
-       }
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
-       if (system_available == FALSE) {
-               err = -EFAULT;
-               goto done;
-       }
+       dbus_message_iter_get_basic(iter, &obj_path);
+       if (!obj_path || g_strcmp0(obj_path, "/") == 0)
+               return;
 
-       data->interface = g_hash_table_lookup(interface_table, path);
-       if (data->interface == NULL) {
-               data->interface = interface_alloc(path);
-               if (data->interface == NULL) {
-                       err = -ENOMEM;
-                       goto done;
-               }
-       }
+       peer = g_hash_table_lookup(interface->peer_table, obj_path);
+       if (peer)
+               return;
 
-       err = supplicant_dbus_property_get_all(path,
-                                       SUPPLICANT_INTERFACE ".Interface",
-                                       interface_create_property, data);
-       if (err == 0)
+       peer = g_try_new0(GSupplicantPeer, 1);
+       if (!peer)
                return;
 
-done:
-       if (data->callback != NULL)
-               data->callback(err, NULL, data->user_data);
+       peer->interface = interface;
+       peer->path = g_strdup(obj_path);
+       g_hash_table_insert(interface->peer_table, peer->path, peer);
+       g_hash_table_replace(peer_mapping, peer->path, interface);
 
-       dbus_free(data);
+       property_data = dbus_malloc0(sizeof(struct peer_property_data));
+       property_data->peer = peer;
+
+       dbus_message_iter_next(iter);
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
+               supplicant_dbus_property_foreach(iter, peer_property,
+                                                       property_data);
+               peer_property(NULL, NULL, property_data);
+               return;
+       }
+
+       supplicant_dbus_property_get_all(obj_path,
+                                       SUPPLICANT_INTERFACE ".Peer",
+                                       peer_property, property_data, NULL);
 }
 
-static void interface_create_params(DBusMessageIter *iter, void *user_data)
+static void signal_peer_lost(const char *path, DBusMessageIter *iter)
 {
-       struct interface_create_data *data = user_data;
-       DBusMessageIter dict;
+       GSupplicantInterface *interface;
+       const char *obj_path = NULL;
+       GSupplicantPeer *peer;
 
        SUPPLICANT_DBG("");
 
-       supplicant_dbus_dict_open(iter, &dict);
-
-       supplicant_dbus_dict_append_basic(&dict, "Ifname",
-                                       DBUS_TYPE_STRING, &data->ifname);
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
-       if (data->driver != NULL)
-               supplicant_dbus_dict_append_basic(&dict, "Driver",
-                                       DBUS_TYPE_STRING, &data->driver);
+       dbus_message_iter_get_basic(iter, &obj_path);
+       if (!obj_path || g_strcmp0(obj_path, "/") == 0)
+               return;
 
-       if (data->bridge != NULL)
-               supplicant_dbus_dict_append_basic(&dict, "BridgeIfname",
-                                       DBUS_TYPE_STRING, &data->bridge);
+       peer = g_hash_table_lookup(interface->peer_table, obj_path);
+       if (!peer)
+               return;
 
-       supplicant_dbus_dict_close(iter, &dict);
+       g_hash_table_remove(interface->peer_table, obj_path);
 }
 
-static void interface_get_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+static void signal_peer_changed(const char *path, DBusMessageIter *iter)
 {
-       struct interface_create_data *data = user_data;
+       struct peer_property_data *property_data;
        GSupplicantInterface *interface;
-       const char *path = NULL;
-       int err;
+       GSupplicantPeer *peer;
 
        SUPPLICANT_DBG("");
 
-       if (error != NULL) {
-               SUPPLICANT_DBG("Interface not created yet");
-               goto create;
-       }
+       interface = g_hash_table_lookup(peer_mapping, path);
+       if (!interface)
+               return;
 
-       dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL) {
-               err = -EINVAL;
-               goto done;
+       peer = g_hash_table_lookup(interface->peer_table, path);
+       if (!peer) {
+               g_hash_table_remove(peer_mapping, path);
+               return;
        }
 
-       interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL) {
-               err = -ENOENT;
-               goto done;
-       }
+       property_data = dbus_malloc0(sizeof(struct peer_property_data));
+       property_data->peer = peer;
 
-       if (data->callback != NULL)
-               data->callback(0, interface, data->user_data);
+       supplicant_dbus_property_foreach(iter, peer_property, property_data);
+       if (property_data->services_changed)
+               callback_peer_changed(peer,
+                                       G_SUPPLICANT_PEER_SERVICES_CHANGED);
 
-       dbus_free(data);
+       if (property_data->groups_changed)
+               callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_CHANGED);
 
-       return;
+       dbus_free(property_data);
 
-create:
-       if (system_available == FALSE) {
-               err = -EFAULT;
-               goto done;
-       }
+       if (!g_supplicant_peer_is_in_a_group(peer))
+               peer->connection_requested = false;
+}
 
-       SUPPLICANT_DBG("Creating interface");
+struct group_sig_data {
+       const char *peer_obj_path;
+       unsigned char iface_address[ETH_ALEN];
+       const char *interface_obj_path;
+       const char *group_obj_path;
+       int role;
+};
 
-       err = supplicant_dbus_method_call(SUPPLICANT_PATH,
-                                               SUPPLICANT_INTERFACE,
-                                               "CreateInterface",
-                                               interface_create_params,
-                                               interface_create_result, data);
-       if (err == 0)
+static void group_sig_property(const char *key, DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       struct group_sig_data *data = user_data;
+
+       if (!key)
                return;
 
-done:
-       if (data->callback != NULL)
-               data->callback(err, NULL, data->user_data);
+       if (g_strcmp0(key, "peer_interface_addr") == 0) {
+               unsigned char *dev_addr;
+               DBusMessageIter array;
+               int len;
 
-       dbus_free(data);
-}
+               dbus_message_iter_recurse(iter, &array);
+               dbus_message_iter_get_fixed_array(&array, &dev_addr, &len);
 
-static void interface_get_params(DBusMessageIter *iter, void *user_data)
-{
-       struct interface_create_data *data = user_data;
+               if (len == ETH_ALEN)
+                       memcpy(data->iface_address, dev_addr, len);
+       } else if (g_strcmp0(key, "role") == 0) {
+               const char *str = NULL;
 
-       SUPPLICANT_DBG("");
+               dbus_message_iter_get_basic(iter, &str);
+               if (g_strcmp0(str, "GO") == 0)
+                       data->role = G_SUPPLICANT_GROUP_ROLE_GO;
+               else
+                       data->role = G_SUPPLICANT_GROUP_ROLE_CLIENT;
+       } else if (g_strcmp0(key, "peer_object") == 0)
+               dbus_message_iter_get_basic(iter, &data->peer_obj_path);
+       else if (g_strcmp0(key, "interface_object") == 0)
+               dbus_message_iter_get_basic(iter, &data->interface_obj_path);
+       else if (g_strcmp0(key, "group_object") == 0)
+               dbus_message_iter_get_basic(iter, &data->group_obj_path);
 
-       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
 }
 
-int g_supplicant_interface_create(const char *ifname, const char *driver,
-                                       const char *bridge,
-                                       GSupplicantInterfaceCallback callback,
-                                                       void *user_data)
+static void signal_group_success(const char *path, DBusMessageIter *iter)
 {
-       struct interface_create_data *data;
+       GSupplicantInterface *interface;
+       struct group_sig_data data = {};
+       GSupplicantPeer *peer;
 
-       SUPPLICANT_DBG("ifname %s", ifname);
+       SUPPLICANT_DBG("");
 
-       if (ifname == NULL)
-               return -EINVAL;
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
-       if (system_available == FALSE)
-               return -EFAULT;
+       supplicant_dbus_property_foreach(iter, group_sig_property, &data);
+       if (!data.peer_obj_path)
+               return;
 
-       data = dbus_malloc0(sizeof(*data));
-       if (data == NULL)
-               return -ENOMEM;
-
-       data->ifname = ifname;
-       data->driver = driver;
-       data->bridge = bridge;
-       data->callback = callback;
-       data->user_data = user_data;
+       peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
+       if (!peer)
+               return;
 
-       return supplicant_dbus_method_call(SUPPLICANT_PATH,
-                                               SUPPLICANT_INTERFACE,
-                                               "GetInterface",
-                                               interface_get_params,
-                                               interface_get_result, data);
+       memcpy(peer->iface_address, data.iface_address, ETH_ALEN);
+       interface->pending_peer_path = peer->path;
 }
 
-static void interface_remove_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+static void signal_group_failure(const char *path, DBusMessageIter *iter)
 {
-       struct interface_data *data = user_data;
-       int err;
-
-       if (error != NULL) {
-               err = -EIO;
-               goto done;
-       }
-
-       if (system_available == FALSE) {
-               err = -EFAULT;
-               goto done;
-       }
-
-       /*
-        * The gsupplicant interface is already freed by the InterfaceRemoved
-        * signal callback. Simply invoke the interface_data callback.
-        */
-       err = 0;
+       GSupplicantInterface *interface;
+       struct group_sig_data data = {};
+       GSupplicantPeer *peer;
 
-done:
-       if (data->callback != NULL)
-               data->callback(err, NULL, data->user_data);
+       SUPPLICANT_DBG("");
 
-       dbus_free(data);
-}
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
+       supplicant_dbus_property_foreach(iter, group_sig_property, &data);
+       if (!data.peer_obj_path)
+               return;
 
-static void interface_remove_params(DBusMessageIter *iter, void *user_data)
-{
-       struct interface_data *data = user_data;
+       peer = g_hash_table_lookup(interface->peer_table, data.peer_obj_path);
+       if (!peer)
+               return;
 
-       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
-                                                       &data->interface->path);
+       callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_FAILED);
+       peer->connection_requested = false;
 }
 
-
-int g_supplicant_interface_remove(GSupplicantInterface *interface,
-                       GSupplicantInterfaceCallback callback,
-                                                       void *user_data)
+static void signal_group_started(const char *path, DBusMessageIter *iter)
 {
-       struct interface_data *data;
+       GSupplicantInterface *interface, *g_interface;
+       struct group_sig_data data = {};
+       GSupplicantGroup *group;
+       GSupplicantPeer *peer;
 
-       if (interface == NULL)
-               return -EINVAL;
+       SUPPLICANT_DBG("");
 
-       if (system_available == FALSE)
-               return -EFAULT;
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
-       data = dbus_malloc0(sizeof(*data));
-       if (data == NULL)
-               return -ENOMEM;
+       supplicant_dbus_property_foreach(iter, group_sig_property, &data);
+       if (!data.interface_obj_path || !data.group_obj_path)
+               return;
 
-       data->interface = interface;
-       data->callback = callback;
-       data->user_data = user_data;
+       peer = g_hash_table_lookup(interface->peer_table,
+                                               interface->pending_peer_path);
+       interface->pending_peer_path = NULL;
+       if (!peer)
+               return;
 
-       return supplicant_dbus_method_call(SUPPLICANT_PATH,
-                                               SUPPLICANT_INTERFACE,
-                                               "RemoveInterface",
-                                               interface_remove_params,
-                                               interface_remove_result, data);
-}
+       g_interface = g_hash_table_lookup(interface_table,
+                                               data.interface_obj_path);
+       if (!g_interface)
+               return;
 
-static void interface_scan_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
-{
-       struct interface_scan_data *data = user_data;
+       group = g_hash_table_lookup(interface->group_table,
+                                               data.group_obj_path);
+       if (group)
+               return;
 
-       if (error != NULL) {
-               SUPPLICANT_DBG("error %s", error);
+       group = g_try_new0(GSupplicantGroup, 1);
+       if (!group)
+               return;
 
-               if (data->callback != NULL)
-                       data->callback(-EIO, data->interface, data->user_data);
-       } else {
-               data->interface->scan_callback = data->callback;
-               data->interface->scan_data = data->user_data;
-       }
+       group->interface = g_interface;
+       group->orig_interface = interface;
+       group->path = g_strdup(data.group_obj_path);
+       group->role = data.role;
 
-       if (data != NULL && data->scan_params != NULL)
-               g_supplicant_free_scan_params(data->scan_params);
+       g_hash_table_insert(interface->group_table, group->path, group);
+       g_hash_table_replace(group_mapping, group->path, group);
 
-       dbus_free(data);
+       peer->current_group_iface = g_interface;
+       callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_STARTED);
 }
 
-static void add_scan_frequency(DBusMessageIter *iter, unsigned int freq)
+static void remove_peer_group_interface(GHashTable *group_table,
+                               const char* path)
 {
-       DBusMessageIter data;
-       unsigned int width = 0; /* Not used by wpa_supplicant atm */
+       GSupplicantGroup *group;
+       GHashTableIter iter;
+       gpointer value, key;
 
-       dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &data);
+       if (!group_table)
+               return;
 
-       dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &freq);
-       dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &width);
+       group = g_hash_table_lookup(group_table, path);
 
-       dbus_message_iter_close_container(iter, &data);
-}
+       if (!group || !group->orig_interface)
+               return;
 
-static void add_scan_frequencies(DBusMessageIter *iter,
-                                               void *user_data)
-{
-       GSupplicantScanParams *scan_data = user_data;
-       unsigned int freq;
-       int i;
+       g_hash_table_iter_init(&iter, group->orig_interface->peer_table);
 
-       for (i = 0; i < scan_data->num_ssids; i++) {
-               freq = scan_data->freqs[i];
-               if (!freq)
-                       break;
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               GSupplicantPeer *peer = value;
 
-               add_scan_frequency(iter, freq);
+               if (peer->current_group_iface == group->interface)
+                       peer->current_group_iface = NULL;
        }
 }
 
-static void append_ssid(DBusMessageIter *iter,
-                       const void *ssid, unsigned int len)
+static void signal_group_finished(const char *path, DBusMessageIter *iter)
 {
-       DBusMessageIter array;
+       GSupplicantInterface *interface;
+       struct group_sig_data data = {};
 
-       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
-       DBUS_TYPE_BYTE_AS_STRING, &array);
+       SUPPLICANT_DBG("");
 
-       dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
-                                                               &ssid, len);
-       dbus_message_iter_close_container(iter, &array);
-}
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
-static void append_ssids(DBusMessageIter *iter, void *user_data)
-{
-       GSupplicantScanParams *scan_data = user_data;
-       GSList *list;
+       supplicant_dbus_property_foreach(iter, group_sig_property, &data);
+       if (!data.interface_obj_path || !data.group_obj_path)
+               return;
 
-       for (list = scan_data->ssids; list; list = list->next) {
-               struct scan_ssid *scan_ssid = list->data;
+       remove_peer_group_interface(interface->group_table, data.group_obj_path);
 
-               append_ssid(iter, scan_ssid->ssid, scan_ssid->ssid_len);
-       }
+       g_hash_table_remove(group_mapping, data.group_obj_path);
+
+       g_hash_table_remove(interface->group_table, data.group_obj_path);
 }
 
-static void supplicant_add_scan_frequency(DBusMessageIter *dict,
-               supplicant_dbus_array_function function,
-                                       void *user_data)
+static void signal_group_request(const char *path, DBusMessageIter *iter)
 {
-       GSupplicantScanParams *scan_params = user_data;
-       DBusMessageIter entry, value, array;
-       const char *key = "Channels";
-
-       if (scan_params->freqs && scan_params->freqs[0] != 0) {
-               dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
-                                               NULL, &entry);
+       GSupplicantInterface *interface;
+       GSupplicantPeer *peer;
+       const char *obj_path;
 
-               dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+       SUPPLICANT_DBG("");
 
-               dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
-                                       DBUS_TYPE_ARRAY_AS_STRING
-                                       DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-                                       DBUS_TYPE_UINT32_AS_STRING
-                                       DBUS_TYPE_UINT32_AS_STRING
-                                       DBUS_STRUCT_END_CHAR_AS_STRING,
-                                       &value);
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
-               dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
-                                       DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-                                       DBUS_TYPE_UINT32_AS_STRING
-                                       DBUS_TYPE_UINT32_AS_STRING
-                                       DBUS_STRUCT_END_CHAR_AS_STRING,
-                                       &array);
+       dbus_message_iter_get_basic(iter, &obj_path);
+       if (!obj_path || !g_strcmp0(obj_path, "/"))
+               return;
 
-               if (function)
-                       function(&array, user_data);
+       peer = g_hash_table_lookup(interface->peer_table, obj_path);
+       if (!peer)
+               return;
 
-               dbus_message_iter_close_container(&value, &array);
-               dbus_message_iter_close_container(&entry, &value);
-               dbus_message_iter_close_container(dict, &entry);
-       }
+       /*
+        * Peer has been previously found and property set,
+        * otherwise, defer connection to when peer property
+        * is set.
+        */
+       if (peer->identifier)
+               callback_peer_request(peer);
+       else
+               g_hash_table_replace(pending_peer_connection, peer->path, peer);
 }
 
-static void interface_scan_params(DBusMessageIter *iter, void *user_data)
+static void signal_group_peer_joined(const char *path, DBusMessageIter *iter)
 {
-       DBusMessageIter dict;
-       const char *type = "passive";
-       struct interface_scan_data *data = user_data;
+       const char *peer_path = NULL;
+       GSupplicantInterface *interface;
+       GSupplicantGroup *group;
+       GSupplicantPeer *peer;
 
-       supplicant_dbus_dict_open(iter, &dict);
+       SUPPLICANT_DBG("");
 
-       if (data && data->scan_params) {
-               type = "active";
+       group = g_hash_table_lookup(group_mapping, path);
+       if (!group)
+               return;
 
-               supplicant_dbus_dict_append_basic(&dict, "Type",
-                                       DBUS_TYPE_STRING, &type);
+       dbus_message_iter_get_basic(iter, &peer_path);
+       if (!peer_path)
+               return;
 
-               supplicant_dbus_dict_append_array(&dict, "SSIDs",
-                                               DBUS_TYPE_STRING,
-                                               append_ssids,
-                                               data->scan_params);
+       interface = g_hash_table_lookup(peer_mapping, peer_path);
+       if (!interface)
+               return;
 
-               supplicant_add_scan_frequency(&dict, add_scan_frequencies,
-                                               data->scan_params);
-       } else
-               supplicant_dbus_dict_append_basic(&dict, "Type",
-                                       DBUS_TYPE_STRING, &type);
+       peer = g_hash_table_lookup(interface->peer_table, peer_path);
+       if (!peer)
+               return;
 
-       supplicant_dbus_dict_close(iter, &dict);
+       group->members = g_slist_prepend(group->members, g_strdup(peer_path));
+
+       callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_JOINED);
 }
 
-int g_supplicant_interface_scan(GSupplicantInterface *interface,
-                               GSupplicantScanParams *scan_data,
-                               GSupplicantInterfaceCallback callback,
-                                                       void *user_data)
+static void signal_group_peer_disconnected(const char *path, DBusMessageIter *iter)
 {
-       struct interface_scan_data *data;
-       int ret;
+       const char *peer_path = NULL;
+       GSupplicantInterface *interface;
+       GSupplicantGroup *group;
+       GSupplicantPeer *peer;
+       GSList *elem;
 
-       if (interface == NULL)
-               return -EINVAL;
+       SUPPLICANT_DBG("");
 
-       if (system_available == FALSE)
-               return -EFAULT;
+       group = g_hash_table_lookup(group_mapping, path);
+       if (!group)
+               return;
 
-       if (interface->scanning == TRUE)
-               return -EALREADY;
+       dbus_message_iter_get_basic(iter, &peer_path);
+       if (!peer_path)
+               return;
 
-       switch (interface->state) {
-       case G_SUPPLICANT_STATE_AUTHENTICATING:
-       case G_SUPPLICANT_STATE_ASSOCIATING:
-       case G_SUPPLICANT_STATE_ASSOCIATED:
-       case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
-       case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
-               return -EBUSY;
-       case G_SUPPLICANT_STATE_UNKNOWN:
-       case G_SUPPLICANT_STATE_DISCONNECTED:
-       case G_SUPPLICANT_STATE_INACTIVE:
-       case G_SUPPLICANT_STATE_SCANNING:
-       case G_SUPPLICANT_STATE_COMPLETED:
-               break;
+       for (elem = group->members; elem; elem = elem->next) {
+               if (!g_strcmp0(elem->data, peer_path))
+                       break;
        }
 
-       data = dbus_malloc0(sizeof(*data));
-       if (data == NULL)
-               return -ENOMEM;
+       if (!elem)
+               return;
 
-       data->interface = interface;
-       data->callback = callback;
-       data->user_data = user_data;
-       data->scan_params = scan_data;
+       g_free(elem->data);
+       group->members = g_slist_delete_link(group->members, elem);
 
-       ret = supplicant_dbus_method_call(interface->path,
-                       SUPPLICANT_INTERFACE ".Interface", "Scan",
-                       interface_scan_params, interface_scan_result, data);
+       interface = g_hash_table_lookup(peer_mapping, peer_path);
+       if (!interface)
+               return;
 
-       if (ret < 0)
-               dbus_free(data);
+       peer = g_hash_table_lookup(interface->peer_table, peer_path);
+       if (!peer)
+               return;
 
-       return ret;
+       callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_DISCONNECTED);
+       peer->connection_requested = false;
 }
 
-static void interface_autoscan_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+#if defined TIZEN_EXT_WIFI_MESH
+const void *g_supplicant_interface_get_mesh_group_ssid(
+                                                       GSupplicantInterface *interface,
+                                                       unsigned int *ssid_len)
 {
-       struct interface_autoscan_data *data = user_data;
-       int err = 0;
+       if (!ssid_len)
+               return NULL;
 
-       if (error != NULL) {
-               SUPPLICANT_DBG("error %s", error);
-               err = -EIO;
+       if (!interface || interface->group_info.ssid_len == 0) {
+               *ssid_len = 0;
+               return NULL;
        }
 
-       if (data != NULL && data->callback != NULL)
-               data->callback(err, data->interface, data->user_data);
-
-       dbus_free(data);
+       *ssid_len = interface->group_info.ssid_len;
+       return interface->group_info.ssid;
 }
 
-static void interface_autoscan_params(DBusMessageIter *iter, void *user_data)
+int g_supplicant_mesh_get_disconnect_reason(GSupplicantInterface *interface)
 {
-       struct interface_autoscan_data *data = user_data;
+       if (!interface)
+               return -EINVAL;
 
-       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
-                                                &data->autoscan_params);
+       return interface->group_info.disconnect_reason;
 }
 
-int g_supplicant_interface_autoscan(GSupplicantInterface *interface,
-                                       const char *autoscan_data,
-                                       GSupplicantInterfaceCallback callback,
-                                                       void *user_data)
+const char *g_supplicant_mesh_peer_get_address(GSupplicantMeshPeer *mesh_peer)
 {
-       struct interface_autoscan_data *data;
-       int ret;
-
-       data = dbus_malloc0(sizeof(*data));
-       if (data == NULL)
-               return -ENOMEM;
+       if (!mesh_peer || !mesh_peer->peer_address)
+               return NULL;
 
-       data->interface = interface;
-       data->callback = callback;
-       data->autoscan_params = autoscan_data;
-       data->user_data = user_data;
+       return mesh_peer->peer_address;
+}
 
-       ret = supplicant_dbus_method_call(interface->path,
-                       SUPPLICANT_INTERFACE ".Interface", "AutoScan",
-                       interface_autoscan_params,
-                       interface_autoscan_result, data);
-       if (ret < 0)
-               dbus_free(data);
+int g_supplicant_mesh_peer_get_disconnect_reason(GSupplicantMeshPeer *mesh_peer)
+{
+       if (!mesh_peer)
+               return -EINVAL;
 
-       return ret;
+       return mesh_peer->disconnect_reason;
 }
 
-static int parse_supplicant_error(DBusMessageIter *iter)
+static void callback_mesh_group_started(GSupplicantInterface *interface)
 {
-       int err = -ECANCELED;
-       char *key;
+       if (!callbacks_pointer)
+               return;
 
-       /* If the given passphrase is malformed wpa_s returns
-        * "invalid message format" but this error should be interpreted as
-        * invalid-key.
-        */
-       while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
-               dbus_message_iter_get_basic(iter, &key);
-               if (strncmp(key, "psk", 3) == 0 ||
-                               strncmp(key, "wep_key", 7) == 0 ||
-                               strcmp(key, "invalid message format") == 0) {
-                       err = -ENOKEY;
-                       break;
-               }
-               dbus_message_iter_next(iter);
-       }
+       if (!callbacks_pointer->mesh_group_started)
+               return;
 
-       return err;
+       callbacks_pointer->mesh_group_started(interface);
 }
 
-static void interface_select_network_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+static void callback_mesh_group_removed(GSupplicantInterface *interface)
 {
-       struct interface_connect_data *data = user_data;
-       int err;
-
-       SUPPLICANT_DBG("");
-
-       err = 0;
-       if (error != NULL) {
-               SUPPLICANT_DBG("SelectNetwork error %s", error);
-               err = parse_supplicant_error(iter);
-       }
+       if (!callbacks_pointer)
+               return;
 
-       if (data->callback != NULL)
-               data->callback(err, data->interface, data->user_data);
+       if (!callbacks_pointer->mesh_group_removed)
+               return;
 
-       g_free(data->ssid);
-       dbus_free(data);
+       callbacks_pointer->mesh_group_removed(interface);
 }
 
-static void interface_select_network_params(DBusMessageIter *iter,
+static void mesh_group_info(const char *key, DBusMessageIter *iter,
                                                        void *user_data)
 {
-       struct interface_connect_data *data = user_data;
-       GSupplicantInterface *interface = data->interface;
-
-       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
-                                       &interface->network_path);
-}
-
-static void interface_add_network_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
-{
-       struct interface_connect_data *data = user_data;
-       GSupplicantInterface *interface = data->interface;
-       const char *path;
-       int err;
-
-       if (error != NULL)
-               goto error;
-
-       dbus_message_iter_get_basic(iter, &path);
-       if (path == NULL)
-               goto error;
-
-       SUPPLICANT_DBG("PATH: %s", path);
-
-       g_free(interface->network_path);
-       interface->network_path = g_strdup(path);
-
-       supplicant_dbus_method_call(data->interface->path,
-                       SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
-                       interface_select_network_params,
-                       interface_select_network_result, data);
+       GSupplicantInterface *interface = user_data;
+       if (!key)
+               return;
 
-       return;
+       if (g_strcmp0(key, "SSID") == 0) {
+               DBusMessageIter array;
+               unsigned char *ssid;
+               int ssid_len;
 
-error:
-       SUPPLICANT_DBG("AddNetwork error %s", error);
-       err = parse_supplicant_error(iter);
-       if (data->callback != NULL)
-               data->callback(err, data->interface, data->user_data);
+               dbus_message_iter_recurse(iter, &array);
+               dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
 
-       g_free(interface->network_path);
-       interface->network_path = NULL;
-       g_free(data->ssid);
-       g_free(data);
+               if (ssid_len > 0 && ssid_len < 33) {
+                       memcpy(interface->group_info.ssid, ssid, ssid_len);
+                       interface->group_info.ssid_len = ssid_len;
+               } else {
+                       memset(interface->group_info.ssid, 0, 32);
+                       interface->group_info.ssid_len = 0;
+               }
+       } else if (g_strcmp0(key, "DisconnectReason") == 0) {
+               int disconnect_reason = 0;
+               dbus_message_iter_get_basic(iter, &disconnect_reason);
+               interface->group_info.disconnect_reason = disconnect_reason;
+       }
 }
 
-static void add_network_security_wep(DBusMessageIter *dict,
-                                       GSupplicantSSID *ssid)
+static void signal_mesh_group_started(const char *path, DBusMessageIter *iter)
 {
-       const char *auth_alg = "OPEN SHARED";
-       const char *key_index = "0";
-
-       supplicant_dbus_dict_append_basic(dict, "auth_alg",
-                                       DBUS_TYPE_STRING, &auth_alg);
-
-       if (ssid->passphrase) {
-               int size = strlen(ssid->passphrase);
-               if (size == 10 || size == 26) {
-                       unsigned char *key = g_try_malloc(13);
-                       char tmp[3];
-                       int i;
+       GSupplicantInterface *interface;
 
-                       memset(tmp, 0, sizeof(tmp));
-                       if (key == NULL)
-                               size = 0;
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
-                       for (i = 0; i < size / 2; i++) {
-                               memcpy(tmp, ssid->passphrase + (i * 2), 2);
-                               key[i] = (unsigned char) strtol(tmp, NULL, 16);
-                       }
+       supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
 
-                       supplicant_dbus_dict_append_fixed_array(dict,
-                                                       "wep_key0",
-                                                       DBUS_TYPE_BYTE,
-                                                       &key, size / 2);
-                       g_free(key);
-               } else if (size == 5 || size == 13) {
-                       unsigned char *key = g_try_malloc(13);
-                       int i;
+       callback_mesh_group_started(interface);
+}
 
-                       if (key == NULL)
-                               size = 0;
+static void signal_mesh_group_removed(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
 
-                       for (i = 0; i < size; i++)
-                               key[i] = (unsigned char) ssid->passphrase[i];
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
 
-                       supplicant_dbus_dict_append_fixed_array(dict,
-                                                               "wep_key0",
-                                                               DBUS_TYPE_BYTE,
-                                                               &key, size);
-                       g_free(key);
-               } else
-                       supplicant_dbus_dict_append_basic(dict,
-                                                       "wep_key0",
-                                                       DBUS_TYPE_STRING,
-                                                       &ssid->passphrase);
+       supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
 
-               supplicant_dbus_dict_append_basic(dict, "wep_tx_keyidx",
-                                       DBUS_TYPE_STRING, &key_index);
-       }
+       callback_mesh_group_removed(interface);
 }
 
-static dbus_bool_t is_psk_raw_key(const char *psk)
+static void callback_mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
 {
-       int i;
-
-       /* A raw key is always 64 bytes length... */
-       if (strlen(psk) != 64)
-               return FALSE;
+       if (!callbacks_pointer)
+               return;
 
-       /* ... and its content is in hex representation */
-       for (i = 0; i < 64; i++)
-               if (!isxdigit((unsigned char) psk[i]))
-                       return FALSE;
+       if (!callbacks_pointer->mesh_peer_connected)
+               return;
 
-       return TRUE;
+       callbacks_pointer->mesh_peer_connected(mesh_peer);
 }
 
-static unsigned char hexchar2bin(char c)
+static void callback_mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
 {
-       if ((c >= '0') && (c <= '9'))
-               return c - '0';
-       else if ((c >= 'A') && (c <= 'F'))
-               return c - 'A' + 10;
-       else if ((c >= 'a') && (c <= 'f'))
-               return c - 'a' + 10;
-       else
-               return c;
-}
+       if (!callbacks_pointer)
+               return;
 
-static void hexstring2bin(const char *string, unsigned char *data, size_t data_len)
-{
-       size_t i;
+       if (!callbacks_pointer->mesh_peer_disconnected)
+               return;
 
-       for (i = 0; i < data_len; i++)
-               data[i] = (hexchar2bin(string[i * 2 + 0]) << 4 |
-                          hexchar2bin(string[i * 2 + 1]) << 0);
+       callbacks_pointer->mesh_peer_disconnected(mesh_peer);
 }
 
-static void add_network_security_psk(DBusMessageIter *dict,
-                                       GSupplicantSSID *ssid)
+static void mesh_peer_info(const char *key, DBusMessageIter *iter,
+                                                       void *user_data)
 {
-       if (ssid->passphrase && strlen(ssid->passphrase) > 0) {
-               const char *key = "psk";
-
-               if (is_psk_raw_key(ssid->passphrase) == TRUE) {
-                       unsigned char data[32];
-                       unsigned char *datap = data;
+       GSupplicantMeshPeer *mesh_peer = user_data;
+       if (!key)
+               return;
 
-                       /* The above pointer alias is required by D-Bus because
-                        * with D-Bus and GCC, non-heap-allocated arrays cannot
-                        * be passed directly by their base pointer. */
+       if (g_strcmp0(key, "PeerAddress") == 0) {
+               DBusMessageIter array;
+               unsigned char *addr;
+               int addr_len;
 
-                       hexstring2bin(ssid->passphrase, datap, sizeof(data));
+               dbus_message_iter_recurse(iter, &array);
+               dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
 
-                       supplicant_dbus_dict_append_fixed_array(dict,
-                                                       key, DBUS_TYPE_BYTE,
-                                                       &datap, sizeof(data));
-               } else
-                       supplicant_dbus_dict_append_basic(dict,
-                                                       key, DBUS_TYPE_STRING,
-                                                       &ssid->passphrase);
+               if (addr_len == 6) {
+                       mesh_peer->peer_address = g_malloc0(19);
+                       snprintf(mesh_peer->peer_address, 19,
+                                        "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1],
+                                        addr[2], addr[3], addr[4], addr[5]);
+               }
+       } else if (g_strcmp0(key, "DisconnectReason") == 0) {
+               int disconnect_reason = 0;
+               dbus_message_iter_get_basic(iter, &disconnect_reason);
+               mesh_peer->disconnect_reason = disconnect_reason;
        }
 }
 
-static void add_network_security_tls(DBusMessageIter *dict,
-                                       GSupplicantSSID *ssid)
+static void signal_mesh_peer_connected(const char *path, DBusMessageIter *iter)
 {
-       /*
-        * For TLS, we at least need:
-        *              The client certificate
-        *              The client private key file
-        *              The client private key file password
-        *
-        * The Authority certificate is optional.
-        */
-       if (ssid->client_cert_path == NULL)
-               return;
+       GSupplicantInterface *interface;
+       GSupplicantMeshPeer *mesh_peer;
 
-       if (ssid->private_key_path == NULL)
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
                return;
 
-       if (ssid->private_key_passphrase == NULL)
-               return;
+       mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
+       mesh_peer->interface = interface;
 
-       if (ssid->ca_cert_path)
-               supplicant_dbus_dict_append_basic(dict, "ca_cert",
-                                       DBUS_TYPE_STRING, &ssid->ca_cert_path);
+       supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
 
-       supplicant_dbus_dict_append_basic(dict, "private_key",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->private_key_path);
-       supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->private_key_passphrase);
-       supplicant_dbus_dict_append_basic(dict, "client_cert",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->client_cert_path);
+       callback_mesh_peer_connected(mesh_peer);
+       g_free(mesh_peer->peer_address);
+       g_free(mesh_peer);
 }
 
-static void add_network_security_peap(DBusMessageIter *dict,
-                                       GSupplicantSSID *ssid)
+static void signal_mesh_peer_disconnected(const char *path,
+                                                               DBusMessageIter *iter)
 {
-       char *phase2_auth;
+       GSupplicantInterface *interface;
+       GSupplicantMeshPeer *mesh_peer;
 
-       /*
-        * For PEAP/TTLS, we at least need
-        *              The authority certificate
-        *              The 2nd phase authentication method
-        *              The 2nd phase passphrase
-        *
-        * The Client certificate is optional although strongly recommended
-        * When setting it, we need in addition
-        *              The Client private key file
-        *              The Client private key file password
-        */
-       if (ssid->passphrase == NULL)
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
                return;
 
-       if (ssid->phase2_auth == NULL)
-               return;
+       mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
+       mesh_peer->interface = interface;
 
-       if (ssid->client_cert_path) {
-               if (ssid->private_key_path == NULL)
-                       return;
+       supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
 
-               if (ssid->private_key_passphrase == NULL)
-                       return;
+       callback_mesh_peer_disconnected(mesh_peer);
+       g_free(mesh_peer->peer_address);
+       g_free(mesh_peer);
+}
+#endif
 
-               supplicant_dbus_dict_append_basic(dict, "client_cert",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->client_cert_path);
+static struct {
+       const char *interface;
+       const char *member;
+       void (*function) (const char *path, DBusMessageIter *iter);
+} signal_map[] = {
+       { DBUS_INTERFACE_DBUS,  "NameOwnerChanged",  signal_name_owner_changed },
 
-               supplicant_dbus_dict_append_basic(dict, "private_key",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->private_key_path);
+       { SUPPLICANT_INTERFACE, "PropertiesChanged", signal_properties_changed },
+       { SUPPLICANT_INTERFACE, "InterfaceAdded",    signal_interface_added    },
+       { SUPPLICANT_INTERFACE, "InterfaceCreated",  signal_interface_added    },
+       { SUPPLICANT_INTERFACE, "InterfaceRemoved",  signal_interface_removed  },
 
-               supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->private_key_passphrase);
+       { SUPPLICANT_INTERFACE ".Interface", "PropertiesChanged", signal_interface_changed },
+       { SUPPLICANT_INTERFACE ".Interface", "ScanDone",          signal_scan_done         },
+       { SUPPLICANT_INTERFACE ".Interface", "BSSAdded",          signal_bss_added         },
+       { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved",        signal_bss_removed       },
+       { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded",      signal_network_added     },
+       { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved",    signal_network_removed   },
 
-       }
+       { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed   },
 
-       if (g_str_has_prefix(ssid->phase2_auth, "EAP-") == TRUE) {
-               phase2_auth = g_strdup_printf("autheap=%s",
-                                       ssid->phase2_auth + strlen("EAP-"));
-       } else
-               phase2_auth = g_strdup_printf("auth=%s", ssid->phase2_auth);
+       { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
+       { SUPPLICANT_INTERFACE ".Interface.WPS", "Event",       signal_wps_event       },
+#if defined TIZEN_EXT
+       { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
+#endif
 
-       supplicant_dbus_dict_append_basic(dict, "password",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->passphrase);
+       { SUPPLICANT_INTERFACE".Interface", "StaAuthorized", signal_station_connected      },
+       { SUPPLICANT_INTERFACE".Interface", "StaDeauthorized", signal_station_disconnected },
+
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost",  signal_peer_lost  },
+
+       { SUPPLICANT_INTERFACE ".Peer", "PropertiesChanged", signal_peer_changed },
+
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationSuccess", signal_group_success },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationFailure", signal_group_failure },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupStarted", signal_group_started },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupFinished", signal_group_finished },
+       { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationRequest", signal_group_request },
+
+       { SUPPLICANT_INTERFACE ".Group", "PeerJoined", signal_group_peer_joined },
+       { SUPPLICANT_INTERFACE ".Group", "PeerDisconnected", signal_group_peer_disconnected },
+#if defined TIZEN_EXT_WIFI_MESH
+       { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupStarted",
+               signal_mesh_group_started },
+       { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupRemoved",
+               signal_mesh_group_removed },
+       { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerConnected",
+               signal_mesh_peer_connected },
+       { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerDisconnected",
+               signal_mesh_peer_disconnected },
+#endif
 
-       if (ssid->ca_cert_path)
-               supplicant_dbus_dict_append_basic(dict, "ca_cert",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->ca_cert_path);
+       { }
+};
 
-       supplicant_dbus_dict_append_basic(dict, "phase2",
-                                               DBUS_TYPE_STRING,
-                                               &phase2_auth);
+static DBusHandlerResult g_supplicant_filter(DBusConnection *conn,
+                                       DBusMessage *message, void *data)
+{
+       DBusMessageIter iter;
+       const char *path;
+       int i;
 
-       g_free(phase2_auth);
+       path = dbus_message_get_path(message);
+       if (!path)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (!dbus_message_iter_init(message, &iter))
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       for (i = 0; signal_map[i].interface; i++) {
+               if (!dbus_message_has_interface(message, signal_map[i].interface))
+                       continue;
+
+               if (!dbus_message_has_member(message, signal_map[i].member))
+                       continue;
+
+               signal_map[i].function(path, &iter);
+               break;
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
-static void add_network_security_eap(DBusMessageIter *dict,
-                                       GSupplicantSSID *ssid)
+void g_supplicant_interface_cancel(GSupplicantInterface *interface)
 {
-       char *eap_value;
+       SUPPLICANT_DBG("Cancelling any pending DBus calls");
+       supplicant_dbus_method_call_cancel_all(interface);
+       supplicant_dbus_property_call_cancel_all(interface);
+}
 
-       if (ssid->eap == NULL || ssid->identity == NULL)
-               return;
+struct supplicant_regdom {
+       GSupplicantCountryCallback callback;
+       const char *alpha2;
+       const void *user_data;
+};
 
-       if (g_strcmp0(ssid->eap, "tls") == 0) {
-               add_network_security_tls(dict, ssid);
-       } else if (g_strcmp0(ssid->eap, "peap") == 0 ||
-                               g_strcmp0(ssid->eap, "ttls") == 0) {
-               add_network_security_peap(dict, ssid);
-       } else
+static void country_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_regdom *regdom = user_data;
+       int result = 0;
+
+       SUPPLICANT_DBG("Country setting result");
+
+       if (!user_data)
                return;
 
-       eap_value = g_ascii_strup(ssid->eap, -1);
+       if (error) {
+               SUPPLICANT_DBG("Country setting failure %s", error);
+               result = -EINVAL;
+       }
 
-       supplicant_dbus_dict_append_basic(dict, "eap",
-                                               DBUS_TYPE_STRING,
-                                               &eap_value);
-       supplicant_dbus_dict_append_basic(dict, "identity",
-                                               DBUS_TYPE_STRING,
-                                               &ssid->identity);
+       if (regdom->callback)
+               regdom->callback(result, regdom->alpha2,
+                                       (void *) regdom->user_data);
 
-       g_free(eap_value);
+       g_free(regdom);
 }
 
-static void add_network_security_ciphers(DBusMessageIter *dict,
-                                               GSupplicantSSID *ssid)
+static void country_params(DBusMessageIter *iter, void *user_data)
 {
-       unsigned int p_cipher, g_cipher, i;
-       char *pairwise, *group;
-       char *pair_ciphers[4];
-       char *group_ciphers[5];
+       struct supplicant_regdom *regdom = user_data;
 
-       p_cipher = ssid->pairwise_cipher;
-       g_cipher = ssid->group_cipher;
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+                                                       &regdom->alpha2);
+}
 
-       if (p_cipher == 0 && g_cipher == 0)
-               return;
+int g_supplicant_set_country(const char *alpha2,
+                               GSupplicantCountryCallback callback,
+                                       const void *user_data)
+{
+       struct supplicant_regdom *regdom;
+       int ret;
 
-       i = 0;
+       SUPPLICANT_DBG("Country setting %s", alpha2);
 
-       if (p_cipher & G_SUPPLICANT_PAIRWISE_CCMP)
-               pair_ciphers[i++] = "CCMP";
+       if (!system_available)
+               return -EFAULT;
 
-       if (p_cipher & G_SUPPLICANT_PAIRWISE_TKIP)
-               pair_ciphers[i++] = "TKIP";
+       regdom = dbus_malloc0(sizeof(*regdom));
+       if (!regdom)
+               return -ENOMEM;
 
-       if (p_cipher & G_SUPPLICANT_PAIRWISE_NONE)
-               pair_ciphers[i++] = "NONE";
+       regdom->callback = callback;
+       regdom->alpha2 = alpha2;
+       regdom->user_data = user_data;
 
-       pair_ciphers[i] = NULL;
+       ret =  supplicant_dbus_property_set(SUPPLICANT_PATH, SUPPLICANT_INTERFACE,
+                                       "Country", DBUS_TYPE_STRING_AS_STRING,
+                                       country_params, country_result,
+                                       regdom, NULL);
+       if (ret < 0) {
+               dbus_free(regdom);
+               SUPPLICANT_DBG("Unable to set Country configuration");
+       }
+       return ret;
+}
 
-       i = 0;
+int g_supplicant_interface_set_country(GSupplicantInterface *interface,
+                                       GSupplicantCountryCallback callback,
+                                                       const char *alpha2,
+                                                       void *user_data)
+{
+       struct supplicant_regdom *regdom;
+       int ret;
 
-       if (g_cipher & G_SUPPLICANT_GROUP_CCMP)
-               group_ciphers[i++] = "CCMP";
+       regdom = dbus_malloc0(sizeof(*regdom));
+       if (!regdom)
+               return -ENOMEM;
 
-       if (g_cipher & G_SUPPLICANT_GROUP_TKIP)
-               group_ciphers[i++] = "TKIP";
+       regdom->callback = callback;
+       regdom->alpha2 = alpha2;
+       regdom->user_data = user_data;
 
-       if (g_cipher & G_SUPPLICANT_GROUP_WEP104)
-               group_ciphers[i++] = "WEP104";
+       ret =  supplicant_dbus_property_set(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface",
+                               "Country", DBUS_TYPE_STRING_AS_STRING,
+                               country_params, country_result,
+                                       regdom, NULL);
+       if (ret < 0) {
+               dbus_free(regdom);
+               SUPPLICANT_DBG("Unable to set Country configuration");
+       }
 
-       if (g_cipher & G_SUPPLICANT_GROUP_WEP40)
-               group_ciphers[i++] = "WEP40";
+       return ret;
+}
 
-       group_ciphers[i] = NULL;
+bool g_supplicant_interface_has_p2p(GSupplicantInterface *interface)
+{
+       if (!interface)
+               return false;
 
-       pairwise = g_strjoinv(" ", pair_ciphers);
-       group = g_strjoinv(" ", group_ciphers);
+       return interface->p2p_support;
+}
 
-       SUPPLICANT_DBG("cipher %s %s", pairwise, group);
+struct supplicant_p2p_dev_config {
+       char *device_name;
+       char *dev_type;
+};
 
-       supplicant_dbus_dict_append_basic(dict, "pairwise",
-                                               DBUS_TYPE_STRING,
-                                               &pairwise);
-       supplicant_dbus_dict_append_basic(dict, "group",
-                                               DBUS_TYPE_STRING,
-                                               &group);
+static void p2p_device_config_result(const char *error,
+                                       DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_p2p_dev_config *config = user_data;
 
-       g_free(pairwise);
-       g_free(group);
+       if (error)
+               SUPPLICANT_DBG("Unable to set P2P Device configuration: %s",
+                                                                       error);
+
+       g_free(config->device_name);
+       g_free(config->dev_type);
+       dbus_free(config);
 }
 
-static void add_network_security_proto(DBusMessageIter *dict,
-                                               GSupplicantSSID *ssid)
+static int dev_type_str2bin(const char *type, unsigned char dev_type[8])
 {
-       unsigned int protocol, i;
-       char *proto;
-       char *protos[3];
+       int length, pos, end;
+       char b[3] = {};
+       char *e = NULL;
 
-       protocol = ssid->protocol;
+       end = strlen(type);
+       for (length = pos = 0; type[pos] != '\0' && length < 8; length++) {
+               if (pos+2 > end)
+                       return 0;
 
-       if (protocol == 0)
-               return;
+               b[0] = type[pos];
+               b[1] = type[pos+1];
 
-       i = 0;
+               dev_type[length] = strtol(b, &e, 16);
+               if (e && *e != '\0')
+                       return 0;
 
-       if (protocol & G_SUPPLICANT_PROTO_RSN)
-               protos[i++] = "RSN";
+               pos += 2;
+       }
 
-       if (protocol & G_SUPPLICANT_PROTO_WPA)
-               protos[i++] = "WPA";
+       return 8;
+}
 
-       protos[i] = NULL;
+static void p2p_device_config_params(DBusMessageIter *iter, void *user_data)
+{
+       struct supplicant_p2p_dev_config *config = user_data;
+       DBusMessageIter dict;
 
-       proto = g_strjoinv(" ", protos);
+       supplicant_dbus_dict_open(iter, &dict);
 
-       SUPPLICANT_DBG("proto %s", proto);
+       supplicant_dbus_dict_append_basic(&dict, "DeviceName",
+                               DBUS_TYPE_STRING, &config->device_name);
 
-       supplicant_dbus_dict_append_basic(dict, "proto",
-                                               DBUS_TYPE_STRING,
-                                               &proto);
+       if (config->dev_type) {
+               unsigned char dev_type[8] = {}, *type;
+               int len;
 
-       g_free(proto);
+               len = dev_type_str2bin(config->dev_type, dev_type);
+               if (len) {
+                       type = dev_type;
+                       supplicant_dbus_dict_append_fixed_array(&dict,
+                                       "PrimaryDeviceType",
+                                       DBUS_TYPE_BYTE, &type, len);
+               }
+       }
+
+       supplicant_dbus_dict_close(iter, &dict);
 }
 
-static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
+int g_supplicant_interface_set_p2p_device_config(GSupplicantInterface *interface,
+                                       const char *device_name,
+                                       const char *primary_dev_type)
 {
-       char *key_mgmt;
+       struct supplicant_p2p_dev_config *config;
+       int ret;
 
-       switch (ssid->security) {
-       case G_SUPPLICANT_SECURITY_UNKNOWN:
-       case G_SUPPLICANT_SECURITY_NONE:
-       case G_SUPPLICANT_SECURITY_WEP:
-               key_mgmt = "NONE";
-               add_network_security_wep(dict, ssid);
-               add_network_security_ciphers(dict, ssid);
-               break;
-       case G_SUPPLICANT_SECURITY_PSK:
-               key_mgmt = "WPA-PSK";
-               add_network_security_psk(dict, ssid);
-               add_network_security_ciphers(dict, ssid);
-               add_network_security_proto(dict, ssid);
-               break;
-       case G_SUPPLICANT_SECURITY_IEEE8021X:
-               key_mgmt = "WPA-EAP";
-               add_network_security_eap(dict, ssid);
-               add_network_security_ciphers(dict, ssid);
-               add_network_security_proto(dict, ssid);
-               break;
+       SUPPLICANT_DBG("P2P Device settings %s/%s",
+                                       device_name, primary_dev_type);
+
+       config = dbus_malloc0(sizeof(*config));
+       if (!config)
+               return -ENOMEM;
+
+       config->device_name = g_strdup(device_name);
+       config->dev_type = g_strdup(primary_dev_type);
+
+       ret = supplicant_dbus_property_set(interface->path,
+                               SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                               "P2PDeviceConfig",
+                               DBUS_TYPE_ARRAY_AS_STRING
+                               DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                               DBUS_TYPE_STRING_AS_STRING
+                               DBUS_TYPE_VARIANT_AS_STRING
+                               DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                               p2p_device_config_params,
+                               p2p_device_config_result, config, NULL);
+       if (ret < 0) {
+               g_free(config->device_name);
+               g_free(config->dev_type);
+               dbus_free(config);
+               SUPPLICANT_DBG("Unable to set P2P Device configuration");
        }
 
-       supplicant_dbus_dict_append_basic(dict, "key_mgmt",
-                               DBUS_TYPE_STRING, &key_mgmt);
+       return ret;
 }
 
-static void add_network_mode(DBusMessageIter *dict, GSupplicantSSID *ssid)
+static gboolean peer_lookup_by_identifier(gpointer key, gpointer value,
+                                                       gpointer user_data)
 {
-       dbus_uint32_t mode;
+       const GSupplicantPeer *peer = value;
+       const char *identifier = user_data;
 
-       switch (ssid->mode) {
-       case G_SUPPLICANT_MODE_UNKNOWN:
-       case G_SUPPLICANT_MODE_INFRA:
-               mode = 0;
-               break;
-       case G_SUPPLICANT_MODE_IBSS:
-               mode = 1;
-               break;
-       case G_SUPPLICANT_MODE_MASTER:
-               mode = 2;
-               break;
+       if (!g_strcmp0(identifier, peer->identifier))
+               return TRUE;
+
+       return FALSE;
+}
+
+GSupplicantPeer *g_supplicant_interface_peer_lookup(GSupplicantInterface *interface,
+                                                       const char *identifier)
+{
+       GSupplicantPeer *peer;
+
+       peer = g_hash_table_find(interface->peer_table,
+                                       peer_lookup_by_identifier,
+                                       (void *) identifier);
+       return peer;
+}
+
+static void interface_create_data_free(struct interface_create_data *data)
+{
+       g_free(data->ifname);
+       g_free(data->driver);
+       g_free(data->bridge);
+#if defined TIZEN_EXT_WIFI_MESH
+       g_free(data->parent_ifname);
+#endif
+       dbus_free(data);
+}
+
+static bool interface_exists(GSupplicantInterface *interface,
+                               const char *path)
+{
+       GSupplicantInterface *tmp;
+
+       tmp = g_hash_table_lookup(interface_table, path);
+       if (tmp && tmp == interface)
+               return true;
+
+       return false;
+}
+
+static void interface_create_property(const char *key, DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       struct interface_create_data *data = user_data;
+       GSupplicantInterface *interface = data->interface;
+
+       if (!key) {
+               if (data->callback) {
+                       data->callback(0, data->interface, data->user_data);
+#if !defined TIZEN_EXT
+                       callback_p2p_support(interface);
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+                       callback_mesh_support(interface);
+#endif
+               }
+
+               interface_create_data_free(data);
+       }
+
+       interface_property(key, iter, interface);
+}
+
+static void interface_create_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_create_data *data = user_data;
+       const char *path = NULL;
+       int err;
+
+       SUPPLICANT_DBG("");
+
+       if (error) {
+               g_warning("error %s", error);
+               err = -EIO;
+               goto done;
+       }
+
+       dbus_message_iter_get_basic(iter, &path);
+       if (!path) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       if (!system_available) {
+               err = -EFAULT;
+               goto done;
+       }
+
+       data->interface = g_hash_table_lookup(interface_table, path);
+       if (!data->interface) {
+               data->interface = interface_alloc(path);
+               if (!data->interface) {
+                       err = -ENOMEM;
+                       goto done;
+               }
+       }
+
+       err = supplicant_dbus_property_get_all(path,
+                                       SUPPLICANT_INTERFACE ".Interface",
+                                       interface_create_property, data,
+                                       NULL);
+       if (err == 0)
+               return;
+
+done:
+       if (data->callback)
+               data->callback(err, NULL, data->user_data);
+
+       interface_create_data_free(data);
+}
+
+static void interface_create_params(DBusMessageIter *iter, void *user_data)
+{
+       struct interface_create_data *data = user_data;
+       DBusMessageIter dict;
+       char *config_file = NULL;
+
+       SUPPLICANT_DBG("");
+
+       supplicant_dbus_dict_open(iter, &dict);
+
+       supplicant_dbus_dict_append_basic(&dict, "Ifname",
+                                       DBUS_TYPE_STRING, &data->ifname);
+
+       if (data->driver)
+               supplicant_dbus_dict_append_basic(&dict, "Driver",
+                                       DBUS_TYPE_STRING, &data->driver);
+
+       if (data->bridge)
+               supplicant_dbus_dict_append_basic(&dict, "BridgeIfname",
+                                       DBUS_TYPE_STRING, &data->bridge);
+
+       config_file = g_hash_table_lookup(config_file_table, data->ifname);
+       if (config_file) {
+               SUPPLICANT_DBG("[%s] ConfigFile %s", data->ifname, config_file);
+
+               supplicant_dbus_dict_append_basic(&dict, "ConfigFile",
+                                       DBUS_TYPE_STRING, &config_file);
+       }
+
+#if defined TIZEN_EXT_WIFI_MESH
+       if (data->is_mesh_interface) {
+               if (data->parent_ifname)
+                       supplicant_dbus_dict_append_basic(&dict, "ParentIfname",
+                                       DBUS_TYPE_STRING, &data->parent_ifname);
+
+               supplicant_dbus_dict_append_basic(&dict, "IsMeshInterface",
+                                       DBUS_TYPE_BOOLEAN, &data->is_mesh_interface);
+       }
+#endif
+
+       supplicant_dbus_dict_close(iter, &dict);
+}
+
+static void interface_get_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_create_data *data = user_data;
+       GSupplicantInterface *interface;
+       const char *path = NULL;
+       int err;
+
+       SUPPLICANT_DBG("");
+
+       if (error) {
+               SUPPLICANT_DBG("Interface not created yet");
+               goto create;
+       }
+
+       dbus_message_iter_get_basic(iter, &path);
+       if (!path) {
+               err = -EINVAL;
+               goto done;
+       }
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface) {
+               err = -ENOENT;
+               goto done;
+       }
+
+       if (data->callback) {
+               data->callback(0, interface, data->user_data);
+#if !defined TIZEN_EXT
+               callback_p2p_support(interface);
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+               callback_mesh_support(interface);
+#endif
+       }
+
+       interface_create_data_free(data);
+
+       return;
+
+create:
+       if (!system_available) {
+               err = -EFAULT;
+               goto done;
+       }
+
+       SUPPLICANT_DBG("Creating interface");
+
+       err = supplicant_dbus_method_call(SUPPLICANT_PATH,
+                                               SUPPLICANT_INTERFACE,
+                                               "CreateInterface",
+                                               interface_create_params,
+                                               interface_create_result, data,
+                                               NULL);
+       if (err == 0)
+               return;
+
+done:
+       if (data->callback)
+               data->callback(err, NULL, data->user_data);
+
+       interface_create_data_free(data);
+}
+
+static void interface_get_params(DBusMessageIter *iter, void *user_data)
+{
+       struct interface_create_data *data = user_data;
+
+       SUPPLICANT_DBG("");
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
+}
+
+#if defined TIZEN_EXT_WIFI_MESH
+int g_supplicant_mesh_interface_create(const char *ifname, const char *driver,
+                                               const char *bridge, const char *parent_ifname,
+                                               GSupplicantInterfaceCallback callback, void *user_data)
+{
+       struct interface_create_data *data;
+       int ret;
+
+       SUPPLICANT_DBG("ifname %s", ifname);
+
+       if (!ifname || !parent_ifname)
+               return -EINVAL;
+
+       if (!system_available)
+               return -EFAULT;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->ifname = g_strdup(ifname);
+       data->driver = g_strdup(driver);
+       data->bridge = g_strdup(bridge);
+       data->is_mesh_interface = true;
+       data->parent_ifname = g_strdup(parent_ifname);
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
+                                               SUPPLICANT_INTERFACE,
+                                               "CreateInterface",
+                                               interface_create_params,
+                                               interface_create_result, data,
+                                               NULL);
+       return ret;
+}
+
+struct interface_mesh_peer_data {
+       char *peer_address;
+       char *method;
+       GSupplicantInterface *interface;
+       GSupplicantInterfaceCallback callback;
+       void *user_data;
+};
+
+static void interface_mesh_change_peer_params(DBusMessageIter *iter,
+                                                                                  void *user_data)
+{
+       struct interface_mesh_peer_data *data = user_data;
+
+       SUPPLICANT_DBG("");
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->peer_address);
+}
+
+static void interface_mesh_change_peer_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_mesh_peer_data *data = user_data;
+       int err = 0;
+
+       SUPPLICANT_DBG("%s", data->method);
+
+       if (error) {
+               err = -EIO;
+               SUPPLICANT_DBG("error %s", error);
+       }
+
+       if (data->callback)
+               data->callback(err, data->interface, data->user_data);
+
+       g_free(data->peer_address);
+       g_free(data->method);
+       dbus_free(data);
+}
+
+int g_supplicant_interface_mesh_peer_change_status(
+                               GSupplicantInterface *interface,
+                               GSupplicantInterfaceCallback callback, const char *peer_address,
+                               const char *method, void *user_data)
+{
+       struct interface_mesh_peer_data *data;
+       int ret;
+
+       if (!peer_address)
+               return -EINVAL;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->peer_address = g_strdup(peer_address);
+       data->method = g_strdup(method);
+       data->interface = interface;
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(interface->path,
+                                               SUPPLICANT_INTERFACE ".Interface.Mesh",
+                                               method, interface_mesh_change_peer_params,
+                                               interface_mesh_change_peer_result, data, NULL);
+       if (ret < 0) {
+               g_free(data->peer_address);
+               g_free(data->method);
+               dbus_free(data);
+       }
+
+       return ret;
+}
+#endif
+
+int g_supplicant_interface_create(const char *ifname, const char *driver,
+                                       const char *bridge,
+                                       GSupplicantInterfaceCallback callback,
+                                                       void *user_data)
+{
+       struct interface_create_data *data;
+       int ret;
+
+       SUPPLICANT_DBG("ifname %s", ifname);
+
+       if (!ifname)
+               return -EINVAL;
+
+       if (!system_available)
+               return -EFAULT;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->ifname = g_strdup(ifname);
+       data->driver = g_strdup(driver);
+       data->bridge = g_strdup(bridge);
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
+                                               SUPPLICANT_INTERFACE,
+                                               "GetInterface",
+                                               interface_get_params,
+                                               interface_get_result, data,
+                                               NULL);
+       if (ret < 0)
+               interface_create_data_free(data);
+
+       return ret;
+}
+
+static void interface_remove_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_data *data = user_data;
+       int err;
+
+       if (error) {
+               err = -EIO;
+               SUPPLICANT_DBG("error: %s", error);
+               goto done;
+       }
+
+       if (!system_available) {
+               err = -EFAULT;
+               goto done;
+       }
+
+       /*
+        * The gsupplicant interface is already freed by the InterfaceRemoved
+        * signal callback. Simply invoke the interface_data callback.
+        */
+       err = 0;
+
+done:
+       g_free(data->path);
+
+       if (data->callback)
+               data->callback(err, NULL, data->user_data);
+
+       dbus_free(data);
+}
+
+
+static void interface_remove_params(DBusMessageIter *iter, void *user_data)
+{
+       struct interface_data *data = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+                                                       &data->interface->path);
+}
+
+
+int g_supplicant_interface_remove(GSupplicantInterface *interface,
+                       GSupplicantInterfaceCallback callback,
+                                                       void *user_data)
+{
+       struct interface_data *data;
+       int ret;
+
+       if (!interface)
+               return -EINVAL;
+
+       if (!system_available)
+               return -EFAULT;
+
+       g_supplicant_interface_cancel(interface);
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
+                                               SUPPLICANT_INTERFACE,
+                                               "RemoveInterface",
+                                               interface_remove_params,
+                                               interface_remove_result, data,
+                                               NULL);
+       if (ret < 0) {
+               g_free(data->path);
+               dbus_free(data);
+       }
+       return ret;
+}
+
+static void interface_scan_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_scan_data *data = user_data;
+       int err = 0;
+
+       if (error) {
+               SUPPLICANT_DBG("error %s", error);
+               err = -EIO;
+       }
+
+       /* A non ready interface cannot send/receive anything */
+       if (interface_exists(data->interface, data->path)) {
+               if (!data->interface->ready)
+                       err = -ENOLINK;
+       }
+
+       g_free(data->path);
+
+       if (err != 0) {
+               if (data->callback)
+                       data->callback(err, data->interface, data->user_data);
+       } else {
+               data->interface->scan_callback = data->callback;
+               data->interface->scan_data = data->user_data;
+       }
+
+       if (data->scan_params)
+               g_supplicant_free_scan_params(data->scan_params);
+
+       dbus_free(data);
+}
+
+static void add_scan_frequency(DBusMessageIter *iter, unsigned int freq)
+{
+       DBusMessageIter data;
+       unsigned int width = 0; /* Not used by wpa_supplicant atm */
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &data);
+
+       dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &freq);
+       dbus_message_iter_append_basic(&data, DBUS_TYPE_UINT32, &width);
+
+       dbus_message_iter_close_container(iter, &data);
+}
+
+static void add_scan_frequencies(DBusMessageIter *iter,
+                                               void *user_data)
+{
+       GSupplicantScanParams *scan_data = user_data;
+       unsigned int freq;
+       int i;
+
+       for (i = 0; i < scan_data->num_freqs; i++) {
+               freq = scan_data->freqs[i];
+               if (!freq)
+                       break;
+
+               add_scan_frequency(iter, freq);
+       }
+}
+
+static void append_ssid(DBusMessageIter *iter,
+                       const void *ssid, unsigned int len)
+{
+       DBusMessageIter array;
+
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+       DBUS_TYPE_BYTE_AS_STRING, &array);
+
+       dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+                                                               &ssid, len);
+       dbus_message_iter_close_container(iter, &array);
+}
+
+static void append_ssids(DBusMessageIter *iter, void *user_data)
+{
+       GSupplicantScanParams *scan_data = user_data;
+       GSList *list;
+
+       for (list = scan_data->ssids; list; list = list->next) {
+               struct scan_ssid *scan_ssid = list->data;
+
+               append_ssid(iter, scan_ssid->ssid, scan_ssid->ssid_len);
+       }
+}
+
+static void supplicant_add_scan_frequency(DBusMessageIter *dict,
+               supplicant_dbus_array_function function,
+                                       void *user_data)
+{
+       GSupplicantScanParams *scan_params = user_data;
+       DBusMessageIter entry, value, array;
+       const char *key = "Channels";
+
+       if (scan_params->freqs && scan_params->freqs[0] != 0) {
+               dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+                                               NULL, &entry);
+
+               dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+               dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+                                       DBUS_TYPE_ARRAY_AS_STRING
+                                       DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+                                       DBUS_TYPE_UINT32_AS_STRING
+                                       DBUS_TYPE_UINT32_AS_STRING
+                                       DBUS_STRUCT_END_CHAR_AS_STRING,
+                                       &value);
+
+               dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
+                                       DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+                                       DBUS_TYPE_UINT32_AS_STRING
+                                       DBUS_TYPE_UINT32_AS_STRING
+                                       DBUS_STRUCT_END_CHAR_AS_STRING,
+                                       &array);
+
+               if (function)
+                       function(&array, user_data);
+
+               dbus_message_iter_close_container(&value, &array);
+               dbus_message_iter_close_container(&entry, &value);
+               dbus_message_iter_close_container(dict, &entry);
+       }
+}
+
+static void interface_scan_params(DBusMessageIter *iter, void *user_data)
+{
+       DBusMessageIter dict;
+       const char *type = "passive";
+       struct interface_scan_data *data = user_data;
+
+       supplicant_dbus_dict_open(iter, &dict);
+
+       if (data && data->scan_params) {
+               type = "active";
+
+               supplicant_dbus_dict_append_basic(&dict, "Type",
+                                       DBUS_TYPE_STRING, &type);
+
+#if defined TIZEN_EXT
+               SUPPLICANT_DBG("[specific_scan] num_ssids %d", data->scan_params->num_ssids);
+               if (data->scan_params->num_ssids != 0)
+#endif
+                       supplicant_dbus_dict_append_array(&dict, "SSIDs",
+                                               DBUS_TYPE_STRING,
+                                               append_ssids,
+                                               data->scan_params);
+
+               supplicant_add_scan_frequency(&dict, add_scan_frequencies,
+                                               data->scan_params);
+       } else
+               supplicant_dbus_dict_append_basic(&dict, "Type",
+                                       DBUS_TYPE_STRING, &type);
+
+       supplicant_dbus_dict_close(iter, &dict);
+}
+
+static int interface_ready_to_scan(GSupplicantInterface *interface)
+{
+       if (!interface)
+               return -EINVAL;
+
+       if (!system_available)
+               return -EFAULT;
+
+       if (interface->scanning)
+               return -EALREADY;
+
+       switch (interface->state) {
+       case G_SUPPLICANT_STATE_AUTHENTICATING:
+       case G_SUPPLICANT_STATE_ASSOCIATING:
+       case G_SUPPLICANT_STATE_ASSOCIATED:
+       case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
+       case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
+               return -EBUSY;
+#if defined TIZEN_EXT
+       case G_SUPPLICANT_STATE_DISABLED:
+               return -ENOLINK;
+       case G_SUPPLICANT_STATE_UNKNOWN:
+#else
+       case G_SUPPLICANT_STATE_UNKNOWN:
+       case G_SUPPLICANT_STATE_DISABLED:
+#endif
+       case G_SUPPLICANT_STATE_DISCONNECTED:
+       case G_SUPPLICANT_STATE_INACTIVE:
+       case G_SUPPLICANT_STATE_SCANNING:
+       case G_SUPPLICANT_STATE_COMPLETED:
+               break;
+       }
+
+       return 0;
+}
+
+#if defined TIZEN_EXT_WIFI_MESH
+static void interface_abort_scan_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_scan_data *data = user_data;
+       int err = 0;
+
+       if (error) {
+               SUPPLICANT_DBG("error %s", error);
+               err = -EIO;
+       }
+
+       g_free(data->path);
+
+               if (data->callback)
+                       data->callback(err, data->interface, data->user_data);
+
+       dbus_free(data);
+}
+
+int g_supplicant_interface_abort_scan(GSupplicantInterface *interface,
+                               GSupplicantInterfaceCallback callback, void *user_data)
+{
+       struct interface_scan_data *data;
+       int ret;
+
+       if (!interface->scanning)
+               return -EEXIST;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "AbortScan", NULL,
+                       interface_abort_scan_result, data, interface);
+
+       if (ret < 0) {
+               g_free(data->path);
+               dbus_free(data);
+       }
+
+       return ret;
+}
+#endif
+
+int g_supplicant_interface_scan(GSupplicantInterface *interface,
+                               GSupplicantScanParams *scan_data,
+                               GSupplicantInterfaceCallback callback,
+                                                       void *user_data)
+{
+       struct interface_scan_data *data;
+       int ret;
+
+       ret = interface_ready_to_scan(interface);
+       if (ret)
+               return ret;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+#if defined TIZEN_EXT
+       data->interface->scan_callback = data->callback = callback;
+       data->interface->scan_data = data->user_data = user_data;
+#else
+       data->callback = callback;
+       data->user_data = user_data;
+#endif
+       data->scan_params = scan_data;
+
+        interface->scan_callback = callback;
+        interface->scan_data = user_data;
+
+       ret = supplicant_dbus_method_call(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "Scan",
+                       interface_scan_params, interface_scan_result, data,
+                       interface);
+
+       if (ret < 0) {
+               g_free(data->path);
+               dbus_free(data);
+       }
+
+       return ret;
+}
+
+#if defined TIZEN_EXT
+static void interface_signalpoll_result(const char *error,
+                                DBusMessageIter *iter, void *user_data)
+{
+       struct interface_signalpoll_data *data = user_data;
+       int err = 0;
+       dbus_int32_t maxspeed = 0;
+       DBusMessageIter sub_iter, dict;
+
+       if (error) {
+               err = -EIO;
+               SUPPLICANT_DBG("error: %s", error);
+               goto out;
+       }
+
+       dbus_message_iter_get_arg_type(iter);
+       dbus_message_iter_recurse(iter, &sub_iter);
+       dbus_message_iter_recurse(&sub_iter, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+               DBusMessageIter entry, value;
+               const char *key;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_recurse(&entry, &value);
+
+               switch (dbus_message_iter_get_arg_type(&value)) {
+               case DBUS_TYPE_INT32:
+                       if (g_strcmp0(key, "linkspeed") == 0) {
+                               dbus_message_iter_get_basic(&value, &maxspeed);
+                               SUPPLICANT_DBG("linkspeed = %d", maxspeed);
+                               break;
+                       }
+               }
+               dbus_message_iter_next(&dict);
+       }
+
+out:
+       if(data->callback)
+               data->callback(err, maxspeed, data->user_data);
+
+       g_free(data->path);
+       dbus_free(data);
+}
+
+int g_supplicant_interface_signalpoll(GSupplicantInterface *interface,
+                               GSupplicantMaxSpeedCallback callback,
+                               void *user_data)
+{
+       struct interface_signalpoll_data *data;
+       int ret;
+
+       if (!interface)
+               return -EINVAL;
+
+       if (!system_available)
+               return -EFAULT;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "SignalPoll",
+                       NULL, interface_signalpoll_result, data,
+                       interface);
+
+       if (ret < 0) {
+               g_free(data->path);
+               dbus_free(data);
+       }
+
+       return ret;
+}
+#endif
+
+static int parse_supplicant_error(DBusMessageIter *iter)
+{
+       int err = -ECONNABORTED;
+       char *key;
+
+       if (!iter)
+               return err;
+
+       /* If the given passphrase is malformed wpa_s returns
+        * "invalid message format" but this error should be interpreted as
+        * invalid-key.
+        */
+       while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
+               dbus_message_iter_get_basic(iter, &key);
+               if (strncmp(key, "psk", 3) == 0 ||
+                               strncmp(key, "wep_key", 7) == 0 ||
+                               strcmp(key, "invalid message format") == 0) {
+                       err = -ENOKEY;
+                       break;
+               }
+               dbus_message_iter_next(iter);
+       }
+
+       return err;
+}
+
+static void interface_select_network_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_connect_data *data = user_data;
+       int err;
+
+       SUPPLICANT_DBG("");
+
+       err = 0;
+       if (error) {
+#if defined TIZEN_EXT
+               SUPPLICANT_DBG("SelectNetwork errorFreq %s", error);
+#else
+               SUPPLICANT_DBG("SelectNetwork error %s", error);
+#endif
+               err = parse_supplicant_error(iter);
+       }
+
+       g_free(data->path);
+
+       if (data->callback)
+               data->callback(err, data->interface, data->user_data);
+
+#if defined TIZEN_EXT
+       g_free(data->ssid->ssid);
+       g_free((char *)data->ssid->passphrase);
+#endif
+       g_free(data->ssid);
+       dbus_free(data);
+}
+
+static void interface_select_network_params(DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       struct interface_connect_data *data = user_data;
+       GSupplicantInterface *interface = data->interface;
+#if defined TIZEN_EXT
+       GSupplicantSSID *ssid = data->ssid;
+#endif
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+                                       &interface->network_path);
+#if defined TIZEN_EXT
+       if (!ssid->bssid_for_connect_len)
+               dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
+#endif
+}
+
+static void interface_add_network_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_connect_data *data = user_data;
+       GSupplicantInterface *interface = data->interface;
+       const char *path;
+       int err;
+
+       if (error)
+               goto error;
+
+       dbus_message_iter_get_basic(iter, &path);
+       if (!path)
+               goto error;
+
+       SUPPLICANT_DBG("PATH: %s", path);
+
+#if defined TIZEN_EXT
+       if (interface->network_path)
+               g_free(interface->network_path);
+#endif
+       interface->network_path = g_strdup(path);
+
+       store_network_information(interface, data->ssid);
+
+#if defined TIZEN_EXT
+       SUPPLICANT_DBG(".Interface.SelectNetworkFreq");
+       GSupplicantSSID *ssid = data->ssid;
+
+       if (!ssid->bssid_for_connect_len)
+               supplicant_dbus_method_call(data->interface->path,
+                               SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq",
+                               interface_select_network_params,
+                               interface_select_network_result, data,
+                               interface);
+       else
+               supplicant_dbus_method_call(data->interface->path,
+                               SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
+                               interface_select_network_params,
+                               interface_select_network_result, data,
+                               interface);
+#else
+       supplicant_dbus_method_call(data->interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
+                       interface_select_network_params,
+                       interface_select_network_result, data,
+                       interface);
+#endif
+
+       return;
+
+error:
+       SUPPLICANT_DBG("AddNetwork error %s", error);
+
+       if (interface_exists(data->interface, data->interface->path)) {
+               err = parse_supplicant_error(iter);
+               if (data->callback)
+                       data->callback(err, data->interface, data->user_data);
+
+               g_free(interface->network_path);
+               interface->network_path = NULL;
+       }
+
+       g_free(data->path);
+#if defined TIZEN_EXT
+       g_free(data->ssid->ssid);
+       g_free((char *)data->ssid->passphrase);
+#endif
+       g_free(data->ssid);
+       g_free(data);
+}
+
+static void add_network_security_none(DBusMessageIter *dict)
+{
+       const char *auth_alg = "OPEN";
+
+       supplicant_dbus_dict_append_basic(dict, "auth_alg",
+                                       DBUS_TYPE_STRING, &auth_alg);
+}
+
+static void add_network_security_wep(DBusMessageIter *dict,
+                                       GSupplicantSSID *ssid)
+{
+       const char *auth_alg = "OPEN SHARED";
+       dbus_uint32_t key_index = 0;
+
+       supplicant_dbus_dict_append_basic(dict, "auth_alg",
+                                       DBUS_TYPE_STRING, &auth_alg);
+
+       if (ssid->passphrase) {
+               int size = strlen(ssid->passphrase);
+               if (size == 10 || size == 26) {
+                       unsigned char *key = g_try_malloc(13);
+                       char tmp[3];
+                       int i;
+
+                       memset(tmp, 0, sizeof(tmp));
+                       if (!key)
+                               size = 0;
+
+                       for (i = 0; i < size / 2; i++) {
+                               memcpy(tmp, ssid->passphrase + (i * 2), 2);
+                               key[i] = (unsigned char) strtol(tmp, NULL, 16);
+                       }
+
+                       supplicant_dbus_dict_append_fixed_array(dict,
+                                                       "wep_key0",
+                                                       DBUS_TYPE_BYTE,
+                                                       &key, size / 2);
+                       g_free(key);
+               } else if (size == 5 || size == 13) {
+                       unsigned char *key = g_try_malloc(13);
+                       int i;
+
+                       if (!key)
+                               size = 0;
+
+                       for (i = 0; i < size; i++)
+                               key[i] = (unsigned char) ssid->passphrase[i];
+
+                       supplicant_dbus_dict_append_fixed_array(dict,
+                                                               "wep_key0",
+                                                               DBUS_TYPE_BYTE,
+                                                               &key, size);
+                       g_free(key);
+               } else
+                       supplicant_dbus_dict_append_basic(dict,
+                                                       "wep_key0",
+                                                       DBUS_TYPE_STRING,
+                                                       &ssid->passphrase);
+
+               supplicant_dbus_dict_append_basic(dict, "wep_tx_keyidx",
+                                       DBUS_TYPE_UINT32, &key_index);
+       }
+}
+
+static dbus_bool_t is_psk_raw_key(const char *psk)
+{
+       int i;
+
+       /* A raw key is always 64 bytes length... */
+       if (strlen(psk) != 64)
+               return FALSE;
+
+       /* ... and its content is in hex representation */
+       for (i = 0; i < 64; i++)
+               if (!isxdigit((unsigned char) psk[i]))
+                       return FALSE;
+
+       return TRUE;
+}
+
+static unsigned char hexchar2bin(char c)
+{
+       if ((c >= '0') && (c <= '9'))
+               return c - '0';
+       else if ((c >= 'A') && (c <= 'F'))
+               return c - 'A' + 10;
+       else if ((c >= 'a') && (c <= 'f'))
+               return c - 'a' + 10;
+       else
+               return c;
+}
+
+static void hexstring2bin(const char *string, unsigned char *data,
+                               size_t data_len)
+{
+       size_t i;
+
+       for (i = 0; i < data_len; i++)
+               data[i] = (hexchar2bin(string[i * 2 + 0]) << 4 |
+                          hexchar2bin(string[i * 2 + 1]) << 0);
+}
+
+static void add_network_security_psk(DBusMessageIter *dict,
+                                       GSupplicantSSID *ssid)
+{
+       if (ssid->passphrase && strlen(ssid->passphrase) > 0) {
+               const char *key = "psk";
+
+               if (is_psk_raw_key(ssid->passphrase)) {
+                       unsigned char data[32];
+                       unsigned char *datap = data;
+
+                       /* The above pointer alias is required by D-Bus because
+                        * with D-Bus and GCC, non-heap-allocated arrays cannot
+                        * be passed directly by their base pointer. */
+
+                       hexstring2bin(ssid->passphrase, datap, sizeof(data));
+
+                       supplicant_dbus_dict_append_fixed_array(dict,
+                                                       key, DBUS_TYPE_BYTE,
+                                                       &datap, sizeof(data));
+               } else
+                       supplicant_dbus_dict_append_basic(dict,
+                                                       key, DBUS_TYPE_STRING,
+                                                       &ssid->passphrase);
+       }
+}
+
+static void add_network_security_tls(DBusMessageIter *dict,
+                                       GSupplicantSSID *ssid)
+{
+       /*
+        * For TLS, we at least need:
+        *              The client certificate
+        *              The client private key file
+        *              The client private key file password
+        *
+        * The Authority certificate is optional.
+        */
+       if (!ssid->client_cert_path)
+               return;
+
+       if (!ssid->private_key_path)
+               return;
+
+#if !defined TIZEN_EXT
+       if (!ssid->private_key_passphrase)
+               return;
+#endif
+
+       if (ssid->ca_cert_path)
+               supplicant_dbus_dict_append_basic(dict, "ca_cert",
+                                       DBUS_TYPE_STRING, &ssid->ca_cert_path);
+
+       supplicant_dbus_dict_append_basic(dict, "private_key",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->private_key_path);
+#if !defined TIZEN_EXT
+       supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->private_key_passphrase);
+#endif
+       supplicant_dbus_dict_append_basic(dict, "client_cert",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->client_cert_path);
+}
+
+static void add_network_security_peap(DBusMessageIter *dict,
+                                       GSupplicantSSID *ssid)
+{
+       char *phase2_auth;
+
+       /*
+        * For PEAP/TTLS, we at least need
+        *              The authority certificate
+        *              The 2nd phase authentication method
+        *              The 2nd phase passphrase
+        *
+        * The Client certificate is optional although strongly recommended
+        * When setting it, we need in addition
+        *              The Client private key file
+        *              The Client private key file password
+        */
+       if (!ssid->passphrase)
+               return;
+
+       if (!ssid->phase2_auth)
+               return;
+
+       if (ssid->client_cert_path) {
+               if (!ssid->private_key_path)
+                       return;
+
+#if !defined TIZEN_EXT
+               if (!ssid->private_key_passphrase)
+                       return;
+#endif
+
+               supplicant_dbus_dict_append_basic(dict, "client_cert",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->client_cert_path);
+
+               supplicant_dbus_dict_append_basic(dict, "private_key",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->private_key_path);
+
+#if !defined TIZEN_EXT
+               supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->private_key_passphrase);
+#endif
+
+       }
+
+       if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) {
+               phase2_auth = g_strdup_printf("autheap=%s",
+                                       ssid->phase2_auth + strlen("EAP-"));
+       } else
+               phase2_auth = g_strdup_printf("auth=%s", ssid->phase2_auth);
+
+       supplicant_dbus_dict_append_basic(dict, "password",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->passphrase);
+
+       if (ssid->ca_cert_path)
+               supplicant_dbus_dict_append_basic(dict, "ca_cert",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->ca_cert_path);
+
+       supplicant_dbus_dict_append_basic(dict, "phase2",
+                                               DBUS_TYPE_STRING,
+                                               &phase2_auth);
+
+       g_free(phase2_auth);
+}
+
+#if defined TIZEN_EXT
+static void add_network_security_aka_sim(DBusMessageIter *dict,
+                                       GSupplicantSSID *ssid)
+{
+       if (!ssid->passphrase)
+               return;
+
+       supplicant_dbus_dict_append_basic(dict, "password",
+                       DBUS_TYPE_STRING,
+                       &ssid->passphrase);
+}
+
+static void add_network_security_fast(DBusMessageIter *dict,
+               GSupplicantSSID *ssid)
+{
+       /*
+        * For FAST, we at least need:
+        *              id / password
+        *              phase1 (provisiong information)
+        *              pac_file
+        */
+
+       /* Allow provisioing both authenticated and unauthenticated */
+       const char *phase1 = "fast_provisioning=2";
+       supplicant_dbus_dict_append_basic(dict, "phase1",
+                       DBUS_TYPE_STRING,
+                       &phase1);
+
+       SUPPLICANT_DBG("pac_file [%s]", ssid->pac_file);
+       if(ssid->pac_file)
+               supplicant_dbus_dict_append_basic(dict, "pac_file",
+                               DBUS_TYPE_STRING,
+                               &ssid->pac_file);
+
+       supplicant_dbus_dict_append_basic(dict, "password",
+                       DBUS_TYPE_STRING,
+                       &ssid->passphrase);
+}
+#endif
+
+static void add_network_security_eap(DBusMessageIter *dict,
+                                       GSupplicantSSID *ssid)
+{
+       char *eap_value;
+
+#if defined TIZEN_EXT
+       if (!ssid->eap)
+#else
+       if (!ssid->eap || !ssid->identity)
+#endif
+               return;
+
+       if (g_strcmp0(ssid->eap, "tls") == 0) {
+               add_network_security_tls(dict, ssid);
+       } else if (g_strcmp0(ssid->eap, "peap") == 0 ||
+                               g_strcmp0(ssid->eap, "ttls") == 0) {
+#if defined TIZEN_EXT
+               if (!ssid->identity)
+                       return;
+#endif
+               add_network_security_peap(dict, ssid);
+
+#if defined TIZEN_EXT
+       } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
+                       g_strcmp0(ssid->eap, "aka") == 0 ||
+                       g_strcmp0(ssid->eap, "aka'") == 0) {
+               add_network_security_aka_sim(dict, ssid);
+       } else if (g_strcmp0(ssid->eap, "pwd") == 0) {
+               if(!ssid->passphrase)
+                       return;
+               supplicant_dbus_dict_append_basic(dict, "password",
+                               DBUS_TYPE_STRING,
+                               &ssid->passphrase);
+       } else if (g_strcmp0(ssid->eap, "fast") == 0){
+               if (!ssid->identity || !ssid->passphrase)
+                       return;
+
+               add_network_security_fast(dict, ssid);
+#endif
+       } else
+               return;
+
+       eap_value = g_ascii_strup(ssid->eap, -1);
+
+       supplicant_dbus_dict_append_basic(dict, "eap",
+                                               DBUS_TYPE_STRING,
+                                               &eap_value);
+#if defined TIZEN_EXT
+       if (ssid->identity != NULL)
+               supplicant_dbus_dict_append_basic(dict, "identity",
+                                                       DBUS_TYPE_STRING,
+                                                       &ssid->identity);
+#else
+       supplicant_dbus_dict_append_basic(dict, "identity",
+                                               DBUS_TYPE_STRING,
+                                               &ssid->identity);
+#endif
+       if(ssid->anonymous_identity)
+               supplicant_dbus_dict_append_basic(dict, "anonymous_identity",
+                                                    DBUS_TYPE_STRING,
+                                                    &ssid->anonymous_identity);
+
+       if(ssid->subject_match)
+               supplicant_dbus_dict_append_basic(dict, "subject_match",
+                                                    DBUS_TYPE_STRING,
+                                                    &ssid->subject_match);
+
+       if(ssid->altsubject_match)
+               supplicant_dbus_dict_append_basic(dict, "altsubject_match",
+                                                    DBUS_TYPE_STRING,
+                                                    &ssid->altsubject_match);
+
+       if(ssid->domain_suffix_match)
+               supplicant_dbus_dict_append_basic(dict, "domain_suffix_match",
+                                                    DBUS_TYPE_STRING,
+                                                    &ssid->domain_suffix_match);
+
+       if(ssid->domain_match)
+               supplicant_dbus_dict_append_basic(dict, "domain_match",
+                                                    DBUS_TYPE_STRING,
+                                                    &ssid->domain_match);
+
+       g_free(eap_value);
+}
+
+static void add_network_security_ciphers(DBusMessageIter *dict,
+                                               GSupplicantSSID *ssid)
+{
+       unsigned int p_cipher, g_cipher, i;
+       char *pairwise, *group;
+       char *pair_ciphers[4];
+       char *group_ciphers[5];
+
+       p_cipher = ssid->pairwise_cipher;
+       g_cipher = ssid->group_cipher;
+
+       if (p_cipher == 0 && g_cipher == 0)
+               return;
+
+       i = 0;
+
+       if (p_cipher & G_SUPPLICANT_PAIRWISE_CCMP)
+               pair_ciphers[i++] = "CCMP";
+
+       if (p_cipher & G_SUPPLICANT_PAIRWISE_TKIP)
+               pair_ciphers[i++] = "TKIP";
+
+       if (p_cipher & G_SUPPLICANT_PAIRWISE_NONE)
+               pair_ciphers[i++] = "NONE";
+
+       pair_ciphers[i] = NULL;
+
+       i = 0;
+
+       if (g_cipher & G_SUPPLICANT_GROUP_CCMP)
+               group_ciphers[i++] = "CCMP";
+
+       if (g_cipher & G_SUPPLICANT_GROUP_TKIP)
+               group_ciphers[i++] = "TKIP";
+
+       if (g_cipher & G_SUPPLICANT_GROUP_WEP104)
+               group_ciphers[i++] = "WEP104";
+
+       if (g_cipher & G_SUPPLICANT_GROUP_WEP40)
+               group_ciphers[i++] = "WEP40";
+
+       group_ciphers[i] = NULL;
+
+       pairwise = g_strjoinv(" ", pair_ciphers);
+       group = g_strjoinv(" ", group_ciphers);
+
+       SUPPLICANT_DBG("cipher %s %s", pairwise, group);
+
+       supplicant_dbus_dict_append_basic(dict, "pairwise",
+                                               DBUS_TYPE_STRING,
+                                               &pairwise);
+       supplicant_dbus_dict_append_basic(dict, "group",
+                                               DBUS_TYPE_STRING,
+                                               &group);
+
+       g_free(pairwise);
+       g_free(group);
+}
+
+static void add_network_security_proto(DBusMessageIter *dict,
+                                               GSupplicantSSID *ssid)
+{
+       unsigned int protocol, i;
+       char *proto;
+       char *protos[3];
+
+       protocol = ssid->protocol;
+
+       if (protocol == 0)
+               return;
+
+       i = 0;
+
+       if (protocol & G_SUPPLICANT_PROTO_RSN)
+               protos[i++] = "RSN";
+
+       if (protocol & G_SUPPLICANT_PROTO_WPA)
+               protos[i++] = "WPA";
+
+       protos[i] = NULL;
+
+       proto = g_strjoinv(" ", protos);
+
+       SUPPLICANT_DBG("proto %s", proto);
+
+       supplicant_dbus_dict_append_basic(dict, "proto",
+                                               DBUS_TYPE_STRING,
+                                               &proto);
+
+       g_free(proto);
+}
+
+#if defined TIZEN_EXT
+static void add_network_ieee80211w(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+       if (ssid->security != G_SUPPLICANT_SECURITY_SAE)
+               return;
+
+       supplicant_dbus_dict_append_basic(dict, "ieee80211w", DBUS_TYPE_UINT32,
+                                         &ssid->ieee80211w);
+}
+#endif
+
+static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+       char *key_mgmt;
+
+       switch (ssid->security) {
+       case G_SUPPLICANT_SECURITY_NONE:
+               key_mgmt = "NONE";
+               add_network_security_none(dict);
+               add_network_security_ciphers(dict, ssid);
+               break;
+       case G_SUPPLICANT_SECURITY_UNKNOWN:
+       case G_SUPPLICANT_SECURITY_WEP:
+               key_mgmt = "NONE";
+               add_network_security_wep(dict, ssid);
+               add_network_security_ciphers(dict, ssid);
+               break;
+       case G_SUPPLICANT_SECURITY_PSK:
+               key_mgmt = "WPA-PSK";
+               add_network_security_psk(dict, ssid);
+               add_network_security_ciphers(dict, ssid);
+               add_network_security_proto(dict, ssid);
+               break;
+       case G_SUPPLICANT_SECURITY_IEEE8021X:
+               key_mgmt = "WPA-EAP";
+               add_network_security_eap(dict, ssid);
+               add_network_security_ciphers(dict, ssid);
+               add_network_security_proto(dict, ssid);
+               break;
+#if defined TIZEN_EXT
+       case G_SUPPLICANT_SECURITY_FT_PSK:
+               key_mgmt = "FT-PSK";
+               add_network_security_psk(dict, ssid);
+               add_network_security_ciphers(dict, ssid);
+               add_network_security_proto(dict, ssid);
+               break;
+       case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
+               key_mgmt = "FT-EAP";
+               add_network_security_eap(dict, ssid);
+               add_network_security_ciphers(dict, ssid);
+               add_network_security_proto(dict, ssid);
+               break;
+       case G_SUPPLICANT_SECURITY_SAE:
+               key_mgmt = "SAE";
+               add_network_security_psk(dict, ssid);
+               break;
+#endif
+       }
+
+       supplicant_dbus_dict_append_basic(dict, "key_mgmt",
+                               DBUS_TYPE_STRING, &key_mgmt);
+}
+
+static void add_network_mode(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+       dbus_uint32_t mode;
+
+       switch (ssid->mode) {
+       case G_SUPPLICANT_MODE_UNKNOWN:
+       case G_SUPPLICANT_MODE_INFRA:
+               mode = 0;
+               break;
+       case G_SUPPLICANT_MODE_IBSS:
+               mode = 1;
+               break;
+       case G_SUPPLICANT_MODE_MASTER:
+               mode = 2;
+               break;
+#if defined TIZEN_EXT_WIFI_MESH
+       case G_SUPPLICANT_MODE_MESH:
+               mode = 5;
+               break;
+#endif
+       }
+
+       supplicant_dbus_dict_append_basic(dict, "mode",
+                               DBUS_TYPE_UINT32, &mode);
+}
+
+static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
+{
+       DBusMessageIter dict;
+       struct interface_connect_data *data = user_data;
+       GSupplicantSSID *ssid = data->ssid;
+
+       supplicant_dbus_dict_open(iter, &dict);
+
+       if (ssid->scan_ssid)
+               supplicant_dbus_dict_append_basic(&dict, "scan_ssid",
+                                        DBUS_TYPE_UINT32, &ssid->scan_ssid);
+
+       if (ssid->freq)
+               supplicant_dbus_dict_append_basic(&dict, "frequency",
+                                        DBUS_TYPE_UINT32, &ssid->freq);
+
+       if (ssid->bgscan)
+               supplicant_dbus_dict_append_basic(&dict, "bgscan",
+                                       DBUS_TYPE_STRING, &ssid->bgscan);
+
+       add_network_mode(&dict, ssid);
+
+       add_network_security(&dict, ssid);
+
+#if defined TIZEN_EXT
+       add_network_ieee80211w(&dict, ssid);
+#endif
+
+       supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
+                                       DBUS_TYPE_BYTE, &ssid->ssid,
+                                               ssid->ssid_len);
+
+       supplicant_dbus_dict_append_basic(&dict, "ignore_broadcast_ssid",
+                                       DBUS_TYPE_INT32,
+                                       &ssid->ignore_broadcast_ssid);
+
+#if defined TIZEN_EXT
+       if (ssid->bssid) {
+               char *bssid = NULL;
+               bssid = g_try_malloc0(18);
+               if (bssid == NULL) {
+                       SUPPLICANT_DBG("memory allocation error");
+                       supplicant_dbus_dict_close(iter, &dict);
+                       return;
+               }
+
+               if (ssid->bssid_for_connect_len)
+                       snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
+                                       ssid->bssid_for_connect[0], ssid->bssid_for_connect[1], ssid->bssid_for_connect[2],
+                                       ssid->bssid_for_connect[3], ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
+               else
+                       snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
+                                       ssid->bssid[0], ssid->bssid[1], ssid->bssid[2],
+                                       ssid->bssid[3], ssid->bssid[4], ssid->bssid[5]);
+
+               supplicant_dbus_dict_append_basic(&dict, "bssid",
+                                       DBUS_TYPE_STRING, &bssid);
+               g_free(bssid);
+       }
+#endif
+
+       supplicant_dbus_dict_close(iter, &dict);
+}
+
+static void interface_wps_start_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_connect_data *data = user_data;
+       int err;
+
+       SUPPLICANT_DBG("");
+
+       err = 0;
+       if (error) {
+               SUPPLICANT_DBG("error: %s", error);
+               err = parse_supplicant_error(iter);
+       }
+
+       if(data->callback)
+               data->callback(err, data->interface, data->user_data);
+
+       g_free(data->path);
+       g_free(data->ssid);
+       dbus_free(data);
+}
+
+static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
+{
+       struct interface_connect_data *data = user_data;
+       GSupplicantSSID *ssid = data->ssid;
+       const char *role = "enrollee", *type;
+       DBusMessageIter dict;
+
+       SUPPLICANT_DBG("");
+
+       supplicant_dbus_dict_open(iter, &dict);
+
+       supplicant_dbus_dict_append_basic(&dict, "Role",
+                                               DBUS_TYPE_STRING, &role);
+
+       type = "pbc";
+       if (ssid->pin_wps) {
+               type = "pin";
+               supplicant_dbus_dict_append_basic(&dict, "Pin",
+                                       DBUS_TYPE_STRING, &ssid->pin_wps);
+       }
+
+       supplicant_dbus_dict_append_basic(&dict, "Type",
+                                       DBUS_TYPE_STRING, &type);
+
+#if defined TIZEN_EXT
+       if (ssid->bssid)
+               supplicant_dbus_dict_append_fixed_array(&dict, "Bssid",
+                                               DBUS_TYPE_BYTE, &ssid->bssid, 6);
+#endif
+
+       supplicant_dbus_dict_close(iter, &dict);
+}
+
+static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
+{
+       struct interface_connect_data *data = user_data;
+
+       SUPPLICANT_DBG("");
+
+       if (error) {
+               SUPPLICANT_DBG("error: %s", error);
+               g_free(data->path);
+               g_free(data->ssid);
+               dbus_free(data);
+               return;
+       }
+#if defined TIZEN_EXT
+       GSupplicantSSID *ssid = data->ssid;
+       if (ssid->pin_wps != NULL) {
+               if (!g_utf8_validate(ssid->pin_wps, 8, NULL)) {
+                       SUPPLICANT_DBG("Invalid characters in WPS_PIN");
+                       g_free(data->ssid);
+                       dbus_free(data);
+                       return;
+               }
+       }
+#endif
+       supplicant_dbus_method_call(data->interface->path,
+                       SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
+                       interface_add_wps_params,
+                       interface_wps_start_result, data, NULL);
+}
+
+static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
+{
+       dbus_bool_t credentials = TRUE;
+
+       SUPPLICANT_DBG("");
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
+}
+
+
+#if defined TIZEN_EXT
+#define NETCONFIG_SERVICE "net.netconfig"
+#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
+#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
+
+struct dec_method_call_data {
+       struct interface_connect_data *data;
+       DBusPendingCall *pending_call;
+};
+
+static struct dec_method_call_data decrypt_request_data;
+
+static void crypt_method_call_cancel(void)
+{
+       if (decrypt_request_data.pending_call) {
+               dbus_pending_call_cancel(decrypt_request_data.pending_call);
+               dbus_pending_call_unref(decrypt_request_data.pending_call);
+               decrypt_request_data.pending_call = NULL;
+       }
+
+       g_free(decrypt_request_data.data->path);
+       g_free(decrypt_request_data.data->ssid);
+       dbus_free(decrypt_request_data.data);
+       decrypt_request_data.data = NULL;
+}
+
+static void decryption_request_reply(DBusPendingCall *call,
+                                               void *user_data)
+{
+       DBusMessage *reply;
+       DBusError error;
+       DBusMessageIter args;
+       char *out_data;
+       int ret;
+       struct interface_connect_data *data = user_data;
+
+       SUPPLICANT_DBG("");
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       dbus_error_init(&error);
+       if (dbus_set_error_from_message(&error, reply)) {
+               SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (dbus_message_iter_init(reply, &args) == FALSE) {
+               SUPPLICANT_DBG("dbus_message_iter_init() failed");
+               ret = -EINVAL;
+               goto done;
+       }
+
+       dbus_message_iter_get_basic(&args, &out_data);
+       data->ssid->passphrase = g_strdup((const gchar *)out_data);
+
+       ret = supplicant_dbus_method_call(data->interface->path,
+               SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
+               interface_add_network_params,
+               interface_add_network_result, data,
+               data->interface);
+
+done:
+       if (ret < 0) {
+               SUPPLICANT_DBG("AddNetwork failed %d", ret);
+               callback_assoc_failed(decrypt_request_data.data->user_data);
+               g_free(data->path);
+               g_free(data->ssid->ssid);
+               g_free((char *)data->ssid->passphrase);
+               g_free(data->ssid);
+               dbus_free(data);
+       }
+
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+
+       decrypt_request_data.pending_call = NULL;
+       decrypt_request_data.data = NULL;
+}
+
+static int send_decryption_request(const char *passphrase,
+                       struct interface_connect_data *data)
+{
+       DBusMessage *msg = NULL;
+       DBusPendingCall *call;
+
+       SUPPLICANT_DBG("Decryption request");
+
+       if (!passphrase) {
+               SUPPLICANT_DBG("Invalid parameter");
+               return -EINVAL;
+       }
+
+       if (!connection)
+               return -EINVAL;
+
+       msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
+                       NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase");
+       if (!msg)
+               return -EINVAL;
+
+       dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
+                                                       DBUS_TYPE_INVALID);
+
+       if (!dbus_connection_send_with_reply(connection, msg,
+                               &call, DBUS_TIMEOUT_USE_DEFAULT)) {
+               dbus_message_unref(msg);
+               return -EIO;
+       }
+
+       if (!call) {
+               dbus_message_unref(msg);
+               return -EIO;
+       }
+
+       decrypt_request_data.pending_call = call;
+       decrypt_request_data.data = data;
+
+       dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL);
+       dbus_message_unref(msg);
+
+       SUPPLICANT_DBG("Decryption request succeeded");
+
+       return 0;
+}
+#endif
+
+int g_supplicant_interface_connect(GSupplicantInterface *interface,
+                               GSupplicantSSID *ssid,
+                               GSupplicantInterfaceCallback callback,
+                                                       void *user_data)
+{
+       struct interface_connect_data *data;
+       struct interface_data *intf_data;
+       int ret = 0;
+
+       SUPPLICANT_DBG("");
+
+       if (!interface)
+               return -EINVAL;
+
+       if (!system_available)
+               return -EFAULT;
+
+       /* TODO: Check if we're already connected and switch */
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+       data->callback = callback;
+       data->ssid = ssid;
+       data->user_data = user_data;
+
+       if (ssid->use_wps) {
+               g_free(interface->wps_cred.key);
+               memset(&interface->wps_cred, 0,
+                               sizeof(struct _GSupplicantWpsCredentials));
+
+               ret = supplicant_dbus_property_set(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface.WPS",
+                       "ProcessCredentials", DBUS_TYPE_BOOLEAN_AS_STRING,
+                       wps_process_credentials, wps_start, data, interface);
+       } else {
+               /* By the time there is a request for connect and the network
+                * path is not NULL it means that connman has not removed the
+                * previous network pointer. This can happen in the case AP
+                * deauthenticated client and connman does not remove the
+                * previously connected network pointer. This causes supplicant
+                * to reallocate the memory for struct wpa_ssid again even if it
+                * is the same SSID. This causes memory usage of wpa_supplicnat
+                * to go high. The idea here is that if the previously connected
+                * network is not removed at the time of next connection attempt
+                * check if the network path is not NULL. In case it is non-NULL
+                * first remove the network and then once removal is successful, add
+                * the network.
+                */
+
+               if (interface->network_path != NULL) {
+                       g_free(data->path);
+                       dbus_free(data);
+
+                       /*
+                        * If this add network is for the same network for
+                        * which wpa_supplicant already has a profile then do
+                        * not need to add another profile. Only if the
+                        * profile that needs to get added is different from
+                        * what is there in wpa_s delete the current one. A
+                        * network is identified by its SSID, security_type
+                        * and passphrase (private passphrase in case security
+                        * type is 802.11x).
+                        */
+                       if (compare_network_parameters(interface, ssid)) {
+                               return -EALREADY;
+                       }
+
+                       intf_data = dbus_malloc0(sizeof(*intf_data));
+                       if (!intf_data)
+                               return -ENOMEM;
+
+                       intf_data->interface = interface;
+                       intf_data->path = g_strdup(interface->path);
+                       intf_data->callback = callback;
+                       intf_data->ssid = ssid;
+                       intf_data->user_data = user_data;
+                       intf_data->network_remove_in_progress = TRUE;
+                       network_remove(intf_data);
+               } else
+#if defined TIZEN_EXT
+                       if (ssid->passphrase &&
+                           g_strcmp0(ssid->passphrase, "") != 0 &&
+#if defined TIZEN_EXT_WIFI_MESH
+                           ssid->mode != G_SUPPLICANT_MODE_MESH &&
+#endif
+                           !ssid->eap) {
+                               ret = send_decryption_request(ssid->passphrase, data);
+                               if (ret < 0)
+                                       SUPPLICANT_DBG("Decryption request failed %d", ret);
+                       } else
+#endif
+                               ret = supplicant_dbus_method_call(interface->path,
+                                               SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
+                                               interface_add_network_params,
+                                               interface_add_network_result, data,
+                                               interface);
+       }
+
+       if (ret < 0) {
+               g_free(data->path);
+               dbus_free(data);
+               return ret;
+       }
+
+       return -EINPROGRESS;
+}
+
+static void network_remove_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_data *data = user_data;
+       struct interface_connect_data *connect_data;
+       int result = 0;
+
+       SUPPLICANT_DBG("");
+
+       if (error) {
+               result = -EIO;
+               SUPPLICANT_DBG("error: %s", error);
+
+               if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
+                                               error) == 0)
+                       result = -ECONNABORTED;
+       }
+
+       g_free(data->interface->network_path);
+       data->interface->network_path = NULL;
+
+       remove_network_information(data->interface);
+
+       if (data->network_remove_in_progress == TRUE) {
+               data->network_remove_in_progress = FALSE;
+               connect_data = dbus_malloc0(sizeof(*connect_data));
+               if (!connect_data)
+                       return;
+
+               connect_data->interface = data->interface;
+               connect_data->path = g_strdup(data->path);
+               connect_data->callback = data->callback;
+               connect_data->ssid = data->ssid;
+               connect_data->user_data = data->user_data;
+
+#if defined TIZEN_EXT
+               int ret;
+               if (data->ssid->passphrase && g_strcmp0(data->ssid->passphrase, "") != 0
+                       && !data->ssid->eap) {
+                       ret = send_decryption_request(data->ssid->passphrase, connect_data);
+                       if (ret < 0) {
+                               SUPPLICANT_DBG("Decryption request failed %d", ret);
+                               g_free(connect_data->ssid);
+                               g_free(connect_data->path);
+                               dbus_free(connect_data);
+                       }
+               } else
+#endif
+               supplicant_dbus_method_call(data->interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
+                       interface_add_network_params,
+                       interface_add_network_result, connect_data,
+                       connect_data->interface);
+       } else {
+               if (data->callback)
+                       data->callback(result, data->interface, data->user_data);
+       }
+       g_free(data->path);
+       dbus_free(data);
+}
+
+static void network_remove_params(DBusMessageIter *iter, void *user_data)
+{
+       struct interface_data *data = user_data;
+       const char *path = data->interface->network_path;
+
+       SUPPLICANT_DBG("path %s", path);
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static int network_remove(struct interface_data *data)
+{
+       GSupplicantInterface *interface = data->interface;
+
+       SUPPLICANT_DBG("");
+
+#if defined TIZEN_EXT
+       GSupplicantInterface *intf = NULL;
+       /*
+        * Check if 'interface' is valid
+        */
+       intf = g_hash_table_lookup(interface_table, interface->path);
+       if (intf == NULL)
+               return -EINVAL;
+#endif
+
+       return supplicant_dbus_method_call(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork",
+                       network_remove_params, network_remove_result, data,
+                       interface);
+}
+
+static void interface_disconnect_result(const char *error,
+                               DBusMessageIter *iter, void *user_data)
+{
+       struct interface_data *data = user_data;
+       int result = 0;
+
+       SUPPLICANT_DBG("");
+
+       if (error) {
+               result = -EIO;
+               SUPPLICANT_DBG("error: %s", error);
+
+               if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod",
+                                               error) == 0)
+                       result = -ECONNABORTED;
+       }
+
+       /* If we are disconnecting from previous WPS successful
+        * association. i.e.: it did not went through AddNetwork,
+        * and interface->network_path was never set. */
+       if (!data->interface->network_path) {
+               if (data->callback)
+                       data->callback(result, data->interface,
+                                                       data->user_data);
+
+               g_free(data->path);
+               dbus_free(data);
+               return;
+       }
+
+       if (result < 0 && data->callback) {
+               data->callback(result, data->interface, data->user_data);
+               data->callback = NULL;
+       }
+
+       if (result != -ECONNABORTED) {
+               if (network_remove(data) < 0) {
+                       g_free(data->path);
+                       dbus_free(data);
+               }
+       } else {
+               g_free(data->path);
+               dbus_free(data);
+       }
+}
+
+int g_supplicant_interface_disconnect(GSupplicantInterface *interface,
+                                       GSupplicantInterfaceCallback callback,
+                                                       void *user_data)
+{
+       struct interface_data *data;
+       int ret;
+
+       SUPPLICANT_DBG("");
+
+       if (!interface)
+               return -EINVAL;
+
+       if (!system_available)
+               return -EFAULT;
+#if defined TIZEN_EXT
+       if (decrypt_request_data.pending_call &&
+                       decrypt_request_data.data &&
+                       decrypt_request_data.data->user_data == user_data) {
+
+               callback_assoc_failed(decrypt_request_data.data->user_data);
+               crypt_method_call_cancel();
+
+               return 0;
+       }
+#endif
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface", "Disconnect",
+                       NULL, interface_disconnect_result, data,
+                       interface);
+
+       if (ret < 0) {
+               g_free(data->path);
+               dbus_free(data);
+       }
+
+       return ret;
+}
+
+static void interface_p2p_find_result(const char *error,
+                                       DBusMessageIter *iter, void *user_data)
+{
+       struct interface_scan_data *data = user_data;
+       int err = 0;
+
+       SUPPLICANT_DBG("error %s", error);
+
+       if (error)
+               err = -EIO;
+
+       if (interface_exists(data->interface, data->path)) {
+               if (!data->interface->ready)
+                       err = -ENOLINK;
+               if (!err)
+                       data->interface->p2p_finding = true;
        }
 
-       supplicant_dbus_dict_append_basic(dict, "mode",
-                               DBUS_TYPE_UINT32, &mode);
+       if (data->callback)
+               data->callback(err, data->interface, data->user_data);
+
+       g_free(data->path);
+       dbus_free(data);
 }
 
-static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
+static void interface_p2p_find_params(DBusMessageIter *iter, void *user_data)
 {
        DBusMessageIter dict;
-       struct interface_connect_data *data = user_data;
-       GSupplicantSSID *ssid = data->ssid;
 
        supplicant_dbus_dict_open(iter, &dict);
+       supplicant_dbus_dict_close(iter, &dict);
+}
 
-       if (ssid->scan_ssid)
-               supplicant_dbus_dict_append_basic(&dict, "scan_ssid",
-                                        DBUS_TYPE_UINT32, &ssid->scan_ssid);
+int g_supplicant_interface_p2p_find(GSupplicantInterface *interface,
+                                       GSupplicantInterfaceCallback callback,
+                                                       void *user_data)
+{
+       struct interface_scan_data *data;
+       int ret;
 
-       if (ssid->freq)
-               supplicant_dbus_dict_append_basic(&dict, "frequency",
-                                        DBUS_TYPE_UINT32, &ssid->freq);
+       if (!interface->p2p_support)
+               return -ENOTSUP;
 
-       if (ssid->bgscan != NULL)
-               supplicant_dbus_dict_append_basic(&dict, "bgscan",
-                                       DBUS_TYPE_STRING, &ssid->bgscan);
+       ret = interface_ready_to_scan(interface);
+       if (ret && ret != -EALREADY)
+               return ret;
 
-       add_network_mode(&dict, ssid);
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
 
-       add_network_security(&dict, ssid);
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+       data->callback = callback;
+       data->user_data = user_data;
 
-       supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
-                                       DBUS_TYPE_BYTE, &ssid->ssid,
-                                               ssid->ssid_len);
+       ret = supplicant_dbus_method_call(interface->path,
+                       SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Find",
+                       interface_p2p_find_params, interface_p2p_find_result,
+                       data, interface);
+       if (ret < 0) {
+               g_free(data->path);
+               dbus_free(data);
+       }
 
-       supplicant_dbus_dict_close(iter, &dict);
+       return ret;
 }
 
-static void interface_wps_start_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+bool g_supplicant_interface_is_p2p_finding(GSupplicantInterface *interface)
+{
+       if (!interface)
+               return false;
+
+       return interface->p2p_finding;
+}
+
+int g_supplicant_interface_p2p_stop_find(GSupplicantInterface *interface)
+{
+       if (!interface->p2p_finding)
+               return 0;
+
+       SUPPLICANT_DBG("");
+
+       interface->p2p_finding = false;
+
+       return supplicant_dbus_method_call(interface->path,
+               SUPPLICANT_INTERFACE ".Interface.P2PDevice", "StopFind",
+               NULL, NULL, NULL, NULL);
+}
+
+static void interface_p2p_connect_result(const char *error,
+                                       DBusMessageIter *iter, void *user_data)
 {
        struct interface_connect_data *data = user_data;
+       int err = 0;
 
        SUPPLICANT_DBG("");
-       if (error != NULL)
+
+       if (error) {
                SUPPLICANT_DBG("error: %s", error);
+               err = parse_supplicant_error(iter);
+       }
 
-       g_free(data->ssid);
-       dbus_free(data);
+       if (data->callback)
+               data->callback(err, data->interface, data->user_data);
+
+       g_free(data->path);
+       g_free(data->peer->wps_pin);
+       g_free(data->peer->path);
+       g_free(data->peer);
+       g_free(data);
 }
 
-static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
+static void interface_p2p_connect_params(DBusMessageIter *iter, void *user_data)
 {
        struct interface_connect_data *data = user_data;
-       GSupplicantSSID *ssid = data->ssid;
-       const char *role = "enrollee", *type;
+       const char *wps = "pbc";
        DBusMessageIter dict;
+       int go_intent = 7;
 
        SUPPLICANT_DBG("");
 
        supplicant_dbus_dict_open(iter, &dict);
 
-       supplicant_dbus_dict_append_basic(&dict, "Role",
-                                               DBUS_TYPE_STRING, &role);
+       if (data->peer->master)
+               go_intent = 15;
 
-       type = "pbc";
-       if (ssid->pin_wps != NULL) {
-               type = "pin";
-               supplicant_dbus_dict_append_basic(&dict, "Pin",
-                                       DBUS_TYPE_STRING, &ssid->pin_wps);
+       if (data->peer->wps_pin)
+               wps = "pin";
+
+       supplicant_dbus_dict_append_basic(&dict, "peer",
+                               DBUS_TYPE_OBJECT_PATH, &data->peer->path);
+       supplicant_dbus_dict_append_basic(&dict, "wps_method",
+                               DBUS_TYPE_STRING, &wps);
+       if (data->peer->wps_pin) {
+               supplicant_dbus_dict_append_basic(&dict, "pin",
+                               DBUS_TYPE_STRING, &data->peer->wps_pin);
        }
 
-       supplicant_dbus_dict_append_basic(&dict, "Type",
-                                       DBUS_TYPE_STRING, &type);
+       supplicant_dbus_dict_append_basic(&dict, "go_intent",
+                                       DBUS_TYPE_INT32, &go_intent);
 
        supplicant_dbus_dict_close(iter, &dict);
 }
 
-static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
+int g_supplicant_interface_p2p_connect(GSupplicantInterface *interface,
+                                       GSupplicantPeerParams *peer_params,
+                                       GSupplicantInterfaceCallback callback,
+                                       void *user_data)
 {
-       struct interface_connect_data *data = user_data;
+       struct interface_connect_data *data;
+       int ret;
 
        SUPPLICANT_DBG("");
 
-       if (error != NULL) {
-               SUPPLICANT_DBG("error: %s", error);
-               g_free(data->ssid);
+       if (!interface->p2p_support)
+               return -ENOTSUP;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
+
+       data->interface = interface;
+       data->path = g_strdup(interface->path);
+       data->peer = peer_params;
+       data->callback = callback;
+       data->user_data = user_data;
+
+       ret = supplicant_dbus_method_call(interface->path,
+               SUPPLICANT_INTERFACE ".Interface.P2PDevice", "Connect",
+               interface_p2p_connect_params, interface_p2p_connect_result,
+               data, interface);
+       if (ret < 0) {
+               g_free(data->path);
                dbus_free(data);
-               return;
+               return ret;
        }
 
-       supplicant_dbus_method_call(data->interface->path,
-                       SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
-                       interface_add_wps_params,
-                       interface_wps_start_result, data);
+       return -EINPROGRESS;
 }
 
-static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
+int g_supplicant_interface_p2p_disconnect(GSupplicantInterface *interface,
+                                       GSupplicantPeerParams *peer_params)
 {
-       dbus_bool_t credentials = TRUE;
+       GSupplicantPeer *peer;
+       int count = 0;
+       GSList *list;
 
        SUPPLICANT_DBG("");
 
-       dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
+       if (!interface->p2p_support)
+               return -ENOTSUP;
+
+       peer = g_hash_table_lookup(interface->peer_table, peer_params->path);
+       if (!peer)
+               return -ENODEV;
+
+       for (list = peer->groups; list; list = list->next, count++) {
+               const char *group_obj_path = list->data;
+               GSupplicantInterface *g_interface;
+               GSupplicantGroup *group;
+
+               group = g_hash_table_lookup(group_mapping, group_obj_path);
+               if (!group || !group->interface)
+                       continue;
+
+               g_interface = group->interface;
+               supplicant_dbus_method_call(g_interface->path,
+                               SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                               "Disconnect", NULL, NULL, NULL, g_interface);
+       }
+
+       if (count == 0 && peer->current_group_iface) {
+               supplicant_dbus_method_call(peer->current_group_iface->path,
+                               SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                               "Disconnect", NULL, NULL, NULL,
+                               peer->current_group_iface->path);
+       }
+
+       peer->current_group_iface = NULL;
+
+       return -EINPROGRESS;
 }
 
+struct p2p_service_data {
+       bool registration;
+       GSupplicantInterface *interface;
+       GSupplicantP2PServiceParams *service;
+       GSupplicantInterfaceCallback callback;
+       void *user_data;
+};
 
-int g_supplicant_interface_connect(GSupplicantInterface *interface,
-                               GSupplicantSSID *ssid,
-                               GSupplicantInterfaceCallback callback,
+static void interface_p2p_service_result(const char *error,
+                                       DBusMessageIter *iter, void *user_data)
+{
+       struct p2p_service_data *data = user_data;
+       int result = 0;
+
+       SUPPLICANT_DBG("%s result - %s", data->registration ?
+                               "Registration" : "Deletion",
+                               error ? error : "Success");
+       if (error)
+               result = -EINVAL;
+
+       if (data->callback)
+               data->callback(result, data->interface, data->user_data);
+
+       g_free(data->service->query);
+       g_free(data->service->response);
+       g_free(data->service->service);
+       g_free(data->service->wfd_ies);
+       g_free(data->service);
+       dbus_free(data);
+}
+
+static void interface_p2p_service_params(DBusMessageIter *iter,
                                                        void *user_data)
 {
-       struct interface_connect_data *data;
-       int ret;
+       struct p2p_service_data *data = user_data;
+       GSupplicantP2PServiceParams *service;
+       DBusMessageIter dict;
+       const char *type;
 
-       if (interface == NULL)
-               return -EINVAL;
+       SUPPLICANT_DBG("");
 
-       if (system_available == FALSE)
-               return -EFAULT;
+       service = data->service;
 
-       /* TODO: Check if we're already connected and switch */
+       supplicant_dbus_dict_open(iter, &dict);
+
+       if (service->query && service->response) {
+               type = "bonjour";
+               supplicant_dbus_dict_append_basic(&dict, "service_type",
+                                               DBUS_TYPE_STRING, &type);
+               supplicant_dbus_dict_append_fixed_array(&dict, "query",
+                                       DBUS_TYPE_BYTE, &service->query,
+                                       service->query_length);
+               supplicant_dbus_dict_append_fixed_array(&dict, "response",
+                                       DBUS_TYPE_BYTE, &service->response,
+                                       service->response_length);
+       } else if (service->version && service->service) {
+               type = "upnp";
+               supplicant_dbus_dict_append_basic(&dict, "service_type",
+                                               DBUS_TYPE_STRING, &type);
+               supplicant_dbus_dict_append_basic(&dict, "version",
+                                       DBUS_TYPE_INT32, &service->version);
+               supplicant_dbus_dict_append_basic(&dict, "service",
+                                       DBUS_TYPE_STRING, &service->service);
+       }
+
+       supplicant_dbus_dict_close(iter, &dict);
+}
+
+int g_supplicant_interface_p2p_add_service(GSupplicantInterface *interface,
+                               GSupplicantInterfaceCallback callback,
+                               GSupplicantP2PServiceParams *p2p_service_params,
+                               void *user_data)
+{
+       struct p2p_service_data *data;
+       int ret;
+
+       SUPPLICANT_DBG("");
+
+       if (!interface->p2p_support)
+               return -ENOTSUP;
 
        data = dbus_malloc0(sizeof(*data));
-       if (data == NULL)
+       if (!data)
                return -ENOMEM;
 
+       data->registration = true;
        data->interface = interface;
+       data->service = p2p_service_params;
        data->callback = callback;
-       data->ssid = ssid;
        data->user_data = user_data;
 
-       if (ssid->use_wps == TRUE) {
-               g_free(interface->wps_cred.key);
-               memset(&interface->wps_cred, 0,
-                               sizeof(struct _GSupplicantWpsCredentials));
-
-               ret = supplicant_dbus_property_set(interface->path,
-                       SUPPLICANT_INTERFACE ".Interface.WPS",
-                       "ProcessCredentials", DBUS_TYPE_BOOLEAN_AS_STRING,
-                       wps_process_credentials, wps_start, data);
-       } else
-               ret = supplicant_dbus_method_call(interface->path,
-                       SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
-                       interface_add_network_params,
-                       interface_add_network_result, data);
-
-       if (ret < 0)
+       ret = supplicant_dbus_method_call(interface->path,
+               SUPPLICANT_INTERFACE ".Interface.P2PDevice", "AddService",
+               interface_p2p_service_params, interface_p2p_service_result,
+               data, interface);
+       if (ret < 0) {
+               dbus_free(data);
                return ret;
+       }
 
        return -EINPROGRESS;
 }
 
-static void network_remove_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+int g_supplicant_interface_p2p_del_service(GSupplicantInterface *interface,
+                               GSupplicantP2PServiceParams *p2p_service_params)
 {
-       struct interface_data *data = user_data;
-       int result = 0;
+       struct p2p_service_data *data;
+       int ret;
 
        SUPPLICANT_DBG("");
 
-       if (error != NULL)
-               result = -EIO;
+       if (!interface->p2p_support)
+               return -ENOTSUP;
 
-       if (data->callback != NULL)
-               data->callback(result, data->interface, data->user_data);
+       data = dbus_malloc0(sizeof(*data));
+       if (!data)
+               return -ENOMEM;
 
-       dbus_free(data);
+       data->interface = interface;
+       data->service = p2p_service_params;
+
+       ret = supplicant_dbus_method_call(interface->path,
+               SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeleteService",
+               interface_p2p_service_params, interface_p2p_service_result,
+               data, interface);
+       if (ret < 0) {
+               dbus_free(data);
+               return ret;
+       }
+
+       return -EINPROGRESS;
 }
 
-static void network_remove_params(DBusMessageIter *iter, void *user_data)
+struct p2p_listen_data {
+       int period;
+       int interval;
+};
+
+static void interface_p2p_listen_params(DBusMessageIter *iter, void *user_data)
 {
-       struct interface_data *data = user_data;
-       const char *path = data->interface->network_path;
+       struct p2p_listen_data *params = user_data;
+       DBusMessageIter dict;
 
-       SUPPLICANT_DBG("path %s", path);
+       supplicant_dbus_dict_open(iter, &dict);
 
-       dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+       supplicant_dbus_dict_append_basic(&dict, "period",
+                                       DBUS_TYPE_INT32, &params->period);
+       supplicant_dbus_dict_append_basic(&dict, "interval",
+                                       DBUS_TYPE_INT32, &params->interval);
+       supplicant_dbus_dict_close(iter, &dict);
 }
 
-static int network_remove(struct interface_data *data)
+int g_supplicant_interface_p2p_listen(GSupplicantInterface *interface,
+                                               int period, int interval)
 {
-       GSupplicantInterface *interface = data->interface;
+       struct p2p_listen_data params;
 
        SUPPLICANT_DBG("");
 
+       if (!interface->p2p_support)
+               return -ENOTSUP;
+
+       params.period = period;
+       params.interval = interval;
+
        return supplicant_dbus_method_call(interface->path,
-                       SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork",
-                       network_remove_params, network_remove_result, data);
+                       SUPPLICANT_INTERFACE ".Interface.P2PDevice",
+                       "ExtendedListen", interface_p2p_listen_params,
+                       NULL, &params, NULL);
 }
 
-static void interface_disconnect_result(const char *error,
-                               DBusMessageIter *iter, void *user_data)
+static void widi_ies_params(DBusMessageIter *iter, void *user_data)
 {
-       struct interface_data *data = user_data;
+       struct p2p_service_data *data = user_data;
+       GSupplicantP2PServiceParams *service = data->service;
+       DBusMessageIter array;
 
-       SUPPLICANT_DBG("");
+       SUPPLICANT_DBG("%p - %d", service->wfd_ies, service->wfd_ies_length);
 
-       if (error != NULL && data->callback != NULL)
-               data->callback(-EIO, data->interface, data->user_data);
+       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+                                       DBUS_TYPE_BYTE_AS_STRING, &array);
 
-       /* If we are disconnecting from previous WPS successful
-        * association. i.e.: it did not went through AddNetwork,
-        * and interface->network_path was never set. */
-       if (data->interface->network_path == NULL) {
-               dbus_free(data);
-               return;
+       if (service->wfd_ies && service->wfd_ies_length > 0) {
+               dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+                               &service->wfd_ies, service->wfd_ies_length);
        }
 
-       network_remove(data);
+       dbus_message_iter_close_container(iter, &array);
 }
 
-int g_supplicant_interface_disconnect(GSupplicantInterface *interface,
+int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params,
                                        GSupplicantInterfaceCallback callback,
-                                                       void *user_data)
+                                       void *user_data)
 {
-       struct interface_data *data;
+       struct p2p_service_data *data;
+       int ret;
 
        SUPPLICANT_DBG("");
 
-       if (interface == NULL)
-               return -EINVAL;
-
-       if (system_available == FALSE)
+       if (!system_available)
                return -EFAULT;
 
        data = dbus_malloc0(sizeof(*data));
-       if (data == NULL)
+       if (!data)
                return -ENOMEM;
 
-       data->interface = interface;
+       data->service = p2p_service_params;
        data->callback = callback;
        data->user_data = user_data;
 
-       return supplicant_dbus_method_call(interface->path,
-                       SUPPLICANT_INTERFACE ".Interface", "Disconnect",
-                               NULL, interface_disconnect_result, data);
-}
+       if (p2p_service_params->wfd_ies)
+               data->registration = true;
+
+       ret = supplicant_dbus_property_set(SUPPLICANT_PATH,
+                                       SUPPLICANT_INTERFACE, "WFDIEs",
+                                       DBUS_TYPE_ARRAY_AS_STRING
+                                       DBUS_TYPE_BYTE_AS_STRING,
+                                       widi_ies_params,
+                                       interface_p2p_service_result,
+                                       data, NULL);
+       if (ret < 0 && ret != -EINPROGRESS) {
+               dbus_free(data);
+               return ret;
+       }
 
+       return -EINPROGRESS;
+}
 
 static const char *g_supplicant_rule0 = "type=signal,"
                                        "path=" DBUS_PATH_DBUS ","
@@ -3666,6 +7312,18 @@ static const char *g_supplicant_rule4 = "type=signal,"
                        "interface=" SUPPLICANT_INTERFACE ".BSS";
 static const char *g_supplicant_rule5 = "type=signal,"
                        "interface=" SUPPLICANT_INTERFACE ".Network";
+#if !defined TIZEN_EXT
+static const char *g_supplicant_rule6 = "type=signal,"
+               "interface=" SUPPLICANT_INTERFACE ".Interface.P2PDevice";
+static const char *g_supplicant_rule7 = "type=signal,"
+               "interface=" SUPPLICANT_INTERFACE ".Peer";
+static const char *g_supplicant_rule8 = "type=signal,"
+               "interface=" SUPPLICANT_INTERFACE ".Group";
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+static const char *g_supplicant_rule9 = "type=signal,"
+               "interface=" SUPPLICANT_INTERFACE ".Interface.Mesh";
+#endif
 
 static void invoke_introspect_method(void)
 {
@@ -3676,7 +7334,7 @@ static void invoke_introspect_method(void)
                                        DBUS_INTERFACE_INTROSPECTABLE,
                                        "Introspect");
 
-       if (message == NULL)
+       if (!message)
                return;
 
        dbus_message_set_no_reply(message, TRUE);
@@ -3687,11 +7345,11 @@ static void invoke_introspect_method(void)
 int g_supplicant_register(const GSupplicantCallbacks *callbacks)
 {
        connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
-       if (connection == NULL)
+       if (!connection)
                return -EIO;
 
-       if (dbus_connection_add_filter(connection,
-                               g_supplicant_filter, NULL, NULL) == FALSE) {
+       if (!dbus_connection_add_filter(connection, g_supplicant_filter,
+                                               NULL, NULL)) {
                dbus_connection_unref(connection);
                connection = NULL;
                return -EIO;
@@ -3705,6 +7363,14 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
 
        bss_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                                NULL, NULL);
+       peer_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                               NULL, NULL);
+       group_mapping = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                               NULL, NULL);
+       pending_peer_connection = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                               NULL, NULL);
+       config_file_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                               g_free, g_free);
 
        supplicant_dbus_setup(connection);
 
@@ -3714,14 +7380,27 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
        dbus_bus_add_match(connection, g_supplicant_rule3, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule4, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule5, NULL);
+#if defined TIZEN_EXT
+       dbus_bus_add_match(connection,
+                       "type=signal,interface=org.tizen.system.deviced.PowerOff,"
+                       "member=ChangeState", NULL);
+#endif
+#if !defined TIZEN_EXT
+       dbus_bus_add_match(connection, g_supplicant_rule6, NULL);
+       dbus_bus_add_match(connection, g_supplicant_rule7, NULL);
+       dbus_bus_add_match(connection, g_supplicant_rule8, NULL);
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+       dbus_bus_add_match(connection, g_supplicant_rule9, NULL);
+#endif
        dbus_connection_flush(connection);
 
        if (dbus_bus_name_has_owner(connection,
-                                       SUPPLICANT_SERVICE, NULL) == TRUE) {
+                                       SUPPLICANT_SERVICE, NULL)) {
                system_available = TRUE;
                supplicant_dbus_property_get_all(SUPPLICANT_PATH,
                                                SUPPLICANT_INTERFACE,
-                                               service_property, NULL);
+                                               service_property, NULL, NULL);
        } else
                invoke_introspect_method();
 
@@ -3747,14 +7426,22 @@ static void unregister_remove_interface(gpointer key, gpointer value,
                                        SUPPLICANT_INTERFACE,
                                        "RemoveInterface",
                                        unregister_interface_remove_params,
-                                               NULL, interface->path);
+                                       NULL, interface->path, NULL);
 }
 
 void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
 {
        SUPPLICANT_DBG("");
 
-       if (connection != NULL) {
+       if (connection) {
+#if defined TIZEN_EXT_WIFI_MESH
+               dbus_bus_remove_match(connection, g_supplicant_rule9, NULL);
+#endif
+#if !defined TIZEN_EXT
+               dbus_bus_remove_match(connection, g_supplicant_rule8, NULL);
+               dbus_bus_remove_match(connection, g_supplicant_rule7, NULL);
+               dbus_bus_remove_match(connection, g_supplicant_rule6, NULL);
+#endif
                dbus_bus_remove_match(connection, g_supplicant_rule5, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule4, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule3, NULL);
@@ -3767,22 +7454,37 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
                                                g_supplicant_filter, NULL);
        }
 
-       if (bss_mapping != NULL) {
+       if (config_file_table) {
+               g_hash_table_destroy(config_file_table);
+               config_file_table = NULL;
+       }
+
+       if (bss_mapping) {
                g_hash_table_destroy(bss_mapping);
                bss_mapping = NULL;
        }
 
-       if (system_available == TRUE)
-               callback_system_killed();
+       if (peer_mapping) {
+               g_hash_table_destroy(peer_mapping);
+               peer_mapping = NULL;
+       }
 
-       if (interface_table != NULL) {
+       if (group_mapping) {
+               g_hash_table_destroy(group_mapping);
+               group_mapping = NULL;
+       }
+
+       if (interface_table) {
                g_hash_table_foreach(interface_table,
                                        unregister_remove_interface, NULL);
                g_hash_table_destroy(interface_table);
                interface_table = NULL;
        }
 
-       if (connection != NULL) {
+       if (system_available)
+               callback_system_killed();
+
+       if (connection) {
                dbus_connection_unref(connection);
                connection = NULL;
        }