D-Bus: Add ConfigFile parameter into the interface properties
[mech_eap.git] / wpa_supplicant / dbus / dbus_new_handlers.c
index 166db5d..e11dd36 100644 (file)
@@ -2,7 +2,7 @@
  * WPA Supplicant / dbus-based control interface
  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -157,7 +157,8 @@ static struct wpa_supplicant * get_iface_by_dbus_path(
        struct wpa_supplicant *wpa_s;
 
        for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
-               if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
+               if (wpa_s->dbus_new_path &&
+                   os_strcmp(wpa_s->dbus_new_path, path) == 0)
                        return wpa_s;
        }
        return NULL;
@@ -213,7 +214,7 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
                } else if (entry.type == DBUS_TYPE_STRING) {
                        if (should_quote_opt(entry.key)) {
                                size = os_strlen(entry.str_value);
-                               if (size <= 0)
+                               if (size == 0)
                                        goto error;
 
                                size += 3;
@@ -254,6 +255,19 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s,
                if (wpa_config_set(ssid, entry.key, value, 0) < 0)
                        goto error;
 
+               if (os_strcmp(entry.key, "bssid") != 0 &&
+                   os_strcmp(entry.key, "priority") != 0)
+                       wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+
+               if (wpa_s->current_ssid == ssid ||
+                   wpa_s->current_ssid == NULL) {
+                       /*
+                        * Invalidate the EAP session cache if anything in the
+                        * current or previously used configuration changes.
+                        */
+                       eapol_sm_invalidate_cached_session(wpa_s->eapol);
+               }
+
                if ((os_strcmp(entry.key, "psk") == 0 &&
                     value[0] == '"' && ssid->ssid_len) ||
                    (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
@@ -421,7 +435,8 @@ dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter,
 
        for (i = 0; i < array_len; i++) {
                if (!dbus_message_iter_append_basic(&array_iter, type,
-                                                   array + i * element_size)) {
+                                                   (const char *) array +
+                                                   i * element_size)) {
                        dbus_set_error(error, DBUS_ERROR_FAILED,
                                       "%s: failed to construct message 2.5",
                                       __func__);
@@ -537,28 +552,28 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
                        driver = os_strdup(entry.str_value);
                        wpa_dbus_dict_entry_clear(&entry);
                        if (driver == NULL)
-                               goto error;
+                               goto oom;
                } else if (os_strcmp(entry.key, "Ifname") == 0 &&
                           entry.type == DBUS_TYPE_STRING) {
                        os_free(ifname);
                        ifname = os_strdup(entry.str_value);
                        wpa_dbus_dict_entry_clear(&entry);
                        if (ifname == NULL)
-                               goto error;
+                               goto oom;
                } else if (os_strcmp(entry.key, "ConfigFile") == 0 &&
                           entry.type == DBUS_TYPE_STRING) {
                        os_free(confname);
                        confname = os_strdup(entry.str_value);
                        wpa_dbus_dict_entry_clear(&entry);
                        if (confname == NULL)
-                               goto error;
+                               goto oom;
                } else if (os_strcmp(entry.key, "BridgeIfname") == 0 &&
                           entry.type == DBUS_TYPE_STRING) {
                        os_free(bridge_ifname);
                        bridge_ifname = os_strdup(entry.str_value);
                        wpa_dbus_dict_entry_clear(&entry);
                        if (bridge_ifname == NULL)
-                               goto error;
+                               goto oom;
                } else {
                        wpa_dbus_dict_entry_clear(&entry);
                        goto error;
@@ -586,8 +601,8 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
                iface.confname = confname;
                iface.bridge_ifname = bridge_ifname;
                /* Otherwise, have wpa_supplicant attach to it. */
-               wpa_s = wpa_supplicant_add_iface(global, &iface);
-               if (wpa_s) {
+               wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
+               if (wpa_s && wpa_s->dbus_new_path) {
                        const char *path = wpa_s->dbus_new_path;
 
                        reply = dbus_message_new_method_return(message);
@@ -610,6 +625,9 @@ out:
 error:
        reply = wpas_dbus_error_invalid_args(message, NULL);
        goto out;
+oom:
+       reply = wpas_dbus_error_no_memory(message);
+       goto out;
 }
 
 
@@ -668,7 +686,7 @@ DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
                              DBUS_TYPE_INVALID);
 
        wpa_s = wpa_supplicant_get_iface(global, ifname);
-       if (wpa_s == NULL)
+       if (wpa_s == NULL || wpa_s->dbus_new_path == NULL)
                return wpas_dbus_error_iface_unknown(message);
 
        path = wpa_s->dbus_new_path;
@@ -694,9 +712,9 @@ DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
  *
  * Getter for "DebugLevel" property.
  */
-dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
-                                        DBusError *error,
-                                        void *user_data)
+dbus_bool_t wpas_dbus_getter_debug_level(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        const char *str;
        int idx = wpa_debug_level;
@@ -720,9 +738,9 @@ dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
  *
  * Getter for "DebugTimestamp" property.
  */
-dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
-                                            DBusError *error,
-                                            void *user_data)
+dbus_bool_t wpas_dbus_getter_debug_timestamp(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
                                                &wpa_debug_timestamp, error);
@@ -739,9 +757,9 @@ dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
  *
  * Getter for "DebugShowKeys" property.
  */
-dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
-                                            DBusError *error,
-                                            void *user_data)
+dbus_bool_t wpas_dbus_getter_debug_show_keys(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
                                                &wpa_debug_show_keys, error);
@@ -757,8 +775,9 @@ dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
  *
  * Setter for "DebugLevel" property.
  */
-dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
-                                        DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_setter_debug_level(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_global *global = user_data;
        const char *str = NULL;
@@ -795,9 +814,9 @@ dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
  *
  * Setter for "DebugTimestamp" property.
  */
-dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
-                                            DBusError *error,
-                                            void *user_data)
+dbus_bool_t wpas_dbus_setter_debug_timestamp(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_global *global = user_data;
        dbus_bool_t val;
@@ -821,9 +840,9 @@ dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
  *
  * Setter for "DebugShowKeys" property.
  */
-dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
-                                            DBusError *error,
-                                            void *user_data)
+dbus_bool_t wpas_dbus_setter_debug_show_keys(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_global *global = user_data;
        dbus_bool_t val;
@@ -850,9 +869,9 @@ dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
  * by dbus clients to return list of registered interfaces objects
  * paths
  */
-dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
-                                       DBusError *error,
-                                       void *user_data)
+dbus_bool_t wpas_dbus_getter_interfaces(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_global *global = user_data;
        struct wpa_supplicant *wpa_s;
@@ -860,8 +879,10 @@ dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
        unsigned int i = 0, num = 0;
        dbus_bool_t success;
 
-       for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
-               num++;
+       for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+               if (wpa_s->dbus_new_path)
+                       num++;
+       }
 
        paths = os_calloc(num, sizeof(char *));
        if (!paths) {
@@ -869,8 +890,10 @@ dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
                return FALSE;
        }
 
-       for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
-               paths[i++] = wpa_s->dbus_new_path;
+       for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+               if (wpa_s->dbus_new_path)
+                       paths[i++] = wpa_s->dbus_new_path;
+       }
 
        success = wpas_dbus_simple_array_property_getter(iter,
                                                         DBUS_TYPE_OBJECT_PATH,
@@ -891,8 +914,9 @@ dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
  * Getter for "EapMethods" property. Handles requests
  * by dbus clients to return list of strings with supported EAP methods
  */
-dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
-                                        DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_eap_methods(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        char **eap_methods;
        size_t num_items = 0;
@@ -927,9 +951,9 @@ dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
  * return a list of strings with supported capabilities like AP, RSN IBSS,
  * and P2P that are determined at compile time.
  */
-dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
-                                                DBusError *error,
-                                                void *user_data)
+dbus_bool_t wpas_dbus_getter_global_capabilities(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
        size_t num_items = 0;
@@ -1018,10 +1042,10 @@ static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
 
                dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
 
-               if (len > MAX_SSID_LEN) {
+               if (len > SSID_MAX_LEN) {
                        wpa_printf(MSG_DEBUG,
                                   "%s[dbus]: SSID too long (len=%d max_len=%d)",
-                                  __func__, len, MAX_SSID_LEN);
+                                  __func__, len, SSID_MAX_LEN);
                        *reply = wpas_dbus_error_invalid_args(
                                message, "Invalid SSID: too long");
                        return -1;
@@ -1311,14 +1335,26 @@ DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
                                message,
                                "You can specify only Channels in passive scan");
                        goto out;
-               } else if (params.freqs && params.freqs[0]) {
-                       if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
-                               reply = wpas_dbus_error_scan_error(
-                                       message, "Scan request rejected");
-                       }
                } else {
-                       wpa_s->scan_req = MANUAL_SCAN_REQ;
-                       wpa_supplicant_req_scan(wpa_s, 0, 0);
+                       if (wpa_s->sched_scanning) {
+                               wpa_printf(MSG_DEBUG,
+                                          "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
+                                          __func__);
+                               wpa_supplicant_cancel_sched_scan(wpa_s);
+                       }
+
+                       if (params.freqs && params.freqs[0]) {
+                               wpa_s->last_scan_req = MANUAL_SCAN_REQ;
+                               if (wpa_supplicant_trigger_scan(wpa_s,
+                                                               &params)) {
+                                       reply = wpas_dbus_error_scan_error(
+                                               message,
+                                               "Scan request rejected");
+                               }
+                       } else {
+                               wpa_s->scan_req = MANUAL_SCAN_REQ;
+                               wpa_supplicant_req_scan(wpa_s, 0, 0);
+                       }
                }
        } else if (os_strcmp(type, "active") == 0) {
                if (!params.num_ssids) {
@@ -1328,6 +1364,14 @@ DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
 #ifdef CONFIG_AUTOSCAN
                autoscan_deinit(wpa_s);
 #endif /* CONFIG_AUTOSCAN */
+               if (wpa_s->sched_scanning) {
+                       wpa_printf(MSG_DEBUG,
+                                  "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed",
+                                  __func__);
+                       wpa_supplicant_cancel_sched_scan(wpa_s);
+               }
+
+               wpa_s->last_scan_req = MANUAL_SCAN_REQ;
                if (wpa_supplicant_trigger_scan(wpa_s, &params)) {
                        reply = wpas_dbus_error_scan_error(
                                message, "Scan request rejected");
@@ -1431,10 +1475,7 @@ DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
                                           struct wpa_supplicant *wpa_s)
 {
        if (wpa_s->current_ssid != NULL) {
-               wpa_s->disconnected = 1;
-               wpa_supplicant_deauthenticate(wpa_s,
-                                             WLAN_REASON_DEAUTH_LEAVING);
-
+               wpas_request_disconnection(wpa_s);
                return NULL;
        }
 
@@ -1462,7 +1503,8 @@ DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
 
        dbus_message_iter_init(message, &iter);
 
-       ssid = wpa_config_add_network(wpa_s->conf);
+       if (wpa_s->dbus_new_path)
+               ssid = wpa_supplicant_add_network(wpa_s);
        if (ssid == NULL) {
                wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
                           __func__);
@@ -1471,9 +1513,6 @@ DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
                        "wpa_supplicant could not add a network on this interface.");
                goto err;
        }
-       wpas_notify_network_added(wpa_s, ssid);
-       ssid->disabled = 1;
-       wpa_config_set_network_defaults(ssid);
 
        dbus_error_init(&error);
        if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
@@ -1538,6 +1577,27 @@ DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
 
 
 /**
+ * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: NULL
+ *
+ * Handler function for notifying system there will be a expected disconnect.
+ * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
+ */
+DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
+                                                 struct wpa_global *global)
+{
+       struct wpa_supplicant *wpa_s = global->ifaces;
+
+       for (; wpa_s; wpa_s = wpa_s->next)
+               if (wpa_s->wpa_state >= WPA_ASSOCIATED)
+                       wpa_s->own_disconnect_req = 1;
+       return NULL;
+}
+
+
+/**
  * wpas_dbus_handler_reattach - Reattach to current AP
  * @message: Pointer to incoming dbus message
  * @wpa_s: wpa_supplicant structure for a network interface
@@ -1561,6 +1621,30 @@ DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
 
 
 /**
+ * wpas_dbus_handler_reconnect - Reconnect if disconnected
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: InterfaceDisabled DBus error message if disabled
+ * or NULL otherwise.
+ *
+ * Handler function for "Reconnect" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message,
+               struct wpa_supplicant *wpa_s)
+{
+       if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+               return dbus_message_new_error(message,
+                                             WPAS_DBUS_ERROR_IFACE_DISABLED,
+                                             "This interface is disabled");
+       }
+
+       if (wpa_s->disconnected)
+               wpas_request_connection(wpa_s);
+       return NULL;
+}
+
+
+/**
  * wpas_dbus_handler_remove_network - Remove a configured network
  * @message: Pointer to incoming dbus message
  * @wpa_s: wpa_supplicant structure for a network interface
@@ -1575,8 +1659,7 @@ DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
        const char *op;
        char *iface, *net_id;
        int id;
-       struct wpa_ssid *ssid;
-       int was_disabled;
+       int result;
 
        dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
                              DBUS_TYPE_INVALID);
@@ -1586,7 +1669,7 @@ DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
        iface = wpas_dbus_new_decompose_object_path(op,
                                                    WPAS_DBUS_NEW_NETWORKS_PART,
                                                    &net_id);
-       if (iface == NULL || net_id == NULL ||
+       if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
            os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
                reply = wpas_dbus_error_invalid_args(message, op);
                goto out;
@@ -1599,27 +1682,12 @@ DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
                goto out;
        }
 
-       ssid = wpa_config_get_network(wpa_s->conf, id);
-       if (ssid == NULL) {
+       result = wpa_supplicant_remove_network(wpa_s, id);
+       if (result == -1) {
                reply = wpas_dbus_error_network_unknown(message);
                goto out;
        }
-
-       was_disabled = ssid->disabled;
-
-       wpas_notify_network_removed(wpa_s, ssid);
-
-       if (ssid == wpa_s->current_ssid)
-               wpa_supplicant_deauthenticate(wpa_s,
-                                             WLAN_REASON_DEAUTH_LEAVING);
-       else if (!was_disabled && wpa_s->sched_scanning) {
-               wpa_printf(MSG_DEBUG,
-                          "Stop ongoing sched_scan to remove network from filters");
-               wpa_supplicant_cancel_sched_scan(wpa_s);
-               wpa_supplicant_req_scan(wpa_s, 0, 0);
-       }
-
-       if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+       if (result == -2) {
                wpa_printf(MSG_ERROR,
                           "%s[dbus]: error occurred when removing network %d",
                           __func__, id);
@@ -1699,7 +1767,7 @@ DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
        iface = wpas_dbus_new_decompose_object_path(op,
                                                    WPAS_DBUS_NEW_NETWORKS_PART,
                                                    &net_id);
-       if (iface == NULL || net_id == NULL ||
+       if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
            os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
                reply = wpas_dbus_error_invalid_args(message, op);
                goto out;
@@ -1757,7 +1825,7 @@ DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message,
        iface = wpas_dbus_new_decompose_object_path(op,
                                                    WPAS_DBUS_NEW_NETWORKS_PART,
                                                    &net_id);
-       if (iface == NULL || net_id == NULL ||
+       if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path ||
            os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
                reply = wpas_dbus_error_invalid_args(message, op);
                goto out;
@@ -1788,7 +1856,7 @@ out:
        os_free(iface);
        return reply;
 #else /* IEEE8021X_EAPOL */
-       wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
+       wpa_printf(MSG_DEBUG, "dbus: 802.1X not included");
        return wpas_dbus_error_unknown_error(message, "802.1X not included");
 #endif /* IEEE8021X_EAPOL */
 }
@@ -2205,6 +2273,35 @@ DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
 #endif /* CONFIG_TDLS */
 
 
+#ifndef CONFIG_NO_CONFIG_WRITE
+/**
+ * wpas_dbus_handler_save_config - Save configuration to configuration file
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL on Success, Otherwise errror message
+ *
+ * Handler function for "SaveConfig" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
+                                           struct wpa_supplicant *wpa_s)
+{
+       int ret;
+
+       if (!wpa_s->conf->update_config) {
+               return wpas_dbus_error_unknown_error(
+                       message,
+                       "Not allowed to update configuration (update_config=0)");
+       }
+
+       ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
+       if (ret)
+               return wpas_dbus_error_unknown_error(
+                       message, "Failed to update configuration");
+       return NULL;
+}
+#endif /* CONFIG_NO_CONFIG_WRITE */
+
+
 /**
  * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
  * @message: Pointer to incoming dbus message
@@ -2250,12 +2347,14 @@ DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
                        message, DBUS_ERROR_FAILED,
                        "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed.");
 
-       wpa_dbus_mark_property_changed(
-               wpa_s->global->dbus, wpa_s->dbus_new_path,
-               WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
-       wpa_dbus_mark_property_changed(
-               wpa_s->global->dbus, wpa_s->dbus_new_path,
-               WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
+       if (wpa_s->dbus_new_path) {
+               wpa_dbus_mark_property_changed(
+                       wpa_s->global->dbus, wpa_s->dbus_new_path,
+                       WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath");
+               wpa_dbus_mark_property_changed(
+                       wpa_s->global->dbus, wpa_s->dbus_new_path,
+                       WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath");
+       }
 
        return NULL;
 }
@@ -2270,8 +2369,9 @@ DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path(
  *
  * Getter for "Capabilities" property of an interface.
  */
-dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
-                                         DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_capabilities(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        struct wpa_driver_capa capa;
@@ -2517,12 +2617,14 @@ dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
                                              &iter_array) ||
            !wpa_dbus_dict_string_array_add_element(
                    &iter_array, "infrastructure") ||
-           !wpa_dbus_dict_string_array_add_element(
-                   &iter_array, "ad-hoc") ||
+           (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_IBSS) &&
+            !wpa_dbus_dict_string_array_add_element(
+                    &iter_array, "ad-hoc")) ||
            (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
             !wpa_dbus_dict_string_array_add_element(
                     &iter_array, "ap")) ||
            (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
+            !wpa_s->conf->p2p_disabled &&
             !wpa_dbus_dict_string_array_add_element(
                     &iter_array, "p2p")) ||
            !wpa_dbus_dict_end_string_array(&iter_dict,
@@ -2561,8 +2663,9 @@ nomem:
  *
  * Getter for "State" property.
  */
-dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
-                                  void *user_data)
+dbus_bool_t wpas_dbus_getter_state(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        const char *str_state;
@@ -2601,8 +2704,9 @@ dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "scanning" property.
  */
-dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
-                                     void *user_data)
+dbus_bool_t wpas_dbus_getter_scanning(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
@@ -2621,8 +2725,9 @@ dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
  *
  * Getter function for "ApScan" property.
  */
-dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_getter_ap_scan(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
@@ -2641,8 +2746,9 @@ dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
  *
  * Setter function for "ApScan" property.
  */
-dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_setter_ap_scan(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_uint32_t ap_scan;
@@ -2670,9 +2776,9 @@ dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
  *
  * Getter function for "FastReauth" property.
  */
-dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
-                                        DBusError *error,
-                                        void *user_data)
+dbus_bool_t wpas_dbus_getter_fast_reauth(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
@@ -2692,9 +2798,9 @@ dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
  *
  * Setter function for "FastReauth" property.
  */
-dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
-                                    DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_setter_fast_reauth(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_bool_t fast_reauth;
@@ -2718,9 +2824,9 @@ dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
  * Getter for "DisconnectReason" property.  The reason is negative if it is
  * locally generated.
  */
-dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
-                                              DBusError *error,
-                                              void *user_data)
+dbus_bool_t wpas_dbus_getter_disconnect_reason(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_int32_t reason = wpa_s->disconnect_reason;
@@ -2731,6 +2837,27 @@ dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
 
 
 /**
+ * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "AssocStatusCode" property.
+ */
+dbus_bool_t wpas_dbus_getter_assoc_status_code(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       dbus_int32_t status_code = wpa_s->assoc_status_code;
+
+       return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
+                                               &status_code, error);
+}
+
+
+/**
  * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
  * @iter: Pointer to incoming dbus message iter
  * @error: Location to store error on failure
@@ -2739,9 +2866,9 @@ dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
  *
  * Getter function for "BSSExpireAge" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
-                                           DBusError *error,
-                                           void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_expire_age(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
@@ -2760,9 +2887,9 @@ dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
  *
  * Setter function for "BSSExpireAge" property.
  */
-dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
-                                           DBusError *error,
-                                           void *user_data)
+dbus_bool_t wpas_dbus_setter_bss_expire_age(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_uint32_t expire_age;
@@ -2789,9 +2916,9 @@ dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
  *
  * Getter function for "BSSExpireCount" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
-                                             DBusError *error,
-                                             void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_expire_count(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
@@ -2810,9 +2937,9 @@ dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
  *
  * Setter function for "BSSExpireCount" property.
  */
-dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
-                                             DBusError *error,
-                                             void *user_data)
+dbus_bool_t wpas_dbus_setter_bss_expire_count(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_uint32_t expire_count;
@@ -2839,8 +2966,9 @@ dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
  *
  * Getter function for "Country" property.
  */
-dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_getter_country(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        char country[3];
@@ -2864,8 +2992,9 @@ dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
  *
  * Setter function for "Country" property.
  */
-dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_setter_country(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        const char *country;
@@ -2902,9 +3031,9 @@ dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
  *
  * Getter function for "ScanInterval" property.
  */
-dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
-                                          DBusError *error,
-                                          void *user_data)
+dbus_bool_t wpas_dbus_getter_scan_interval(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_int32_t scan_interval = wpa_s->scan_interval;
@@ -2923,9 +3052,9 @@ dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
  *
  * Setter function for "ScanInterval" property.
  */
-dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
-                                          DBusError *error,
-                                          void *user_data)
+dbus_bool_t wpas_dbus_setter_scan_interval(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        dbus_int32_t scan_interval;
@@ -2952,8 +3081,9 @@ dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
  *
  * Getter for "Ifname" property.
  */
-dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
-                                   void *user_data)
+dbus_bool_t wpas_dbus_getter_ifname(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        const char *ifname = wpa_s->ifname;
@@ -2972,8 +3102,9 @@ dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "Driver" property.
  */
-dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
-                                   void *user_data)
+dbus_bool_t wpas_dbus_getter_driver(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        const char *driver;
@@ -3001,14 +3132,14 @@ dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "CurrentBSS" property.
  */
-dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
-                                        DBusError *error,
-                                        void *user_data)
+dbus_bool_t wpas_dbus_getter_current_bss(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
 
-       if (wpa_s->current_bss)
+       if (wpa_s->current_bss && wpa_s->dbus_new_path)
                os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
                            "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
                            wpa_s->dbus_new_path, wpa_s->current_bss->id);
@@ -3029,14 +3160,14 @@ dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
  *
  * Getter for "CurrentNetwork" property.
  */
-dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
-                                            DBusError *error,
-                                            void *user_data)
+dbus_bool_t wpas_dbus_getter_current_network(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
 
-       if (wpa_s->current_ssid)
+       if (wpa_s->current_ssid && wpa_s->dbus_new_path)
                os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
                            "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
                            wpa_s->dbus_new_path, wpa_s->current_ssid->id);
@@ -3057,9 +3188,9 @@ dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
  *
  * Getter for "CurrentAuthMode" property.
  */
-dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
-                                              DBusError *error,
-                                              void *user_data)
+dbus_bool_t wpas_dbus_getter_current_auth_mode(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        const char *eap_mode;
@@ -3075,9 +3206,11 @@ dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
                            "EAP-%s", eap_mode);
                auth_mode = eap_mode_buf;
 
-       } else {
+       } else if (wpa_s->current_ssid) {
                auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
                                             wpa_s->current_ssid->proto);
+       } else {
+               auth_mode = "UNKNOWN";
        }
 
        return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
@@ -3094,9 +3227,9 @@ dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
  *
  * Getter for "BridgeIfname" property.
  */
-dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
-                                          DBusError *error,
-                                          void *user_data)
+dbus_bool_t wpas_dbus_getter_bridge_ifname(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        const char *bridge_ifname = wpa_s->bridge_ifname;
@@ -3107,6 +3240,30 @@ dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
 
 
 /**
+ * wpas_dbus_getter_config_file - Get interface configuration file path
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "ConfigFile" property.
+ */
+dbus_bool_t wpas_dbus_getter_config_file(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       char *confname = "";
+
+       if (wpa_s->confname)
+               confname = wpa_s->confname;
+
+       return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
+                                               &confname, error);
+}
+
+
+/**
  * wpas_dbus_getter_bsss - Get array of BSSs objects
  * @iter: Pointer to incoming dbus message iter
  * @error: Location to store error on failure
@@ -3115,8 +3272,9 @@ dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
  *
  * Getter for "BSSs" property.
  */
-dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
-                                 void *user_data)
+dbus_bool_t wpas_dbus_getter_bsss(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        struct wpa_bss *bss;
@@ -3124,6 +3282,12 @@ dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
        unsigned int i = 0;
        dbus_bool_t success = FALSE;
 
+       if (!wpa_s->dbus_new_path) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "%s: no D-Bus interface", __func__);
+               return FALSE;
+       }
+
        paths = os_calloc(wpa_s->num_bss, sizeof(char *));
        if (!paths) {
                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
@@ -3166,8 +3330,9 @@ out:
  *
  * Getter for "Networks" property.
  */
-dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
-                                     void *user_data)
+dbus_bool_t wpas_dbus_getter_networks(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        struct wpa_ssid *ssid;
@@ -3175,6 +3340,12 @@ dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
        unsigned int i = 0, num = 0;
        dbus_bool_t success = FALSE;
 
+       if (!wpa_s->dbus_new_path) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "%s: no D-Bus interface", __func__);
+               return FALSE;
+       }
+
        for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
                if (!network_is_persistent_group(ssid))
                        num++;
@@ -3223,9 +3394,9 @@ out:
  *
  * Getter for "PKCS11EnginePath" property.
  */
-dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
-                                               DBusError *error,
-                                               void *user_data)
+dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        const char *pkcs11_engine_path;
@@ -3248,9 +3419,9 @@ dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
  *
  * Getter for "PKCS11ModulePath" property.
  */
-dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
-                                               DBusError *error,
-                                               void *user_data)
+dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        const char *pkcs11_module_path;
@@ -3273,8 +3444,9 @@ dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
  *
  * Getter for "Blobs" property.
  */
-dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
-                                  void *user_data)
+dbus_bool_t wpas_dbus_getter_blobs(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
@@ -3326,6 +3498,79 @@ dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
 }
 
 
+dbus_bool_t wpas_dbus_getter_iface_global(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       int ret;
+       char buf[250];
+       char *p = buf;
+
+       if (!property_desc->data) {
+               dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
+                              "Unhandled interface property %s",
+                              property_desc->dbus_property);
+               return FALSE;
+       }
+
+       ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf,
+                                  sizeof(buf));
+       if (ret < 0)
+               *p = '\0';
+
+       return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p,
+                                               error);
+}
+
+
+dbus_bool_t wpas_dbus_setter_iface_global(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       const char *new_value = NULL;
+       char buf[250];
+       size_t combined_len;
+       int ret;
+
+       if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+                                             &new_value))
+               return FALSE;
+
+       combined_len = os_strlen(property_desc->data) + os_strlen(new_value) +
+               3;
+       if (combined_len >= sizeof(buf)) {
+               dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
+                              "Interface property %s value too large",
+                              property_desc->dbus_property);
+               return FALSE;
+       }
+
+       if (!new_value[0])
+               new_value = "NULL";
+
+       ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data,
+                         new_value);
+       if (os_snprintf_error(combined_len, ret)) {
+               dbus_set_error(error,  WPAS_DBUS_ERROR_UNKNOWN_ERROR,
+                              "Failed to construct new interface property %s",
+                              property_desc->dbus_property);
+               return FALSE;
+       }
+
+       if (wpa_config_process_global(wpa_s->conf, buf, -1)) {
+               dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
+                              "Failed to set interface property %s",
+                              property_desc->dbus_property);
+               return FALSE;
+       }
+
+       wpa_supplicant_update_config(wpa_s);
+       return TRUE;
+}
+
+
 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
                                       DBusError *error, const char *func_name)
 {
@@ -3352,8 +3597,9 @@ static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
  *
  * Getter for "BSSID" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
-                                      void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_bssid(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3377,8 +3623,9 @@ dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "SSID" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
-                                     void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_ssid(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3402,8 +3649,9 @@ dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "Privacy" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
-                                        DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_privacy(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3428,8 +3676,9 @@ dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
  *
  * Getter for "Mode" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
-                                     void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_mode(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3469,8 +3718,9 @@ dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "Level" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
-                                       DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_signal(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3495,8 +3745,9 @@ dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
  *
  * Getter for "Frequency" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
-                                          DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_frequency(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3527,8 +3778,9 @@ static int cmp_u8s_desc(const void *a, const void *b)
  *
  * Getter for "Rates" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
-                                      DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_rates(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3567,14 +3819,14 @@ dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
 }
 
 
-static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
-                                                  struct wpa_ie_data *ie_data,
-                                                  DBusError *error)
+static dbus_bool_t wpas_dbus_get_bss_security_prop(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error)
 {
        DBusMessageIter iter_dict, variant_iter;
        const char *group;
        const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
-       const char *key_mgmt[8]; /* max 8 key managements may be supported */
+       const char *key_mgmt[9]; /* max 9 key managements may be supported */
        int n;
 
        if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
@@ -3598,8 +3850,14 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
                key_mgmt[n++] = "wpa-ft-eap";
        if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
                key_mgmt[n++] = "wpa-eap-sha256";
+#ifdef CONFIG_SUITEB
        if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
                key_mgmt[n++] = "wpa-eap-suite-b";
+#endif /* CONFIG_SUITEB */
+#ifdef CONFIG_SUITEB192
+       if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
+               key_mgmt[n++] = "wpa-eap-suite-b-192";
+#endif /* CONFIG_SUITEB192 */
        if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
                key_mgmt[n++] = "wpa-none";
 
@@ -3694,8 +3952,9 @@ nomem:
  *
  * Getter for "WPA" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_wpa(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3714,7 +3973,7 @@ dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
                return FALSE;
        }
 
-       return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
+       return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
 }
 
 
@@ -3727,8 +3986,9 @@ dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "RSN" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_rsn(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3747,7 +4007,7 @@ dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
                return FALSE;
        }
 
-       return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
+       return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
 }
 
 
@@ -3760,8 +4020,9 @@ dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "WPS" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_wps(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3769,6 +4030,7 @@ dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
        struct wpabuf *wps_ie;
 #endif /* CONFIG_WPS */
        DBusMessageIter iter_dict, variant_iter;
+       int wps_support = 0;
        const char *type = "";
 
        res = get_bss_helper(args, error, __func__);
@@ -3783,6 +4045,7 @@ dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
 #ifdef CONFIG_WPS
        wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE);
        if (wps_ie) {
+               wps_support = 1;
                if (wps_is_selected_pbc_registrar(wps_ie))
                        type = "pbc";
                else if (wps_is_selected_pin_registrar(wps_ie))
@@ -3792,7 +4055,7 @@ dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
        }
 #endif /* CONFIG_WPS */
 
-       if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type) ||
+       if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) ||
            !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) ||
            !dbus_message_iter_close_container(iter, &variant_iter))
                goto nomem;
@@ -3814,8 +4077,9 @@ nomem:
  *
  * Getter for "IEs" property.
  */
-dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_ies(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3839,8 +4103,9 @@ dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for BSS age
  */
-dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_age(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct bss_handler_args *args = user_data;
        struct wpa_bss *res;
@@ -3868,8 +4133,9 @@ dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "enabled" property of a configured network.
  */
-dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_getter_enabled(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct network_handler_args *net = user_data;
        dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
@@ -3888,8 +4154,9 @@ dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
  *
  * Setter for "Enabled" property of a configured network.
  */
-dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
-                                    void *user_data)
+dbus_bool_t wpas_dbus_setter_enabled(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct network_handler_args *net = user_data;
        struct wpa_supplicant *wpa_s;
@@ -3921,9 +4188,9 @@ dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
  *
  * Getter for "Properties" property of a configured network.
  */
-dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
-                                               DBusError *error,
-                                               void *user_data)
+dbus_bool_t wpas_dbus_getter_network_properties(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct network_handler_args *net = user_data;
        DBusMessageIter variant_iter, dict_iter;
@@ -3983,9 +4250,9 @@ out:
  *
  * Setter for "Properties" property of a configured network.
  */
-dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
-                                               DBusError *error,
-                                               void *user_data)
+dbus_bool_t wpas_dbus_setter_network_properties(
+       const struct wpa_dbus_property_desc *property_desc,
+       DBusMessageIter *iter, DBusError *error, void *user_data)
 {
        struct network_handler_args *net = user_data;
        struct wpa_ssid *ssid = net->ssid;
@@ -4080,7 +4347,7 @@ void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s,
        struct wpas_dbus_priv *priv = wpa_s->global->dbus;
 
        /* Do nothing if the control interface is not turned on */
-       if (priv == NULL)
+       if (priv == NULL || !wpa_s->dbus_new_path)
                return;
 
        if (wpa_s->preq_notify_peer == NULL)
@@ -4123,3 +4390,147 @@ out:
 }
 
 #endif /* CONFIG_AP */
+
+
+DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
+                                               struct wpa_supplicant *wpa_s)
+{
+       u8 *ielems;
+       int len;
+       struct ieee802_11_elems elems;
+       dbus_int32_t frame_id;
+       DBusMessageIter iter, array;
+
+       dbus_message_iter_init(message, &iter);
+       dbus_message_iter_get_basic(&iter, &frame_id);
+       if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "Invalid ID");
+       }
+
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_recurse(&iter, &array);
+       dbus_message_iter_get_fixed_array(&array, &ielems, &len);
+       if (!ielems || len == 0) {
+               return dbus_message_new_error(
+                       message, DBUS_ERROR_INVALID_ARGS, "Invalid value");
+       }
+
+       if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "Parse error");
+       }
+
+       wpa_s = wpas_vendor_elem(wpa_s, frame_id);
+       if (!wpa_s->vendor_elem[frame_id]) {
+               wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len);
+               wpas_vendor_elem_update(wpa_s);
+               return NULL;
+       }
+
+       if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "Resize error");
+       }
+
+       wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len);
+       wpas_vendor_elem_update(wpa_s);
+       return NULL;
+}
+
+
+DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
+                                               struct wpa_supplicant *wpa_s)
+{
+       DBusMessage *reply;
+       DBusMessageIter iter, array_iter;
+       dbus_int32_t frame_id;
+       const u8 *elem;
+       size_t elem_len;
+
+       dbus_message_iter_init(message, &iter);
+       dbus_message_iter_get_basic(&iter, &frame_id);
+
+       if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "Invalid ID");
+       }
+
+       wpa_s = wpas_vendor_elem(wpa_s, frame_id);
+       if (!wpa_s->vendor_elem[frame_id]) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "ID value does not exist");
+       }
+
+       reply = dbus_message_new_method_return(message);
+       if (!reply)
+               return wpas_dbus_error_no_memory(message);
+
+       dbus_message_iter_init_append(reply, &iter);
+
+       elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]);
+       elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
+
+       if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                                             DBUS_TYPE_BYTE_AS_STRING,
+                                             &array_iter) ||
+           !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
+                                                 &elem, elem_len) ||
+           !dbus_message_iter_close_container(&iter, &array_iter)) {
+               dbus_message_unref(reply);
+               reply = wpas_dbus_error_no_memory(message);
+       }
+
+       return reply;
+}
+
+
+DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
+                                                  struct wpa_supplicant *wpa_s)
+{
+       u8 *ielems;
+       int len;
+       struct ieee802_11_elems elems;
+       DBusMessageIter iter, array;
+       dbus_int32_t frame_id;
+
+       dbus_message_iter_init(message, &iter);
+       dbus_message_iter_get_basic(&iter, &frame_id);
+       if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "Invalid ID");
+       }
+
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_recurse(&iter, &array);
+       dbus_message_iter_get_fixed_array(&array, &ielems, &len);
+       if (!ielems || len == 0) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "Invalid value");
+       }
+
+       wpa_s = wpas_vendor_elem(wpa_s, frame_id);
+
+       if (len == 1 && *ielems == '*') {
+               wpabuf_free(wpa_s->vendor_elem[frame_id]);
+               wpa_s->vendor_elem[frame_id] = NULL;
+               wpas_vendor_elem_update(wpa_s);
+               return NULL;
+       }
+
+       if (!wpa_s->vendor_elem[frame_id]) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "ID value does not exist");
+       }
+
+       if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
+               return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                             "Parse error");
+       }
+
+       if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0)
+               return NULL;
+
+       return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+                                     "Not found");
+}