Move disconnect command handling to a common place
[mech_eap.git] / wpa_supplicant / dbus / dbus_new_handlers.c
index 66ee32f..8ccace5 100644 (file)
@@ -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;
@@ -434,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__);
@@ -600,7 +602,7 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
                iface.bridge_ifname = bridge_ifname;
                /* Otherwise, have wpa_supplicant attach to it. */
                wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
-               if (wpa_s) {
+               if (wpa_s && wpa_s->dbus_new_path) {
                        const char *path = wpa_s->dbus_new_path;
 
                        reply = dbus_message_new_method_return(message);
@@ -684,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;
@@ -710,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;
@@ -736,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);
@@ -755,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);
@@ -773,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;
@@ -811,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;
@@ -837,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;
@@ -866,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;
@@ -876,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) {
@@ -885,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,
@@ -907,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;
@@ -943,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;
@@ -1034,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;
@@ -1327,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) {
@@ -1344,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");
@@ -1447,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;
        }
 
@@ -1478,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_config_add_network(wpa_s->conf);
        if (ssid == NULL) {
                wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
                           __func__);
@@ -1554,6 +1580,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
@@ -1577,6 +1624,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
@@ -1602,7 +1673,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;
@@ -1715,7 +1786,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;
@@ -1773,7 +1844,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;
@@ -1804,7 +1875,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 */
 }
@@ -2221,6 +2292,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
@@ -2266,12 +2366,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;
 }
@@ -2286,8 +2388,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;
@@ -2533,12 +2636,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,
@@ -2577,8 +2682,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;
@@ -2617,8 +2723,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;
@@ -2637,8 +2744,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;
@@ -2657,8 +2765,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;
@@ -2686,9 +2795,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;
@@ -2708,9 +2817,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;
@@ -2734,9 +2843,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;
@@ -2747,6 +2856,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
@@ -2755,9 +2885,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;
@@ -2776,9 +2906,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;
@@ -2805,9 +2935,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;
@@ -2826,9 +2956,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;
@@ -2855,8 +2985,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];
@@ -2880,8 +3011,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;
@@ -2918,9 +3050,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;
@@ -2939,9 +3071,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;
@@ -2968,8 +3100,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;
@@ -2988,8 +3121,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;
@@ -3017,14 +3151,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);
@@ -3045,14 +3179,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);
@@ -3073,9 +3207,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;
@@ -3091,9 +3225,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,
@@ -3110,9 +3246,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;
@@ -3131,8 +3267,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;
@@ -3140,6 +3277,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");
@@ -3182,8 +3325,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;
@@ -3191,6 +3335,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++;
@@ -3239,9 +3389,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;
@@ -3264,9 +3414,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;
@@ -3289,8 +3439,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;
@@ -3342,6 +3493,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)
 {
@@ -3368,8 +3592,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;
@@ -3393,8 +3618,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;
@@ -3418,8 +3644,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;
@@ -3444,8 +3671,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;
@@ -3485,8 +3713,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;
@@ -3511,8 +3740,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;
@@ -3543,8 +3773,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;
@@ -3583,9 +3814,9 @@ 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;
@@ -3716,8 +3947,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;
@@ -3736,7 +3968,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);
 }
 
 
@@ -3749,8 +3981,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;
@@ -3769,7 +4002,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);
 }
 
 
@@ -3782,8 +4015,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;
@@ -3838,8 +4072,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;
@@ -3863,8 +4098,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;
@@ -3892,8 +4128,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;
@@ -3912,8 +4149,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;
@@ -3945,9 +4183,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;
@@ -4007,9 +4245,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;
@@ -4104,7 +4342,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)
@@ -4147,3 +4385,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");
+}