Add DPP service based on configuration file
[platform/upstream/connman.git] / gsupplicant / supplicant.c
index 5e9f509..431c6e7 100644 (file)
 #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;
@@ -92,6 +101,11 @@ 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                },
+       { "owe",                G_SUPPLICANT_KEYMGMT_OWE                },
+       { "dpp",                G_SUPPLICANT_KEYMGMT_DPP                },
+#endif
        { }
 };
 
@@ -135,6 +149,9 @@ static struct strvalmap mode_capa_map[] = {
        { "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
        { }
 };
 
@@ -156,8 +173,21 @@ struct added_network_information {
        GSupplicantSecurity security;
        char * passphrase;
        char * private_passphrase;
+#if defined TIZEN_EXT
+       char *connector;
+       char *c_sign_key;
+       char *net_access_key;
+#endif
 };
 
+#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;
@@ -192,8 +222,13 @@ struct _GSupplicantInterface {
        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 {
@@ -221,11 +256,17 @@ struct g_supplicant_bss {
 #if defined TIZEN_EXT
        dbus_bool_t ft_psk;
        dbus_bool_t ft_ieee8021x;
-       char *wifi_vsie;
-       unsigned int wifi_vsie_len;
+       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;
+       dbus_bool_t owe;
+       dbus_bool_t dpp;
+#endif
 };
 
 struct _GSupplicantNetwork {
@@ -250,8 +291,9 @@ struct _GSupplicantNetwork {
        char *identity;
        char *phase2;
        unsigned int keymgmt;
-       char *wifi_vsie;
-       unsigned int wifi_vsie_len;
+       GSList *vsie_list;
+       unsigned char country_code[COUNTRY_CODE_LENGTH];
+       GSupplicantPhy_mode phy_mode;
 #endif
 };
 
@@ -289,10 +331,23 @@ struct interface_data {
        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;
@@ -317,8 +372,24 @@ struct interface_scan_data {
        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];
@@ -347,6 +418,10 @@ static GSupplicantMode string2mode(const char *mode)
                return G_SUPPLICANT_MODE_INFRA;
        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;
 }
@@ -362,6 +437,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;
@@ -385,6 +464,12 @@ static const char *security2string(GSupplicantSecurity security)
                return "ft_psk";
        case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
                return "ft_ieee8021x";
+       case G_SUPPLICANT_SECURITY_SAE:
+               return "sae";
+       case G_SUPPLICANT_SECURITY_OWE:
+               return "owe";
+       case G_SUPPLICANT_SECURITY_DPP:
+               return "dpp";
 #endif
        }
 
@@ -425,6 +510,11 @@ static GSupplicantState string2state(const char *state)
 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;
 
@@ -443,6 +533,23 @@ static bool compare_network_parameters(GSupplicantInterface *interface,
                return FALSE;
        }
 
+#if defined TIZEN_EXT
+       if (interface->network_info.connector &&
+                       g_strcmp0(interface->network_info.connector,
+                               ssid->connector) != 0) {
+               return FALSE;
+       }
+       if (interface->network_info.c_sign_key &&
+                       g_strcmp0(interface->network_info.c_sign_key,
+                               ssid->c_sign_key) != 0) {
+               return FALSE;
+       }
+       if (interface->network_info.net_access_key &&
+                       g_strcmp0(interface->network_info.net_access_key,
+                               ssid->net_access_key) != 0) {
+               return FALSE;
+       }
+#endif
        return TRUE;
 }
 
@@ -451,9 +558,19 @@ 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);
+#if defined TIZEN_EXT
+       g_free(interface->network_info.connector);
+       g_free(interface->network_info.c_sign_key);
+       g_free(interface->network_info.net_access_key);
+#endif
        interface->network_info.ssid = NULL;
        interface->network_info.passphrase = NULL;
        interface->network_info.private_passphrase = NULL;
+#if defined TIZEN_EXT
+       interface->network_info.connector = NULL;
+       interface->network_info.c_sign_key = NULL;
+       interface->network_info.net_access_key = NULL;
+#endif
 }
 
 static int store_network_information(GSupplicantInterface * interface,
@@ -563,6 +680,27 @@ static void callback_p2p_support(GSupplicantInterface *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)
@@ -665,6 +803,30 @@ static void callback_network_associated(GSupplicantNetwork *network)
        callbacks_pointer->network_associated(network);
 }
 
+static void callback_sta_authorized(GSupplicantInterface *interface,
+                                       const char *addr)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->sta_authorized)
+               return;
+
+       callbacks_pointer->sta_authorized(interface, addr);
+}
+
+static void callback_sta_deauthorized(GSupplicantInterface *interface,
+                                       const char *addr)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->sta_deauthorized)
+               return;
+
+       callbacks_pointer->sta_deauthorized(interface, addr);
+}
+
 static void callback_peer_found(GSupplicantPeer *peer)
 {
        if (!callbacks_pointer)
@@ -808,7 +970,7 @@ static void remove_network(gpointer data)
        g_free(network->phase2);
 #endif
 #if defined TIZEN_EXT
-       g_free(network->wifi_vsie);
+       g_slist_free_full(network->vsie_list, g_free);
 #endif
 
        g_free(network);
@@ -818,9 +980,11 @@ static void remove_bss(gpointer data)
 {
        struct g_supplicant_bss *bss = data;
 
+       supplicant_dbus_property_call_cancel_all(bss);
+
        g_free(bss->path);
 #if defined TIZEN_EXT
-       g_free(bss->wifi_vsie);
+       g_slist_free_full(bss->vsie_list, g_free);
 #endif
        g_free(bss);
 }
@@ -1015,7 +1179,13 @@ static void interface_capability(const char *key, DBusMessageIter *iter,
                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));
@@ -1104,6 +1274,16 @@ const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface)
        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)
@@ -1322,6 +1502,16 @@ 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)
@@ -1410,6 +1600,15 @@ unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network)
 
        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,
@@ -1520,6 +1719,11 @@ const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
                return NULL;
 
        if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
+#if defined TIZEN_EXT
+           network->best_bss->security == G_SUPPLICANT_SECURITY_SAE ||
+           network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
+           network->best_bss->security == G_SUPPLICANT_SECURITY_DPP ||
+#endif /* TIZEN_EXT */
            network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
                unsigned int pairwise;
 
@@ -1547,6 +1751,13 @@ 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 ||
+                       network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
+                       network->best_bss->security == G_SUPPLICANT_SECURITY_DPP)
+               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 ||
@@ -1558,16 +1769,81 @@ bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network)
                return false;
 }
 
-const void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network,
-                                               unsigned int *wifi_vsie_len)
+void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network)
 {
-       if (!network) {
-               *wifi_vsie_len = 0;
+       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");
+               }
        }
 
-       *wifi_vsie_len = network->wifi_vsie_len;
-       return network->wifi_vsie;
+       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
 
@@ -1576,7 +1852,6 @@ static void merge_network(GSupplicantNetwork *network)
        GString *str;
        const char *ssid, *mode, *key_mgmt;
 #if defined TIZEN_EXT
-       GSupplicantInterface *interface;
        const char *isHS20AP;
        const char *eap, *identity, *phase2;
 #endif
@@ -1591,7 +1866,6 @@ static void merge_network(GSupplicantNetwork *network)
        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");
-       interface = network->interface;
 #endif
 
        SUPPLICANT_DBG("ssid %s mode %s", ssid, mode);
@@ -1619,6 +1893,10 @@ static void merge_network(GSupplicantNetwork *network)
                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");
@@ -1650,11 +1928,9 @@ static void merge_network(GSupplicantNetwork *network)
        } else
                network->isHS20AP = 0;
 
-       if (interface)
-               interface->network_path = g_strdup(network->path);
-
        network->group = g_strdup(group);
        callback_network_merged(network);
+       g_free(network->group);
 #endif
 
        g_free(group);
@@ -1736,7 +2012,6 @@ static void interface_network_added(DBusMessageIter *iter, void *user_data)
 static void interface_network_removed(DBusMessageIter *iter, void *user_data)
 {
        SUPPLICANT_DBG("");
-       return;
 }
 
 static char *create_name(unsigned char *ssid, int ssid_len)
@@ -1812,6 +2087,7 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        GSupplicantInterface *interface = bss->interface;
        GSupplicantNetwork *network;
        char *group;
+       bool is_new_network;
 
        group = create_group(bss);
        SUPPLICANT_DBG("New group created: %s", group);
@@ -1823,10 +2099,13 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        if (network) {
                g_free(group);
                SUPPLICANT_DBG("Network %s already exist", network->name);
+               is_new_network = false;
 
                goto done;
        }
 
+       is_new_network = true;
+
        network = g_try_new0(GSupplicantNetwork, 1);
        if (!network) {
                g_free(group);
@@ -1846,21 +2125,32 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        network->frequency = bss->frequency;
        network->best_bss = bss;
 
+       if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
+               network->wps = TRUE;
+               network->wps_capabilities = bss->wps_capabilities;
+       }
+
 #if defined TIZEN_EXT
        network->keymgmt = bss->keymgmt;
 
-       if (bss->wifi_vsie_len > 0) {
-               SUPPLICANT_DBG("vsie len: %d", bss->wifi_vsie_len);
-               network->wifi_vsie = (char *)g_try_malloc0(bss->wifi_vsie_len);
-               if(network->wifi_vsie) {
-                       network->wifi_vsie_len = bss->wifi_vsie_len;
-                       memcpy(network->wifi_vsie, bss->wifi_vsie, network->wifi_vsie_len);
-               } else {
-                       SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie");
+       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);
@@ -1880,7 +2170,10 @@ done:
        /* We update network's WPS properties if only bss provides WPS. */
        if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
                network->wps = TRUE;
-               network->wps_capabilities |= bss->wps_capabilities;
+               network->wps_capabilities = bss->wps_capabilities;
+
+               if (!is_new_network)
+                       callback_network_changed(network, "WPSCapabilities");
        }
 
        /*
@@ -2043,17 +2336,67 @@ 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;
        const unsigned char WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
-#if defined TIZEN_EXT
-       const unsigned char WIFI_OUI[] = {0x00, 0x16, 0x32};
-#endif
        unsigned char *ie, *ie_end;
        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
@@ -2067,6 +2410,7 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 #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);
@@ -2081,16 +2425,66 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
        for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
                                                        ie += ie[1] + 2) {
 #if defined TIZEN_EXT
-               if((ie[0] == VENDOR_SPECIFIC_INFO) && (memcmp(ie+2, WIFI_OUI, sizeof(WIFI_OUI)) == 0)) {
-                               SUPPLICANT_DBG("IE: match WIFI_OUI");
-                               bss->wifi_vsie = (char *)g_try_malloc0(ie[1] + 2);   // tag number size(1), tag length size(1)
-                               if (bss->wifi_vsie) {
-                                       bss->wifi_vsie_len = ie[1] + 2;
-                                       memcpy(bss->wifi_vsie, ie, bss->wifi_vsie_len);
-                               } else {
-                                       SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie");
-                               }
+               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 ||
@@ -2127,6 +2521,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)
@@ -2173,6 +2574,15 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
                bss->psk = TRUE;
 #endif
 
+#if defined TIZEN_EXT
+       if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
+               bss->sae = TRUE;
+       if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_OWE)
+               bss->owe = TRUE;
+       if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_DPP)
+               bss->dpp = TRUE;
+#endif
+
        if (bss->ieee8021x)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
        else if (bss->psk)
@@ -2182,6 +2592,12 @@ static void bss_compute_security(struct g_supplicant_bss *bss)
                bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
        else if (bss->ft_ieee8021x == TRUE)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
+       else if (bss->sae)
+               bss->security = G_SUPPLICANT_SECURITY_SAE;
+       else if (bss->owe)
+               bss->security = G_SUPPLICANT_SECURITY_OWE;
+       else if (bss->dpp)
+               bss->security = G_SUPPLICANT_SECURITY_DPP;
 #endif
        else if (bss->privacy)
                bss->security = G_SUPPLICANT_SECURITY_WEP;
@@ -2370,7 +2786,7 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter,
 
        supplicant_dbus_property_get_all(bss->path,
                                        SUPPLICANT_INTERFACE ".BSS",
-                                       bss_property, bss, NULL);
+                                       bss_property, bss, bss);
 
        bss_compute_security(bss);
        if (add_or_replace_bss_to_network(bss) < 0)
@@ -2475,6 +2891,7 @@ static void interface_bss_removed(DBusMessageIter *iter, void *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)
@@ -2488,6 +2905,7 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
        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);
@@ -2497,8 +2915,16 @@ 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)
@@ -2579,6 +3005,10 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                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;
 
@@ -3043,12 +3473,56 @@ static void signal_network_removed(const char *path, DBusMessageIter *iter)
 
        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_sta_authorized(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       const char *addr = NULL;
+
+       SUPPLICANT_DBG("");
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       dbus_message_iter_get_basic(iter, &addr);
+       if (!addr)
+               return;
+
+       callback_sta_authorized(interface, addr);
+}
+
+static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       const char *addr = NULL;
+
+       SUPPLICANT_DBG("");
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       dbus_message_iter_get_basic(iter, &addr);
+       if (!addr)
+               return;
+
+       callback_sta_deauthorized(interface, addr);
+}
 
 static void signal_bss_changed(const char *path, DBusMessageIter *iter)
 {
        GSupplicantInterface *interface;
        GSupplicantNetwork *network;
        GSupplicantSecurity old_security;
+       unsigned int old_wps_capabilities;
        struct g_supplicant_bss *bss;
 
        SUPPLICANT_DBG("");
@@ -3066,8 +3540,10 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
                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);
@@ -3075,18 +3551,18 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
        if (old_security != bss->security) {
                struct g_supplicant_bss *new_bss;
 
-               SUPPLICANT_DBG("New network security for %s", bss->ssid);
+               SUPPLICANT_DBG("New network security for %s with path %s",
+                              bss->ssid, bss->path);
 
-               /* Security change policy:
-                * - we first copy the current bss into a new one with
-                * its own pointer (path)
-                * - we remove the current bss related network which will
-                * tell the plugin about such removal. This is done due
-                * to the fact that a security change means a group change
-                * so a complete network change.
-                * (current bss becomes invalid as well)
-                * - we add the new bss: it adds new network and tell the
-                * plugin about it. */
+               /*
+                * Security change policy:
+                * - We first copy the current bss into a new one with
+                *   its own pointer (path)
+                * - Clear the old bss pointer and remove the network completely
+                *   if there are no more BSSs in the bss table.
+                * - The new bss will be added either to an existing network
+                *   or an additional network will be created
+                */
 
                new_bss = g_try_new0(struct g_supplicant_bss, 1);
                if (!new_bss)
@@ -3094,21 +3570,47 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
 
                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);
+               if (network->best_bss == bss) {
+                       network->best_bss = NULL;
+                       network->signal = BSS_UNKNOWN_STRENGTH;
+               }
+
+               g_hash_table_remove(bss_mapping, path);
+
+               g_hash_table_remove(interface->bss_mapping, path);
+               g_hash_table_remove(network->bss_table, path);
+
+               update_network_signal(network);
+
+               if (g_hash_table_size(network->bss_table) == 0)
+                       g_hash_table_remove(interface->network_table,
+                                           network->group);
 
                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
+                       /*
+                        * Prevent a memory leak on 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);
+                       SUPPLICANT_DBG("Failed to add bss %s to network table",
+                                      new_bss->path);
+                       g_free(new_bss->path);
+                       g_free(new_bss);
                }
 
                return;
        }
 
+       old_wps_capabilities = network->wps_capabilities;
+
+       if (old_wps_capabilities != bss->wps_capabilities) {
+               network->wps_capabilities = bss->wps_capabilities;
+               callback_network_changed(network, "WPSCapabilities");
+       }
+
 #if defined TIZEN_EXT
        if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
                network->wps = TRUE;
@@ -3246,7 +3748,7 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter)
 
        if (g_strcmp0(name, "success") == 0)
                interface->wps_state = G_SUPPLICANT_WPS_STATE_SUCCESS;
-       else if (g_strcmp0(name, "failed") == 0)
+       else if (g_strcmp0(name, "fail") == 0)
                interface->wps_state = G_SUPPLICANT_WPS_STATE_FAIL;
        else
                interface->wps_state = G_SUPPLICANT_WPS_STATE_UNKNOWN;
@@ -3282,56 +3784,6 @@ static void signal_power_off(const char *path, DBusMessageIter *iter)
 }
 #endif
 
-static void signal_station_connected(const char *path, DBusMessageIter *iter)
-{
-       GSupplicantInterface *interface;
-       const char *sta_mac = NULL;
-
-       SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
-
-       if (callbacks_pointer->add_station == NULL)
-               return;
-
-       if (g_strcmp0(path, "/") == 0)
-               return;
-
-       interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
-               return;
-
-       dbus_message_iter_get_basic(iter, &sta_mac);
-       if (sta_mac == NULL)
-               return;
-
-       SUPPLICANT_DBG("New station %s connected", sta_mac);
-       callbacks_pointer->add_station(sta_mac);
-}
-
-static void signal_station_disconnected(const char *path, DBusMessageIter *iter)
-{
-       GSupplicantInterface *interface;
-       const char *sta_mac = NULL;
-
-       SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH);
-
-       if (callbacks_pointer->remove_station == NULL)
-               return;
-
-       if (g_strcmp0(path, "/") == 0)
-               return;
-
-       interface = g_hash_table_lookup(interface_table, path);
-       if (interface == NULL)
-               return;
-
-       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 create_peer_identifier(GSupplicantPeer *peer)
 {
        const unsigned char test[ETH_ALEN] = {};
@@ -3873,6 +4325,214 @@ static void signal_group_peer_disconnected(const char *path, DBusMessageIter *it
        peer->connection_requested = false;
 }
 
+#if defined TIZEN_EXT_WIFI_MESH
+const void *g_supplicant_interface_get_mesh_group_ssid(
+                                                       GSupplicantInterface *interface,
+                                                       unsigned int *ssid_len)
+{
+       if (!ssid_len)
+               return NULL;
+
+       if (!interface || interface->group_info.ssid_len == 0) {
+               *ssid_len = 0;
+               return NULL;
+       }
+
+       *ssid_len = interface->group_info.ssid_len;
+       return interface->group_info.ssid;
+}
+
+int g_supplicant_mesh_get_disconnect_reason(GSupplicantInterface *interface)
+{
+       if (!interface)
+               return -EINVAL;
+
+       return interface->group_info.disconnect_reason;
+}
+
+const char *g_supplicant_mesh_peer_get_address(GSupplicantMeshPeer *mesh_peer)
+{
+       if (!mesh_peer || !mesh_peer->peer_address)
+               return NULL;
+
+       return mesh_peer->peer_address;
+}
+
+int g_supplicant_mesh_peer_get_disconnect_reason(GSupplicantMeshPeer *mesh_peer)
+{
+       if (!mesh_peer)
+               return -EINVAL;
+
+       return mesh_peer->disconnect_reason;
+}
+
+static void callback_mesh_group_started(GSupplicantInterface *interface)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->mesh_group_started)
+               return;
+
+       callbacks_pointer->mesh_group_started(interface);
+}
+
+static void callback_mesh_group_removed(GSupplicantInterface *interface)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->mesh_group_removed)
+               return;
+
+       callbacks_pointer->mesh_group_removed(interface);
+}
+
+static void mesh_group_info(const char *key, DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       GSupplicantInterface *interface = user_data;
+       if (!key)
+               return;
+
+       if (g_strcmp0(key, "SSID") == 0) {
+               DBusMessageIter array;
+               unsigned char *ssid;
+               int ssid_len;
+
+               dbus_message_iter_recurse(iter, &array);
+               dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
+
+               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 signal_mesh_group_started(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
+
+       callback_mesh_group_started(interface);
+}
+
+static void signal_mesh_group_removed(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
+
+       callback_mesh_group_removed(interface);
+}
+
+static void callback_mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->mesh_peer_connected)
+               return;
+
+       callbacks_pointer->mesh_peer_connected(mesh_peer);
+}
+
+static void callback_mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
+{
+       if (!callbacks_pointer)
+               return;
+
+       if (!callbacks_pointer->mesh_peer_disconnected)
+               return;
+
+       callbacks_pointer->mesh_peer_disconnected(mesh_peer);
+}
+
+static void mesh_peer_info(const char *key, DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       GSupplicantMeshPeer *mesh_peer = user_data;
+       if (!key)
+               return;
+
+       if (g_strcmp0(key, "PeerAddress") == 0) {
+               DBusMessageIter array;
+               unsigned char *addr;
+               int addr_len;
+
+               dbus_message_iter_recurse(iter, &array);
+               dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
+
+               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 signal_mesh_peer_connected(const char *path, DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       GSupplicantMeshPeer *mesh_peer;
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
+       mesh_peer->interface = interface;
+
+       supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
+
+       callback_mesh_peer_connected(mesh_peer);
+       g_free(mesh_peer->peer_address);
+       g_free(mesh_peer);
+}
+
+static void signal_mesh_peer_disconnected(const char *path,
+                                                               DBusMessageIter *iter)
+{
+       GSupplicantInterface *interface;
+       GSupplicantMeshPeer *mesh_peer;
+
+       interface = g_hash_table_lookup(interface_table, path);
+       if (!interface)
+               return;
+
+       mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
+       mesh_peer->interface = interface;
+
+       supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
+
+       callback_mesh_peer_disconnected(mesh_peer);
+       g_free(mesh_peer->peer_address);
+       g_free(mesh_peer);
+}
+#endif
+
 static struct {
        const char *interface;
        const char *member;
@@ -3891,6 +4551,8 @@ static struct {
        { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved",        signal_bss_removed       },
        { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded",      signal_network_added     },
        { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved",    signal_network_removed   },
+       { SUPPLICANT_INTERFACE ".Interface", "StaAuthorized",     signal_sta_authorized    },
+       { SUPPLICANT_INTERFACE ".Interface", "StaDeauthorized",   signal_sta_deauthorized  },
 
        { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed   },
 
@@ -3900,9 +4562,6 @@ static struct {
        { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
 #endif
 
-       { 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  },
 
@@ -3916,6 +4575,16 @@ static struct {
 
        { 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
 
        { }
 };
@@ -4194,6 +4863,9 @@ 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);
 }
 
@@ -4221,6 +4893,9 @@ static void interface_create_property(const char *key, DBusMessageIter *iter,
 #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);
@@ -4307,6 +4982,17 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data)
                                        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);
 }
 
@@ -4342,6 +5028,9 @@ static void interface_get_result(const char *error,
 #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);
@@ -4381,6 +5070,117 @@ static void interface_get_params(DBusMessageIter *iter, void *user_data)
        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,
@@ -4638,14 +5438,16 @@ static void interface_scan_params(DBusMessageIter *iter, void *user_data)
                                        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)
+               SUPPLICANT_DBG("[specific_scan] num_ssids %d",
+                              data->scan_params->num_ssids);
 #endif
-                       supplicant_dbus_dict_append_array(&dict, "SSIDs",
-                                               DBUS_TYPE_STRING,
-                                               append_ssids,
-                                               data->scan_params);
 
+               if (data->scan_params->ssids) {
+                       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
@@ -4688,20 +5490,169 @@ static int interface_ready_to_scan(GSupplicantInterface *interface)
                break;
        }
 
-       return 0;
+       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;
+       unsigned char strength = 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;
+                       }
+               case DBUS_TYPE_BYTE:
+                       if (g_strcmp0(key, "rssi") == 0) {
+                               dbus_message_iter_get_basic(&value, &strength);
+                               SUPPLICANT_DBG("Strength = %d", strength);
+                               break;
+                       }
+               }
+               dbus_message_iter_next(&dict);
+       }
+
+out:
+       if(data->callback)
+               data->callback(err, maxspeed, strength, data->user_data);
+
+       g_free(data->path);
+       dbus_free(data);
 }
 
-int g_supplicant_interface_scan(GSupplicantInterface *interface,
-                               GSupplicantScanParams *scan_data,
-                               GSupplicantInterfaceCallback callback,
-                                                       void *user_data)
+int g_supplicant_interface_signalpoll(GSupplicantInterface *interface,
+                               GSupplicantMaxSpeedCallback callback,
+                               void *user_data)
 {
-       struct interface_scan_data *data;
+       struct interface_signalpoll_data *data;
        int ret;
 
-       ret = interface_ready_to_scan(interface);
-       if (ret)
-               return ret;
+       if (!interface)
+               return -EINVAL;
+
+       if (!system_available)
+               return -EFAULT;
 
        data = dbus_malloc0(sizeof(*data));
        if (!data)
@@ -4709,21 +5660,12 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface,
 
        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,
+                       SUPPLICANT_INTERFACE ".Interface", "SignalPoll",
+                       NULL, interface_signalpoll_result, data,
                        interface);
 
        if (ret < 0) {
@@ -4733,6 +5675,7 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface,
 
        return ret;
 }
+#endif
 
 static int parse_supplicant_error(DBusMessageIter *iter)
 {
@@ -4783,6 +5726,13 @@ static void interface_select_network_result(const char *error,
        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);
+       g_free((char *)data->ssid->connector);
+       g_free((char *)data->ssid->c_sign_key);
+       g_free((char *)data->ssid->net_access_key);
+#endif
        g_free(data->ssid);
        dbus_free(data);
 }
@@ -4799,7 +5749,8 @@ static void interface_select_network_params(DBusMessageIter *iter,
        dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
                                        &interface->network_path);
 #if defined TIZEN_EXT
-       dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
+       if (!ssid->bssid_for_connect_len)
+               dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
 #endif
 }
 
@@ -4820,20 +5771,30 @@ static void interface_add_network_result(const char *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");
-#endif
+       GSupplicantSSID *ssid = data->ssid;
 
-#if defined TIZEN_EXT
-       supplicant_dbus_method_call(data->interface->path,
-                       SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq",
-                       interface_select_network_params,
-                       interface_select_network_result, data,
-                       interface);
+       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",
@@ -4857,6 +5818,13 @@ error:
        }
 
        g_free(data->path);
+#if defined TIZEN_EXT
+       g_free(data->ssid->ssid);
+       g_free((char *)data->ssid->passphrase);
+       g_free((char *)data->ssid->connector);
+       g_free((char *)data->ssid->c_sign_key);
+       g_free((char *)data->ssid->net_access_key);
+#endif
        g_free(data->ssid);
        g_free(data);
 }
@@ -5075,7 +6043,9 @@ static void add_network_security_peap(DBusMessageIter *dict,
 
        }
 
-       if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) {
+       if(g_strcmp0(ssid->phase2_auth, "GTC") == 0 && g_strcmp0(ssid->eap, "ttls") == 0)
+               phase2_auth = g_strdup_printf("autheap=%s", ssid->phase2_auth);
+       else if (g_str_has_prefix(ssid->phase2_auth, "EAP-")) {
                phase2_auth = g_strdup_printf("autheap=%s",
                                        ssid->phase2_auth + strlen("EAP-"));
        } else
@@ -5108,6 +6078,33 @@ static void add_network_security_aka_sim(DBusMessageIter *dict,
                        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,
@@ -5134,8 +6131,20 @@ static void add_network_security_eap(DBusMessageIter *dict,
 
 #if defined TIZEN_EXT
        } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
-                       g_strcmp0(ssid->eap, "aka") == 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;
@@ -5275,6 +6284,83 @@ static void add_network_security_proto(DBusMessageIter *dict,
        g_free(proto);
 }
 
+#if defined TIZEN_EXT
+static void add_network_ieee80211w(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+       if (ssid->security != G_SUPPLICANT_SECURITY_SAE
+                       && ssid->security != G_SUPPLICANT_SECURITY_OWE
+                       && ssid->security != G_SUPPLICANT_SECURITY_DPP)
+               return;
+
+       supplicant_dbus_dict_append_basic(dict, "ieee80211w", DBUS_TYPE_UINT32,
+                                         &ssid->ieee80211w);
+}
+
+static void add_network_security_connector(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+       if (ssid->connector && strlen(ssid->connector) > 0) {
+               const char *key = "dpp_connector";
+
+               supplicant_dbus_dict_append_basic(dict,
+                               key, DBUS_TYPE_STRING,
+                               &ssid->connector);
+       }
+}
+
+static size_t convert_hexstr_to_bin(const char *hex_str, unsigned char **bin)
+{
+       unsigned char *bin_res = NULL;
+       unsigned int i, j, hex;
+       size_t hex_str_len;
+
+       if (!hex_str || strlen(hex_str) == 0)
+               return 0;
+
+       hex_str_len = strlen(hex_str);
+       bin_res = g_try_malloc0(hex_str_len / 2);
+       if (!bin_res)
+               return 0;
+
+       j = 0;
+       for (i = 0; i < hex_str_len; i+=2) {
+               sscanf(hex_str + i, "%02x", &hex);
+               bin_res[j++] = hex;
+       }
+
+       *bin = bin_res;
+       return hex_str_len / 2;
+}
+
+static void add_network_security_c_sign_key(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+       if (ssid->c_sign_key && strlen(ssid->c_sign_key) > 0) {
+               const char *key = "dpp_csign";
+               unsigned char *bin_csign = NULL;
+               size_t bin_csign_len = convert_hexstr_to_bin(ssid->c_sign_key, &bin_csign);
+               if  (bin_csign_len != 0)
+                       supplicant_dbus_dict_append_fixed_array(dict,
+                                       key, DBUS_TYPE_BYTE,
+                                       &bin_csign, bin_csign_len);
+               g_free(bin_csign);
+       }
+}
+
+static void add_network_security_net_access_key(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+       if (ssid->net_access_key && strlen(ssid->net_access_key) > 0) {
+               const char *key = "dpp_netaccesskey";
+               unsigned char *bin_netaccesskey = NULL;
+               size_t bin_netaccesskey_len = convert_hexstr_to_bin(ssid->net_access_key, &bin_netaccesskey);
+               if  (bin_netaccesskey_len != 0)
+                       supplicant_dbus_dict_append_fixed_array(dict,
+                                       key, DBUS_TYPE_BYTE,
+                                       &bin_netaccesskey, bin_netaccesskey_len);
+               g_free(bin_netaccesskey);
+       }
+}
+
+#endif
+
 static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
 {
        char *key_mgmt;
@@ -5316,6 +6402,21 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *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;
+       case G_SUPPLICANT_SECURITY_OWE:
+               key_mgmt = "OWE";
+               add_network_security_ciphers(dict, ssid);
+               add_network_security_proto(dict, ssid);
+               break;
+       case G_SUPPLICANT_SECURITY_DPP:
+               key_mgmt = "DPP";
+               add_network_security_connector(dict, ssid);
+               add_network_security_c_sign_key(dict, ssid);
+               add_network_security_net_access_key(dict, ssid);
+               break;
 #endif
        }
 
@@ -5338,6 +6439,11 @@ static void add_network_mode(DBusMessageIter *dict, GSupplicantSSID *ssid)
        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",
@@ -5368,14 +6474,14 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
 
        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;
@@ -5385,9 +6491,16 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
                        supplicant_dbus_dict_close(iter, &dict);
                        return;
                }
-               snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
+
+               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);
@@ -5465,6 +6578,7 @@ static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
                dbus_free(data);
                return;
        }
+
 #if defined TIZEN_EXT
        GSupplicantSSID *ssid = data->ssid;
        if (ssid->pin_wps != NULL) {
@@ -5526,12 +6640,8 @@ static void decryption_request_reply(DBusPendingCall *call,
        DBusMessageIter args;
        char *out_data;
        int ret;
-       static gchar* origin_value = NULL;
        struct interface_connect_data *data = user_data;
 
-       g_free(origin_value);
-       origin_value = NULL;
-
        SUPPLICANT_DBG("");
 
        reply = dbus_pending_call_steal_reply(call);
@@ -5540,18 +6650,18 @@ static void decryption_request_reply(DBusPendingCall *call,
        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);
-
-       origin_value = g_strdup((const gchar *)out_data);
-       data->ssid->passphrase = origin_value;
+       data->ssid->passphrase = g_strdup((const gchar *)out_data);
 
        ret = supplicant_dbus_method_call(data->interface->path,
                SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
@@ -5559,15 +6669,20 @@ static void decryption_request_reply(DBusPendingCall *call,
                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((char *)data->ssid->connector);
+               g_free((char *)data->ssid->c_sign_key);
+               g_free((char *)data->ssid->net_access_key);
                g_free(data->ssid);
                dbus_free(data);
        }
 
-done:
        dbus_message_unref(reply);
        dbus_pending_call_unref(call);
 
@@ -5620,6 +6735,146 @@ static int send_decryption_request(const char *passphrase,
 
        return 0;
 }
+
+static void decrypt_conf_obj_reply(DBusPendingCall *call,
+                                               void *user_data)
+{
+       DBusMessage *reply;
+       DBusError error;
+       DBusMessageIter iter, dict;
+       char *out_data;
+       int ret;
+       struct interface_connect_data *data = user_data;
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       dbus_error_init(&error);
+       if (dbus_set_error_from_message(&error, reply)) {
+               SUPPLICANT_DBG("decryption_conf_obj_reply() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (dbus_message_iter_init(reply, &iter) == FALSE) {
+               SUPPLICANT_DBG("dbus_message_iter_init() failed");
+               ret = -EINVAL;
+               goto done;
+       }
+
+       dbus_message_iter_recurse(&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);
+               if (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) {
+                       if (g_strcmp0(key, "connector") == 0) {
+                               dbus_message_iter_get_basic(&value, &out_data);
+                               data->ssid->connector = g_strdup((const gchar *)out_data);
+                               SUPPLICANT_DBG("connector %s", data->ssid->connector);
+                       } else if (g_strcmp0(key, "c_sign_key") == 0) {
+                               dbus_message_iter_get_basic(&value, &out_data);
+                               data->ssid->c_sign_key = g_strdup((const gchar *)out_data);
+                               SUPPLICANT_DBG("c_sign_key %s", data->ssid->c_sign_key);
+                       } else if (g_strcmp0(key, "net_access_key") == 0) {
+                               dbus_message_iter_get_basic(&value, &out_data);
+                               data->ssid->net_access_key = g_strdup((const gchar *)out_data);
+                               SUPPLICANT_DBG("net_access_key %s", data->ssid->net_access_key);
+                       }
+               }
+               dbus_message_iter_next(&dict);
+       }
+
+       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->connector);
+               g_free((char *)data->ssid->c_sign_key);
+               g_free((char *)data->ssid->net_access_key);
+               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_conf_obj_request(GSupplicantSSID *ssid,
+                       struct interface_connect_data *data)
+{
+       DBusMessage *msg = NULL;
+       DBusPendingCall *call;
+
+       SUPPLICANT_DBG("Decryption configuration object request");
+
+       if (!ssid) {
+               SUPPLICANT_DBG("Invalid parameter");
+               return -EINVAL;
+       }
+
+       if (!connection)
+               return -EINVAL;
+
+       msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
+                       NETCONFIG_WIFI_INTERFACE, "DecryptConfObj");
+       if (!msg)
+               return -EINVAL;
+
+       dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->connector,
+                                                       DBUS_TYPE_INVALID);
+       dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->c_sign_key,
+                                                       DBUS_TYPE_INVALID);
+       dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->net_access_key,
+                                                       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, decrypt_conf_obj_reply, data, NULL);
+       dbus_message_unref(msg);
+
+       SUPPLICANT_DBG("Decrypt Conf Obj request succeeded");
+
+       return 0;
+}
+
+static bool is_valid_config_object(GSupplicantSSID *ssid)
+{
+       return ((ssid->connector &&
+                       g_strcmp0(ssid->connector, "") != 0) &&
+                       (ssid->c_sign_key &&
+                       g_strcmp0(ssid->c_sign_key, "") != 0) &&
+                       (ssid->net_access_key &&
+                       g_strcmp0(ssid->net_access_key, "") != 0));
+}
 #endif
 
 int g_supplicant_interface_connect(GSupplicantInterface *interface,
@@ -5704,20 +6959,31 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface,
                        intf_data->user_data = user_data;
                        intf_data->network_remove_in_progress = TRUE;
                        network_remove(intf_data);
-               } else
+               } else {
 #if defined TIZEN_EXT
-                       if (ssid->passphrase && g_strcmp0(ssid->passphrase, "") != 0) {
+                       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 if (is_valid_config_object(ssid)) {
+                               ret = send_decryption_conf_obj_request(ssid, data);
+                               if (ret < 0)
+                                       SUPPLICANT_DBG("Decryption Conf Obj 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);
-       }
+                       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);
@@ -5763,6 +7029,27 @@ static void network_remove_result(const char *error,
                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 if (is_valid_config_object(data->ssid)) {
+                       ret = send_decryption_conf_obj_request(data->ssid, connect_data);
+                       if (ret < 0) {
+                               SUPPLICANT_DBG("Decryption Conf Obj 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,
@@ -6353,28 +7640,6 @@ int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params,
        return -EINPROGRESS;
 }
 
-#if defined TIZEN_EXT
-int g_supplicant_interface_remove_network(GSupplicantInterface *interface)
-{
-       struct interface_data *data;
-
-       SUPPLICANT_DBG("");
-
-       if (interface == NULL)
-               return -EINVAL;
-
-       if (system_available == FALSE)
-               return -EFAULT;
-
-       data = dbus_malloc0(sizeof(*data));
-       if (data == NULL)
-               return -ENOMEM;
-
-       data->interface = interface;
-
-       return network_remove(data);
-}
-#endif
 
 static const char *g_supplicant_rule0 = "type=signal,"
                                        "path=" DBUS_PATH_DBUS ","
@@ -6400,6 +7665,10 @@ static const char *g_supplicant_rule7 = "type=signal,"
 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)
 {
@@ -6466,6 +7735,9 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
        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,
@@ -6507,6 +7779,9 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
        SUPPLICANT_DBG("");
 
        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);