D-Bus: Remove useless wpa_s->conf checks
[mech_eap.git] / wpa_supplicant / dbus / dbus_new_handlers_p2p.c
index 79373b4..e24b216 100644 (file)
@@ -1,14 +1,9 @@
 /*
  * WPA Supplicant / dbus-based control interface (P2P)
+ * Copyright (c) 2011-2012, Intel Corporation
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "includes.h"
@@ -31,6 +26,7 @@
 #include "ap/wps_hostapd.h"
 
 #include "../p2p_supplicant.h"
+#include "../wifi_display.h"
 
 /**
  * Parses out the mac address from the peer object path.
@@ -45,7 +41,7 @@ static int parse_peer_object_path(char *peer_path, u8 addr[ETH_ALEN])
 
        if (!peer_path)
                return -1;
-       p = strrchr(peer_path, '/');
+       p = os_strrchr(peer_path, '/');
        if (!p)
                return -1;
        p++;
@@ -78,7 +74,7 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
        DBusMessageIter iter;
        DBusMessageIter iter_dict;
        unsigned int timeout = 0;
-       enum p2p_discovery_type type = P2P_FIND_ONLY_SOCIAL;
+       enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL;
        int num_req_dev_types = 0;
        unsigned int i;
        u8 *req_dev_types = NULL;
@@ -131,8 +127,11 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
                wpa_dbus_dict_entry_clear(&entry);
        }
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
-                     NULL);
+                     NULL, 0);
        os_free(req_dev_types);
        return reply;
 
@@ -148,6 +147,9 @@ error:
 DBusMessage * wpas_dbus_handler_p2p_stop_find(DBusMessage *message,
                                              struct wpa_supplicant *wpa_s)
 {
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        wpas_p2p_stop_find(wpa_s);
        return NULL;
 }
@@ -166,6 +168,9 @@ DBusMessage * wpas_dbus_handler_p2p_rejectpeer(DBusMessage *message,
        if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
                return wpas_dbus_error_invalid_args(message, NULL);
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
                return wpas_dbus_error_unknown_error(message,
                                "Failed to call wpas_p2p_reject method.");
@@ -184,6 +189,9 @@ DBusMessage * wpas_dbus_handler_p2p_listen(DBusMessage *message,
                return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
                                              NULL);
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        if (wpas_p2p_listen(wpa_s, (unsigned int)timeout))
                return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
                                              NULL);
@@ -221,6 +229,9 @@ DBusMessage * wpas_dbus_handler_p2p_extendedlisten(
                wpa_dbus_dict_entry_clear(&entry);
        }
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        if (wpas_p2p_ext_listen(wpa_s, period, interval))
                return wpas_dbus_error_unknown_error(
                        message, "failed to initiate a p2p_ext_listen.");
@@ -269,6 +280,10 @@ DBusMessage * wpas_dbus_handler_p2p_presence_request(
 
                wpa_dbus_dict_entry_clear(&entry);
        }
+
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
                return wpas_dbus_error_unknown_error(message,
                                "Failed to invoke presence request.");
@@ -323,6 +338,9 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
                wpa_dbus_dict_entry_clear(&entry);
        }
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        if (pg_object_path != NULL) {
                /*
                 * A persistent group Object Path is defined meaning we want
@@ -351,13 +369,14 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
                if (ssid == NULL || ssid->disabled != 2)
                        goto inv_args;
 
-               if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq)) {
+               if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
+                                                 NULL, 0)) {
                        reply = wpas_dbus_error_unknown_error(
                                message,
                                "Failed to reinvoke a persistent group");
                        goto out;
                }
-       } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq))
+       } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0))
                goto inv_args;
 
 out:
@@ -413,6 +432,9 @@ DBusMessage * wpas_dbus_handler_p2p_flush(DBusMessage *message,
        if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL))
                return reply;
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
        wpa_s->force_long_sd = 0;
        p2p_flush(wpa_s->global->p2p);
@@ -507,9 +529,12 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
        if ((!pin || !pin[0]) && (wps_method == WPS_PIN_KEYPAD))
                goto inv_args;
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
-                                  persistent_group, join, authorize_only,
-                                  go_intent, freq);
+                                  persistent_group, 0, join, authorize_only,
+                                  go_intent, freq, -1, 0, 0, 0);
 
        if (new_pin >= 0) {
                char npin[9];
@@ -608,6 +633,9 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
                goto err;
        }
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        if (persistent) {
                /*
                 * A group ID is defined meaning we want to re-invoke a
@@ -635,7 +663,8 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
                if (ssid == NULL || ssid->disabled != 2)
                        goto err;
 
-               if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL) < 0) {
+               if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) <
+                   0) {
                        reply = wpas_dbus_error_unknown_error(
                                message,
                                "Failed to reinvoke a persistent group");
@@ -692,7 +721,11 @@ DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
            os_strcmp(config_method, "pushbutton"))
                return wpas_dbus_error_invalid_args(message, NULL);
 
-       if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method, 0) < 0)
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
+       if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
+                              WPAS_P2P_PD_FOR_GO_NEG) < 0)
                return wpas_dbus_error_unknown_error(message,
                                "Failed to send provision discovery request");
 
@@ -704,9 +737,9 @@ DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
  * P2P Device property accessor methods.
  */
 
-dbus_bool_t wpas_dbus_getter_p2p_device_properties(DBusMessageIter *iter,
-                                                  DBusError *error,
-                                                  void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
+                                              DBusError *error,
+                                              void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        DBusMessageIter variant_iter, dict_iter;
@@ -720,6 +753,9 @@ dbus_bool_t wpas_dbus_getter_p2p_device_properties(DBusMessageIter *iter,
        if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
                return FALSE;
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
                                              "a{sv}", &variant_iter) ||
            !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
@@ -782,7 +818,7 @@ dbus_bool_t wpas_dbus_getter_p2p_device_properties(DBusMessageIter *iter,
                goto err_no_mem;
 
        /* Persistent Reconnect */
-       if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistantReconnect",
+       if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistentReconnect",
                                       wpa_s->conf->persistent_reconnect))
                goto err_no_mem;
 
@@ -827,6 +863,16 @@ dbus_bool_t wpas_dbus_getter_p2p_device_properties(DBusMessageIter *iter,
                                         wpa_s->conf->disassoc_low_ack))
                goto err_no_mem;
 
+       /* No Group Iface */
+       if (!wpa_dbus_dict_append_bool(&dict_iter, "NoGroupIface",
+                                      wpa_s->conf->p2p_no_group_iface))
+               goto err_no_mem;
+
+       /* P2P Search Delay */
+       if (!wpa_dbus_dict_append_uint32(&dict_iter, "p2p_search_delay",
+                                        wpa_s->conf->p2p_search_delay))
+               goto err_no_mem;
+
        if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
            !dbus_message_iter_close_container(iter, &variant_iter))
                goto err_no_mem;
@@ -839,9 +885,9 @@ err_no_mem:
 }
 
 
-dbus_bool_t wpas_dbus_setter_p2p_device_properties(DBusMessageIter *iter,
-                                                  DBusError *error,
-                                                  void *user_data)
+dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
+                                              DBusError *error,
+                                              void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
        DBusMessageIter variant_iter, iter_dict;
@@ -851,6 +897,9 @@ dbus_bool_t wpas_dbus_setter_p2p_device_properties(DBusMessageIter *iter,
        if (!wpa_dbus_p2p_check_enabled(wpa_s, NULL, NULL, error))
                return FALSE;
 
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
        dbus_message_iter_recurse(iter, &variant_iter);
        if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
                return FALSE;
@@ -927,7 +976,7 @@ dbus_bool_t wpas_dbus_setter_p2p_device_properties(DBusMessageIter *iter,
                           (entry.type == DBUS_TYPE_UINT32) &&
                           (entry.uint32_value <= 15))
                        wpa_s->conf->p2p_go_intent = entry.uint32_value;
-               else if ((os_strcmp(entry.key, "PersistantReconnect") == 0) &&
+               else if ((os_strcmp(entry.key, "PersistentReconnect") == 0) &&
                         (entry.type == DBUS_TYPE_BOOLEAN))
                        wpa_s->conf->persistent_reconnect = entry.bool_value;
                else if ((os_strcmp(entry.key, "ListenRegClass") == 0) &&
@@ -976,6 +1025,12 @@ dbus_bool_t wpas_dbus_setter_p2p_device_properties(DBusMessageIter *iter,
                else if (os_strcmp(entry.key, "disassoc_low_ack") == 0 &&
                         entry.type == DBUS_TYPE_UINT32)
                        wpa_s->conf->disassoc_low_ack = entry.uint32_value;
+               else if (os_strcmp(entry.key, "NoGroupIface") == 0 &&
+                        entry.type == DBUS_TYPE_BOOLEAN)
+                       wpa_s->conf->p2p_no_group_iface = entry.bool_value;
+               else if (os_strcmp(entry.key, "p2p_search_delay") == 0 &&
+                        entry.type == DBUS_TYPE_UINT32)
+                       wpa_s->conf->p2p_search_delay = entry.uint32_value;
                else
                        goto error;
 
@@ -1053,7 +1108,7 @@ dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
         * Now construct the peer object paths in a form suitable for
         * array_property_getter helper below.
         */
-       peer_obj_paths = os_zalloc(num * sizeof(char *));
+       peer_obj_paths = os_calloc(num, sizeof(char *));
 
        if (!peer_obj_paths) {
                out_of_mem = 1;
@@ -1129,6 +1184,7 @@ dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
                break;
        default:
                str = "device";
+               break;
        }
 
        return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &str,
@@ -1140,13 +1196,18 @@ dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
                                       void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
+       char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
+       char *dbus_groupobj_path = path_buf;
 
        if (wpa_s->dbus_groupobj_path == NULL)
-               return FALSE;
+               os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                           "/");
+       else
+               os_snprintf(dbus_groupobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                           "%s", wpa_s->dbus_groupobj_path);
 
        return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
-                                               &wpa_s->dbus_groupobj_path,
-                                               error);
+                                               &dbus_groupobj_path, error);
 }
 
 
@@ -1157,11 +1218,13 @@ dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
        char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
 
        if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
-               return FALSE;
+               os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
+       else
+               os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                           "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
+                           COMPACT_MACSTR,
+                           wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
 
-       os_snprintf(go_peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-                   "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
-                   wpa_s->dbus_new_path, MAC2STR(wpa_s->go_dev_addr));
        path = go_peer_obj_path;
        return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH,
                                                &path, error);
@@ -1341,6 +1404,7 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
 {
        struct peer_handler_args *peer_args = user_data;
        const struct p2p_peer_info *info;
+       DBusMessageIter variant_iter, array_iter;
 
        info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
                                  peer_args->p2p_device_addr, 0);
@@ -1350,29 +1414,80 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
                return FALSE;
        }
 
+       if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+                                             DBUS_TYPE_ARRAY_AS_STRING
+                                             DBUS_TYPE_ARRAY_AS_STRING
+                                             DBUS_TYPE_BYTE_AS_STRING,
+                                             &variant_iter)) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "%s: failed to construct message 1", __func__);
+               return FALSE;
+       }
+
+       if (!dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
+                                             DBUS_TYPE_ARRAY_AS_STRING
+                                             DBUS_TYPE_BYTE_AS_STRING,
+                                             &array_iter)) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "%s: failed to construct message 2", __func__);
+               return FALSE;
+       }
+
        if (info->wps_sec_dev_type_list_len) {
                const u8 *sec_dev_type_list = info->wps_sec_dev_type_list;
-               int num_sec_dev_types = info->wps_sec_dev_type_list_len;
+               int num_sec_device_types =
+                       info->wps_sec_dev_type_list_len / WPS_DEV_TYPE_LEN;
+               int i;
+               DBusMessageIter inner_array_iter;
+
+               for (i = 0; i < num_sec_device_types; i++) {
+                       if (!dbus_message_iter_open_container(
+                                   &array_iter, DBUS_TYPE_ARRAY,
+                                   DBUS_TYPE_BYTE_AS_STRING,
+                                   &inner_array_iter)) {
+                               dbus_set_error(error, DBUS_ERROR_FAILED,
+                                              "%s: failed to construct "
+                                              "message 3 (%d)",
+                                              __func__, i);
+                               return FALSE;
+                       }
 
-               if (!wpas_dbus_simple_array_property_getter(iter,
-                                                           DBUS_TYPE_BYTE,
-                                                           sec_dev_type_list,
-                                                           num_sec_dev_types,
-                                                           error))
-                       goto err_no_mem;
-               else
-                       return TRUE;
+                       if (!dbus_message_iter_append_fixed_array(
+                                   &inner_array_iter, DBUS_TYPE_BYTE,
+                                   &sec_dev_type_list, WPS_DEV_TYPE_LEN)) {
+                               dbus_set_error(error, DBUS_ERROR_FAILED,
+                                              "%s: failed to construct "
+                                              "message 4 (%d)",
+                                              __func__, i);
+                               return FALSE;
+                       }
+
+                       if (!dbus_message_iter_close_container(
+                                   &array_iter, &inner_array_iter)) {
+                               dbus_set_error(error, DBUS_ERROR_FAILED,
+                                              "%s: failed to construct "
+                                              "message 5 (%d)",
+                                              __func__, i);
+                               return FALSE;
+                       }
+
+                       sec_dev_type_list += WPS_DEV_TYPE_LEN;
+               }
        }
 
-       if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, NULL,
-                                                   0, error))
-               goto err_no_mem;
+       if (!dbus_message_iter_close_container(&variant_iter, &array_iter)) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "%s: failed to construct message 6", __func__);
+               return FALSE;
+       }
 
-       return TRUE;
+       if (!dbus_message_iter_close_container(iter, &variant_iter)) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "%s: failed to construct message 7", __func__);
+               return FALSE;
+       }
 
-err_no_mem:
-       dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
-       return FALSE;
+       return TRUE;
 }
 
 
@@ -1380,8 +1495,8 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
                                                       DBusError *error,
                                                       void *user_data)
 {
-       const struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
-       int i, num;
+       struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
+       unsigned int i, num = 0;
        struct peer_handler_args *peer_args = user_data;
        const struct p2p_peer_info *info;
 
@@ -1394,19 +1509,18 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
        }
 
        /* Add WPS vendor extensions attribute */
-       for (i = 0, num = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
+       os_memset(vendor_extension, 0, sizeof(vendor_extension));
+       for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
                if (info->wps_vendor_ext[i] == NULL)
                        continue;
                vendor_extension[num] = info->wps_vendor_ext[i];
                num++;
        }
 
-       if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_STRING,
-                                                   vendor_extension, num,
-                                                   error)) {
-               dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+       if (!wpas_dbus_simple_array_array_property_getter(iter, DBUS_TYPE_BYTE,
+                                                         vendor_extension,
+                                                         num, error))
                return FALSE;
-       }
 
        return TRUE;
 }
@@ -1415,10 +1529,150 @@ dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
 dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
                                          DBusError *error, void *user_data)
 {
-       /* struct peer_handler_args *peer_args = user_data; */
+       struct peer_handler_args *peer_args = user_data;
+       const struct p2p_peer_info *info;
 
-       dbus_set_error_const(error, DBUS_ERROR_FAILED, "not implemented");
-       return FALSE;
+       info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+                                 peer_args->p2p_device_addr, 0);
+       if (info == NULL) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "failed to find peer");
+               return FALSE;
+       }
+
+       if (info->wfd_subelems == NULL)
+               return wpas_dbus_simple_array_property_getter(iter,
+                                                             DBUS_TYPE_BYTE,
+                                                             NULL, 0, error);
+
+       return wpas_dbus_simple_array_property_getter(
+               iter, DBUS_TYPE_BYTE, (char *) info->wfd_subelems->buf,
+               info->wfd_subelems->used, error);
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
+                                                    DBusError *error,
+                                                    void *user_data)
+{
+       struct peer_handler_args *peer_args = user_data;
+       const struct p2p_peer_info *info;
+
+       info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+                                 peer_args->p2p_device_addr, 0);
+       if (info == NULL) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "failed to find peer");
+               return FALSE;
+       }
+
+       return wpas_dbus_simple_array_property_getter(
+               iter, DBUS_TYPE_BYTE, (char *) info->p2p_device_addr,
+               ETH_ALEN, error);
+}
+
+
+struct peer_group_data {
+       struct wpa_supplicant *wpa_s;
+       const struct p2p_peer_info *info;
+       char **paths;
+       unsigned int nb_paths;
+       int error;
+};
+
+
+static int match_group_where_peer_is_client(struct p2p_group *group,
+                                           void *user_data)
+{
+       struct peer_group_data *data = user_data;
+       const struct p2p_group_config *cfg;
+       struct wpa_supplicant *wpa_s_go;
+       char **paths;
+
+       if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
+               return 1;
+
+       cfg = p2p_group_get_config(group);
+
+       wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
+                                        cfg->ssid_len);
+       if (wpa_s_go == NULL)
+               return 1;
+
+       paths = os_realloc_array(data->paths, data->nb_paths + 1,
+                                sizeof(char *));
+       if (paths == NULL)
+               goto out_of_memory;
+
+       data->paths = paths;
+       data->paths[data->nb_paths] = wpa_s_go->dbus_groupobj_path;
+       data->nb_paths++;
+
+       return 1;
+
+out_of_memory:
+       data->error = ENOMEM;
+       return 0;
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
+                                            DBusError *error,
+                                            void *user_data)
+{
+       struct peer_handler_args *peer_args = user_data;
+       const struct p2p_peer_info *info;
+       struct peer_group_data data;
+       struct wpa_supplicant *wpa_s, *wpa_s_go;
+       dbus_bool_t success = FALSE;
+
+       info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+                                 peer_args->p2p_device_addr, 0);
+       if (info == NULL) {
+               dbus_set_error(error, DBUS_ERROR_FAILED,
+                              "failed to find peer");
+               return FALSE;
+       }
+
+       os_memset(&data, 0, sizeof(data));
+
+       wpa_s = peer_args->wpa_s;
+       if (wpa_s->p2p_dev)
+               wpa_s = wpa_s->p2p_dev;
+
+       wpa_s_go = wpas_get_p2p_client_iface(wpa_s, info->p2p_device_addr);
+       if (wpa_s_go) {
+               data.paths = os_calloc(1, sizeof(char *));
+               if (data.paths == NULL)
+                       goto out_of_memory;
+               data.paths[0] = wpa_s_go->dbus_groupobj_path;
+               data.nb_paths = 1;
+       }
+
+       data.wpa_s = peer_args->wpa_s;
+       data.info = info;
+
+       p2p_loop_on_all_groups(peer_args->wpa_s->global->p2p,
+                              match_group_where_peer_is_client, &data);
+       if (data.error)
+               goto out_of_memory;
+
+       if (data.paths == NULL) {
+               return wpas_dbus_simple_array_property_getter(
+                       iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
+       }
+
+       success = wpas_dbus_simple_array_property_getter(iter,
+                                                        DBUS_TYPE_OBJECT_PATH,
+                                                        data.paths,
+                                                        data.nb_paths, error);
+       goto out;
+
+out_of_memory:
+       dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
+out:
+       os_free(data.paths);
+       return success;
 }
 
 
@@ -1441,20 +1695,11 @@ dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
        unsigned int i = 0, num = 0;
        dbus_bool_t success = FALSE;
 
-       if (wpa_s->conf == NULL) {
-               wpa_printf(MSG_ERROR, "dbus: %s: "
-                          "An error occurred getting persistent groups list",
-                          __func__);
-               dbus_set_error_const(error, DBUS_ERROR_FAILED, "an error "
-                                    "occurred getting persistent groups list");
-               return FALSE;
-       }
-
        for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
                if (network_is_persistent_group(ssid))
                        num++;
 
-       paths = os_zalloc(num * sizeof(char *));
+       paths = os_calloc(num, sizeof(char *));
        if (!paths) {
                dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
                return FALSE;
@@ -1746,9 +1991,11 @@ dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
        const u8 *addr;
        dbus_bool_t success = FALSE;
 
-       /* Ensure we are a GO */
-       if (wpa_s->wpa_state != WPA_COMPLETED)
-               return FALSE;
+       /* Verify correct role for this property */
+       if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_GO) {
+               return wpas_dbus_simple_array_property_getter(
+                       iter, DBUS_TYPE_OBJECT_PATH, NULL, 0, error);
+       }
 
        ssid = wpa_s->conf->ssid;
        /* At present WPAS P2P_GO mode only applicable for p2p_go */
@@ -1759,7 +2006,7 @@ dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
 
        num_members = p2p_get_group_num_members(wpa_s->p2p_group);
 
-       paths = os_zalloc(num_members * sizeof(char *));
+       paths = os_calloc(num_members, sizeof(char *));
        if (!paths)
                goto out_of_memory;
 
@@ -1769,9 +2016,9 @@ dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
                if (!paths[i])
                        goto out_of_memory;
                os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
-                           "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
+                           "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
                            "/" COMPACT_MACSTR,
-                           wpa_s->dbus_groupobj_path, MAC2STR(addr));
+                           wpa_s->parent->dbus_new_path, MAC2STR(addr));
                i++;
        }
 
@@ -1796,116 +2043,149 @@ out_of_memory:
 }
 
 
-dbus_bool_t wpas_dbus_getter_p2p_group_properties(DBusMessageIter *iter,
-                                                 DBusError *error,
-                                                 void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
+                                           DBusError *error, void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       if (wpa_s->current_ssid == NULL)
+               return FALSE;
+       return wpas_dbus_simple_array_property_getter(
+               iter, DBUS_TYPE_BYTE, wpa_s->current_ssid->ssid,
+               wpa_s->current_ssid->ssid_len, error);
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
+                                            DBusError *error,
+                                            void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
-       DBusMessageIter variant_iter, dict_iter;
-       struct hostapd_data *hapd = NULL;
-       const struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
-       int num_vendor_ext = 0;
-       int i;
        u8 role = wpas_get_p2p_role(wpa_s);
-       u16 op_freq = 0;
-       u8 *p_bssid = NULL;
-       char *role_name = NULL;
+       u8 *p_bssid;
 
-       if (!wpa_s->current_ssid)
-               return FALSE;
+       if (role == WPAS_P2P_ROLE_CLIENT) {
+               if (wpa_s->current_ssid == NULL)
+                       return FALSE;
+               p_bssid = wpa_s->current_ssid->bssid;
+       } else {
+               if (wpa_s->ap_iface == NULL)
+                       return FALSE;
+               p_bssid = wpa_s->ap_iface->bss[0]->own_addr;
+       }
 
-       /* Check current role and adjust information accordingly */
-       switch (role) {
-       case WPAS_P2P_ROLE_CLIENT:
-               /* go_params is only valid for a client */
-               if (wpa_s->go_params) {
-                       op_freq = wpa_s->go_params->freq;
-                       p_bssid = wpa_s->current_ssid->bssid;
-                       role_name = "client";
-               } else
+       return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+                                                     p_bssid, ETH_ALEN,
+                                                     error);
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
+                                                DBusError *error,
+                                                void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       u16 op_freq;
+       u8 role = wpas_get_p2p_role(wpa_s);
+
+       if (role == WPAS_P2P_ROLE_CLIENT) {
+               if (wpa_s->go_params == NULL)
                        return FALSE;
-               break;
-       case WPAS_P2P_ROLE_GO:
-               /* ap_iface is only valid for a GO */
-               if (wpa_s->ap_iface) {
-                       hapd = wpa_s->ap_iface->bss[0];
-                       p_bssid = hapd->own_addr;
-                       op_freq = wpa_s->ap_iface->freq;
-                       role_name = "GO";
-               } else
+               op_freq = wpa_s->go_params->freq;
+       } else {
+               if (wpa_s->ap_iface == NULL)
                        return FALSE;
-               break;
-       default:
-               /* Error condition; this should NEVER occur */
-               return FALSE;
+               op_freq = wpa_s->ap_iface->freq;
        }
 
-       if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
-                                             "a{sv}", &variant_iter) ||
-           !wpa_dbus_dict_open_write(&variant_iter, &dict_iter))
-               goto err_no_mem;
-       /* Provide the SSID */
-       if (!wpa_dbus_dict_append_byte_array(
-                   &dict_iter, "SSID",
-                   (const char *) wpa_s->current_ssid->ssid,
-                   wpa_s->current_ssid->ssid_len))
-               goto err_no_mem;
-       /* Provide the BSSID */
-       if (p_bssid &&
-           !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
-                                            (const char *) p_bssid, ETH_ALEN))
-               goto err_no_mem;
-       /* Provide the role within the group */
-       if (role_name &&
-           !wpa_dbus_dict_append_string(&dict_iter, "Role", role_name))
-               goto err_no_mem;
-       /* Provide the operational frequency */
-       if (!wpa_dbus_dict_append_uint16(&dict_iter, "Frequency", op_freq))
-               goto err_no_mem;
+       return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16,
+                                               &op_freq, error);
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
+                                                 DBusError *error,
+                                                 void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       u8 role = wpas_get_p2p_role(wpa_s);
+       char *p_pass = NULL;
 
-       /* Additional information for group owners */
+       /* Verify correct role for this property */
        if (role == WPAS_P2P_ROLE_GO) {
-               /* Provide the passphrase */
-               if (!wpa_dbus_dict_append_string(&dict_iter, "Passphrase",
-                                       wpa_s->current_ssid->passphrase))
-                       goto err_no_mem;
+               if (wpa_s->current_ssid == NULL)
+                       return FALSE;
+               p_pass = wpa_s->current_ssid->passphrase;
+       } else
+               p_pass = "";
+
+       return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
+                                               &p_pass, error);
+
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
+                                          DBusError *error, void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       u8 role = wpas_get_p2p_role(wpa_s);
+       u8 *p_psk = NULL;
+       u8 psk_len = 0;
+
+       /* Verify correct role for this property */
+       if (role == WPAS_P2P_ROLE_CLIENT) {
+               if (wpa_s->current_ssid == NULL)
+                       return FALSE;
+               p_psk = wpa_s->current_ssid->psk;
+               psk_len = 32;
+       }
+
+       return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+                                                     &p_psk, psk_len, error);
+}
+
+
+dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
+                                                 DBusError *error,
+                                                 void *user_data)
+{
+       struct wpa_supplicant *wpa_s = user_data;
+       struct hostapd_data *hapd;
+       struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
+       unsigned int i, num_vendor_ext = 0;
+
+       os_memset(vendor_ext, 0, sizeof(vendor_ext));
+
+       /* Verify correct role for this property */
+       if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
+               if (wpa_s->ap_iface == NULL)
+                       return FALSE;
+               hapd = wpa_s->ap_iface->bss[0];
+
                /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
-               for (i = 0; hapd && i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+               for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
                        if (hapd->conf->wps_vendor_ext[i] == NULL)
                                continue;
                        vendor_ext[num_vendor_ext++] =
                                hapd->conf->wps_vendor_ext[i];
                }
-               if (!wpa_dbus_dict_append_wpabuf_array(&dict_iter,
-                                       "WPSVendorExtensions",
-                                       vendor_ext, num_vendor_ext))
-                       goto err_no_mem;
-       } else {
-               /* If not a GO, provide the PSK */
-               if (!wpa_dbus_dict_append_byte_array(
-                           &dict_iter, "PSK",
-                           (const char *) wpa_s->current_ssid->psk, 32))
-                       goto err_no_mem;
        }
 
-       if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
-           !dbus_message_iter_close_container(iter, &variant_iter))
-               goto err_no_mem;
-
-       return TRUE;
-
-err_no_mem:
-       dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory");
-       return FALSE;
+       /* Return vendor extensions or no data */
+       return wpas_dbus_simple_array_array_property_getter(iter,
+                                                           DBUS_TYPE_BYTE,
+                                                           vendor_ext,
+                                                           num_vendor_ext,
+                                                           error);
 }
 
 
-dbus_bool_t wpas_dbus_setter_p2p_group_properties(DBusMessageIter *iter,
+dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
                                                  DBusError *error,
                                                  void *user_data)
 {
        struct wpa_supplicant *wpa_s = user_data;
-       DBusMessageIter variant_iter, iter_dict;
+       DBusMessageIter variant_iter, iter_dict, array_iter, sub;
        struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
        unsigned int i;
        struct hostapd_data *hapd = NULL;
@@ -1917,6 +2197,82 @@ dbus_bool_t wpas_dbus_setter_p2p_group_properties(DBusMessageIter *iter,
                return FALSE;
 
        dbus_message_iter_recurse(iter, &variant_iter);
+       if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY)
+               return FALSE;
+
+       /*
+        * This is supposed to be array of bytearrays (aay), but the earlier
+        * implementation used a dict with "WPSVendorExtensions" as the key in
+        * this setter function which does not match the format used by the
+        * getter function. For backwards compatibility, allow both formats to
+        * be used in the setter.
+        */
+       if (dbus_message_iter_get_element_type(&variant_iter) ==
+           DBUS_TYPE_ARRAY) {
+               /* This is the proper format matching the getter */
+               struct wpabuf *vals[MAX_WPS_VENDOR_EXTENSIONS];
+
+               dbus_message_iter_recurse(&variant_iter, &array_iter);
+
+               if (dbus_message_iter_get_arg_type(&array_iter) !=
+                   DBUS_TYPE_ARRAY ||
+                   dbus_message_iter_get_element_type(&array_iter) !=
+                   DBUS_TYPE_BYTE) {
+                       wpa_printf(MSG_DEBUG,
+                                  "dbus: Not an array of array of bytes");
+                       return FALSE;
+               }
+
+               i = 0;
+               os_memset(vals, 0, sizeof(vals));
+
+               while (dbus_message_iter_get_arg_type(&array_iter) ==
+                      DBUS_TYPE_ARRAY) {
+                       char *val;
+                       int len;
+
+                       if (i == MAX_WPS_VENDOR_EXTENSIONS) {
+                               wpa_printf(MSG_DEBUG,
+                                          "dbus: Too many WPSVendorExtensions values");
+                               i = MAX_WPS_VENDOR_EXTENSIONS + 1;
+                               break;
+                       }
+
+                       dbus_message_iter_recurse(&array_iter, &sub);
+                       dbus_message_iter_get_fixed_array(&sub, &val, &len);
+                       wpa_hexdump(MSG_DEBUG, "dbus: WPSVendorExtentions[]",
+                                   val, len);
+                       vals[i] = wpabuf_alloc_copy(val, len);
+                       if (vals[i] == NULL) {
+                               i = MAX_WPS_VENDOR_EXTENSIONS + 1;
+                               break;
+                       }
+                       i++;
+                       dbus_message_iter_next(&array_iter);
+               }
+
+               if (i > MAX_WPS_VENDOR_EXTENSIONS) {
+                       for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
+                               wpabuf_free(vals[i]);
+                       return FALSE;
+               }
+
+               for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+                       wpabuf_free(hapd->conf->wps_vendor_ext[i]);
+                       hapd->conf->wps_vendor_ext[i] = vals[i];
+               }
+
+               hostapd_update_wps(hapd);
+
+               return TRUE;
+       }
+
+       if (dbus_message_iter_get_element_type(&variant_iter) !=
+           DBUS_TYPE_DICT_ENTRY)
+               return FALSE;
+
+       wpa_printf(MSG_DEBUG,
+                  "dbus: Try to use backwards compatibility version of WPSVendorExtensions setter");
        if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict, error))
                return FALSE;
 
@@ -1934,6 +2290,7 @@ dbus_bool_t wpas_dbus_setter_p2p_group_properties(DBusMessageIter *iter,
                                goto error;
 
                        for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+                               wpabuf_free(hapd->conf->wps_vendor_ext[i]);
                                if (i < entry.array_len) {
                                        hapd->conf->wps_vendor_ext[i] =
                                                entry.binarray_value[i];
@@ -1978,7 +2335,7 @@ DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
        if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL))
                goto error;
 
-       if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
                if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
                        goto error;
 
@@ -1990,68 +2347,56 @@ DBusMessage * wpas_dbus_handler_p2p_add_service(DBusMessage *message,
                                bonjour = 1;
                        else
                                goto error_clear;
-                       wpa_dbus_dict_entry_clear(&entry);
+               } else if (!os_strcmp(entry.key, "version") &&
+                          entry.type == DBUS_TYPE_INT32) {
+                       version = entry.uint32_value;
+               } else if (!os_strcmp(entry.key, "service") &&
+                            (entry.type == DBUS_TYPE_STRING)) {
+                       os_free(service);
+                       service = os_strdup(entry.str_value);
+               } else if (!os_strcmp(entry.key, "query")) {
+                       if ((entry.type != DBUS_TYPE_ARRAY) ||
+                           (entry.array_type != DBUS_TYPE_BYTE))
+                               goto error_clear;
+                       query = wpabuf_alloc_copy(
+                               entry.bytearray_value,
+                               entry.array_len);
+               } else if (!os_strcmp(entry.key, "response")) {
+                       if ((entry.type != DBUS_TYPE_ARRAY) ||
+                           (entry.array_type != DBUS_TYPE_BYTE))
+                               goto error_clear;
+                       resp = wpabuf_alloc_copy(entry.bytearray_value,
+                                                entry.array_len);
                }
+               wpa_dbus_dict_entry_clear(&entry);
        }
 
        if (upnp == 1) {
-               while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
-                       if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
-                               goto error;
-
-                       if (!os_strcmp(entry.key, "version") &&
-                           entry.type == DBUS_TYPE_INT32)
-                               version = entry.uint32_value;
-                       else if (!os_strcmp(entry.key, "service") &&
-                                entry.type == DBUS_TYPE_STRING)
-                               service = os_strdup(entry.str_value);
-                       wpa_dbus_dict_entry_clear(&entry);
-               }
                if (version <= 0 || service == NULL)
                        goto error;
 
                if (wpas_p2p_service_add_upnp(wpa_s, version, service) != 0)
                        goto error;
 
-               os_free(service);
        } else if (bonjour == 1) {
-               while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
-                       if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
-                               goto error;
-
-                       if (!os_strcmp(entry.key, "query")) {
-                               if ((entry.type != DBUS_TYPE_ARRAY) ||
-                                   (entry.array_type != DBUS_TYPE_BYTE))
-                                       goto error_clear;
-                               query = wpabuf_alloc_copy(
-                                       entry.bytearray_value,
-                                       entry.array_len);
-                       } else if (!os_strcmp(entry.key, "response")) {
-                               if ((entry.type != DBUS_TYPE_ARRAY) ||
-                                   (entry.array_type != DBUS_TYPE_BYTE))
-                                       goto error_clear;
-                               resp = wpabuf_alloc_copy(entry.bytearray_value,
-                                                        entry.array_len);
-                       }
-
-                       wpa_dbus_dict_entry_clear(&entry);
-               }
-
                if (query == NULL || resp == NULL)
                        goto error;
 
-               if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0) {
-                       wpabuf_free(query);
-                       wpabuf_free(resp);
+               if (wpas_p2p_service_add_bonjour(wpa_s, query, resp) < 0)
                        goto error;
-               }
+               query = NULL;
+               resp = NULL;
        } else
                goto error;
 
+       os_free(service);
        return reply;
 error_clear:
        wpa_dbus_dict_entry_clear(&entry);
 error:
+       os_free(service);
+       wpabuf_free(query);
+       wpabuf_free(resp);
        return wpas_dbus_error_invalid_args(message, NULL);
 }
 
@@ -2098,9 +2443,10 @@ DBusMessage * wpas_dbus_handler_p2p_delete_service(
                            entry.type == DBUS_TYPE_INT32)
                                version = entry.uint32_value;
                        else if (!os_strcmp(entry.key, "service") &&
-                                entry.type == DBUS_TYPE_STRING)
+                                entry.type == DBUS_TYPE_STRING) {
+                               os_free(service);
                                service = os_strdup(entry.str_value);
-                       else
+                       else
                                goto error_clear;
 
                        wpa_dbus_dict_entry_clear(&entry);
@@ -2110,7 +2456,6 @@ DBusMessage * wpas_dbus_handler_p2p_delete_service(
                        goto error;
 
                ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
-               os_free(service);
                if (ret != 0)
                        goto error;
        } else if (bonjour == 1) {
@@ -2122,6 +2467,7 @@ DBusMessage * wpas_dbus_handler_p2p_delete_service(
                                if ((entry.type != DBUS_TYPE_ARRAY) ||
                                    (entry.array_type != DBUS_TYPE_BYTE))
                                        goto error_clear;
+                               wpabuf_free(query);
                                query = wpabuf_alloc_copy(
                                        entry.bytearray_value,
                                        entry.array_len);
@@ -2137,14 +2483,17 @@ DBusMessage * wpas_dbus_handler_p2p_delete_service(
                ret = wpas_p2p_service_del_bonjour(wpa_s, query);
                if (ret != 0)
                        goto error;
-               wpabuf_free(query);
        } else
                goto error;
 
+       wpabuf_free(query);
+       os_free(service);
        return reply;
 error_clear:
        wpa_dbus_dict_entry_clear(&entry);
 error:
+       wpabuf_free(query);
+       os_free(service);
        return wpas_dbus_error_invalid_args(message, NULL);
 }
 
@@ -2170,7 +2519,7 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
        struct wpabuf *tlv = NULL;
        u8 version = 0;
        u64 ref = 0;
-       u8 addr[ETH_ALEN];
+       u8 addr_buf[ETH_ALEN], *addr;
 
        dbus_message_iter_init(message, &iter);
 
@@ -2207,10 +2556,15 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_req(
                wpa_dbus_dict_entry_clear(&entry);
        }
 
-       if (!peer_object_path ||
-           (parse_peer_object_path(peer_object_path, addr) < 0) ||
-           !p2p_peer_known(wpa_s->global->p2p, addr))
-               goto error;
+       if (!peer_object_path) {
+               addr = NULL;
+       } else {
+               if (parse_peer_object_path(peer_object_path, addr_buf) < 0 ||
+                   !p2p_peer_known(wpa_s->global->p2p, addr_buf))
+                       goto error;
+
+               addr = addr_buf;
+       }
 
        if (upnp == 1) {
                if (version <= 0 || service == NULL)
@@ -2275,7 +2629,8 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_res(
                           entry.type == DBUS_TYPE_INT32) {
                        freq = entry.uint32_value;
                } else if (!os_strcmp(entry.key, "dialog_token") &&
-                          entry.type == DBUS_TYPE_UINT32) {
+                          (entry.type == DBUS_TYPE_UINT32 ||
+                           entry.type == DBUS_TYPE_INT32)) {
                        dlg_tok = entry.uint32_value;
                } else if (!os_strcmp(entry.key, "tlvs")) {
                        if (entry.type != DBUS_TYPE_ARRAY ||
@@ -2321,7 +2676,7 @@ DBusMessage * wpas_dbus_handler_p2p_service_sd_cancel_req(
        if (req == 0)
                goto error;
 
-       if (!wpas_p2p_sd_cancel_request(wpa_s, req))
+       if (wpas_p2p_sd_cancel_request(wpa_s, req) < 0)
                goto error;
 
        return NULL;
@@ -2352,3 +2707,77 @@ DBusMessage * wpas_dbus_handler_p2p_serv_disc_external(
        return NULL;
 
 }
+
+
+#ifdef CONFIG_WIFI_DISPLAY
+
+dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
+                                           DBusError *error, void *user_data)
+{
+       struct wpa_global *global = user_data;
+       struct wpabuf *ie;
+       dbus_bool_t ret;
+
+       ie = wifi_display_get_wfd_ie(global);
+       if (ie == NULL)
+               return wpas_dbus_simple_array_property_getter(iter,
+                                                             DBUS_TYPE_BYTE,
+                                                             NULL, 0, error);
+
+       ret = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
+                                                    wpabuf_head(ie),
+                                                    wpabuf_len(ie), error);
+       wpabuf_free(ie);
+
+       return ret;
+}
+
+
+dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
+                                           DBusError *error, void *user_data)
+{
+       struct wpa_global *global = user_data;
+       DBusMessageIter variant, array;
+       struct wpabuf *ie = NULL;
+       const u8 *data;
+       int len;
+
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT)
+               goto err;
+
+       dbus_message_iter_recurse(iter, &variant);
+       if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
+               goto err;
+
+       dbus_message_iter_recurse(&variant, &array);
+       dbus_message_iter_get_fixed_array(&array, &data, &len);
+       if (len == 0) {
+               wifi_display_enable(global, 0);
+               wifi_display_deinit(global);
+
+               return TRUE;
+       }
+
+       ie = wpabuf_alloc(len);
+       if (ie == NULL)
+               goto err;
+
+       wpabuf_put_data(ie, data, len);
+       if (wifi_display_subelem_set_from_ies(global, ie) != 0)
+               goto err;
+
+       if (global->wifi_display == 0)
+               wifi_display_enable(global, 1);
+
+       wpabuf_free(ie);
+
+       return TRUE;
+err:
+       wpabuf_free(ie);
+
+       dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
+                            "invalid message format");
+       return FALSE;
+}
+
+#endif /* CONFIG_WIFI_DISPLAY */