DBus: Add support for P2P primitives
authorJohannes Berg <johannes.berg@intel.com>
Sun, 12 Jun 2011 22:08:19 +0000 (15:08 -0700)
committerJouni Malinen <j@w1.fi>
Sun, 12 Jun 2011 22:08:19 +0000 (15:08 -0700)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
wpa_supplicant/Makefile
wpa_supplicant/dbus/dbus_new.c
wpa_supplicant/dbus/dbus_new.h
wpa_supplicant/dbus/dbus_new_handlers_p2p.c [new file with mode: 0644]
wpa_supplicant/dbus/dbus_new_handlers_p2p.h [new file with mode: 0644]
wpa_supplicant/notify.c
wpa_supplicant/wpa_supplicant_i.h

index aeb9ab9..ec2d350 100644 (file)
@@ -1140,6 +1140,9 @@ DBUS_OBJS += dbus/dbus_new.o dbus/dbus_new_handlers.o
 ifdef CONFIG_WPS
 DBUS_OBJS += dbus/dbus_new_handlers_wps.o
 endif
+ifdef CONFIG_P2P
+DBUS_OBJS += dbus/dbus_new_handlers_p2p.o
+endif
 ifndef DBUS_LIBS
 DBUS_LIBS := $(shell pkg-config --libs dbus-1)
 endif
index 49a0895..1340f50 100644 (file)
@@ -17,6 +17,7 @@
 #include "includes.h"
 
 #include "common.h"
+#include "common/ieee802_11_defs.h"
 #include "wps/wps.h"
 #include "../config.h"
 #include "../wpa_supplicant_i.h"
@@ -27,6 +28,8 @@
 #include "dbus_new_handlers.h"
 #include "dbus_common.h"
 #include "dbus_common_i.h"
+#include "dbus_new_handlers_p2p.h"
+#include "p2p/p2p.h"
 
 
 /**
@@ -650,904 +653,2241 @@ nomem:
 
 #endif /* CONFIG_WPS */
 
+#ifdef CONFIG_P2P
 
 /**
- * wpas_dbus_signal_prop_changed - Signals change of property
+ * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
  * @wpa_s: %wpa_supplicant network interface data
- * @property: indicates which property has changed
- *
- * Sends ProertyChanged signals with path, interface and arguments
- * depending on which property has changed.
+ * @role: role of this device (client or GO)
+ * Sends signal with i/f name and role as string arguments
  */
-void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
-                                  enum wpas_dbus_prop property)
+void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
+                                       const char *role)
 {
-       WPADBusPropertyAccessor getter;
-       char *prop;
 
-       if (wpa_s->dbus_new_path == NULL)
-               return; /* Skip signal since D-Bus setup is not yet ready */
+       DBusMessage *msg;
+       DBusMessageIter iter;
+       struct wpas_dbus_priv *iface = wpa_s->global->dbus;
+       char *ifname = wpa_s->ifname;
 
-       switch (property) {
-       case WPAS_DBUS_PROP_AP_SCAN:
-               getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
-               prop = "ApScan";
-               break;
-       case WPAS_DBUS_PROP_SCANNING:
-               getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
-               prop = "Scanning";
-               break;
-       case WPAS_DBUS_PROP_STATE:
-               getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state;
-               prop = "State";
-               break;
-       case WPAS_DBUS_PROP_CURRENT_BSS:
-               getter = (WPADBusPropertyAccessor)
-                       wpas_dbus_getter_current_bss;
-               prop = "CurrentBSS";
-               break;
-       case WPAS_DBUS_PROP_CURRENT_NETWORK:
-               getter = (WPADBusPropertyAccessor)
-                       wpas_dbus_getter_current_network;
-               prop = "CurrentNetwork";
-               break;
-       case WPAS_DBUS_PROP_BSSS:
-               getter = (WPADBusPropertyAccessor) wpas_dbus_getter_bsss;
-               prop = "BSSs";
-               break;
-       case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
-               getter = (WPADBusPropertyAccessor)
-                       wpas_dbus_getter_current_auth_mode;
-               prop = "CurrentAuthMode";
-               break;
-       default:
-               wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
-                          __func__, property);
+       /* Do nothing if the control interface is not turned on */
+       if (iface == NULL)
+               return;
+
+       msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+                                     WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                                     "GroupFinished");
+       if (msg == NULL)
                return;
+
+       dbus_message_iter_init_append(msg, &iter);
+
+       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname)) {
+               wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
+                                     "signal -not enough memory for ifname ");
+               goto err;
        }
 
-       wpa_dbus_mark_property_changed(wpa_s->global->dbus,
-                                      wpa_s->dbus_new_path,
-                                      WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
+       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &role))
+               wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
+                                     "signal -not enough memory for role ");
+       else
+               dbus_connection_send(iface->con, msg, NULL);
+
+err:
+       dbus_message_unref(msg);
 }
 
 
 /**
- * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
- * @wpa_s: %wpa_supplicant network interface data
- * @property: indicates which property has changed
- * @id: unique BSS identifier
+ * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
  *
- * Sends PropertyChanged signals with path, interface, and arguments depending
- * on which property has changed.
+ * @dev_addr - who sent the request or responded to our request.
+ * @request - Will be 1 if request, 0 for response.
+ * @status - valid only in case of response
+ * @config_methods - wps config methods
+ * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
+ *
+ * Sends following provision discovery related events:
+ *     ProvisionDiscoveryRequestDisplayPin
+ *     ProvisionDiscoveryResponseDisplayPin
+ *     ProvisionDiscoveryRequestEnterPin
+ *     ProvisionDiscoveryResponseEnterPin
+ *     ProvisionDiscoveryPBCRequest
+ *     ProvisionDiscoveryPBCResponse
+ *
+ *     TODO::
+ *     ProvisionDiscoveryFailure (timeout case)
  */
-void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
-                                      enum wpas_dbus_bss_prop property,
-                                      unsigned int id)
+void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
+                                             const u8 *dev_addr, int request,
+                                             enum p2p_prov_disc_status status,
+                                             u16 config_methods,
+                                             unsigned int generated_pin)
 {
-       char path[WPAS_DBUS_OBJECT_PATH_MAX];
-       char *prop;
+       DBusMessage *msg;
+       DBusMessageIter iter;
+       struct wpas_dbus_priv *iface;
+       char *_signal;
+       int add_pin = 0;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+       int error_ret = 1;
+       char pin[9], *p_pin = NULL;
 
-       switch (property) {
-       case WPAS_DBUS_BSS_PROP_SIGNAL:
-               prop = "Signal";
-               break;
-       case WPAS_DBUS_BSS_PROP_FREQ:
-               prop = "Frequency";
-               break;
-       case WPAS_DBUS_BSS_PROP_MODE:
-               prop = "Mode";
-               break;
-       case WPAS_DBUS_BSS_PROP_PRIVACY:
-               prop = "Privacy";
-               break;
-       case WPAS_DBUS_BSS_PROP_RATES:
-               prop = "Rates";
-               break;
-       case WPAS_DBUS_BSS_PROP_WPA:
-               prop = "WPA";
-               break;
-       case WPAS_DBUS_BSS_PROP_RSN:
-               prop = "RSN";
-               break;
-       case WPAS_DBUS_BSS_PROP_IES:
-               prop = "IEs";
-               break;
-       default:
-               wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
-                          __func__, property);
+       iface = wpa_s->global->dbus;
+
+       /* Do nothing if the control interface is not turned on */
+       if (iface == NULL)
                return;
+
+       if (request || !status) {
+               if (config_methods & WPS_CONFIG_DISPLAY)
+                       _signal = request ?
+                                "ProvisionDiscoveryRequestDisplayPin" :
+                                "ProvisionDiscoveryResponseEnterPin";
+               else if (config_methods & WPS_CONFIG_KEYPAD)
+                       _signal = request ?
+                                "ProvisionDiscoveryRequestEnterPin" :
+                                "ProvisionDiscoveryResponseDisplayPin";
+               else if (config_methods & WPS_CONFIG_PUSHBUTTON)
+                       _signal = request ? "ProvisionDiscoveryPBCRequest" :
+                                  "ProvisionDiscoveryPBCResponse";
+               else
+                       return; /* Unknown or un-supported method */
+       } else if (!request && status)
+               /* Explicit check for failure response */
+               _signal = "ProvisionDiscoveryFailure";
+
+       add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
+                  (!request && !status &&
+                       (config_methods & WPS_CONFIG_KEYPAD)));
+
+       if (add_pin) {
+               os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
+               p_pin = pin;
        }
 
-       os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
-                   "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
-                   wpa_s->dbus_new_path, id);
+       msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+                                     WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
+       if (msg == NULL)
+               return;
 
-       wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
-                                      WPAS_DBUS_NEW_IFACE_BSS, prop);
+       /* Check if this is a known peer */
+       if (p2p_get_peer_info(wpa_s->global->p2p, dev_addr, 0, NULL, 0) < 0)
+               goto error;
+
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                       "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
+                       COMPACT_MACSTR,
+                       wpa_s->dbus_new_path, MAC2STR(dev_addr));
+
+       path = peer_obj_path;
+
+       dbus_message_iter_init_append(msg, &iter);
+
+       if (!dbus_message_iter_append_basic(&iter,
+                                           DBUS_TYPE_OBJECT_PATH,
+                                           &path))
+                       goto error;
+
+       if (!request && status)
+               /* Attach status to ProvisionDiscoveryFailure */
+               error_ret = !dbus_message_iter_append_basic(&iter,
+                                                   DBUS_TYPE_INT32,
+                                                   &status);
+       else
+               error_ret = (add_pin &&
+                                !dbus_message_iter_append_basic(&iter,
+                                                       DBUS_TYPE_STRING,
+                                                       &p_pin));
+
+error:
+       if (!error_ret)
+               dbus_connection_send(iface->con, msg, NULL);
+       else
+               wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+
+       dbus_message_unref(msg);
 }
 
 
-/**
- * wpas_dbus_signal_debug_level_changed - Signals change of debug param
- * @global: wpa_global structure
- *
- * Sends ProertyChanged signals informing that debug level has changed.
- */
-void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
+void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
+                                    const u8 *src, u16 dev_passwd_id)
 {
-       wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
-                                      WPAS_DBUS_NEW_INTERFACE,
-                                      "DebugLevel");
+       DBusMessage *msg;
+       DBusMessageIter iter;
+       struct wpas_dbus_priv *iface;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+
+       iface = wpa_s->global->dbus;
+
+       /* Do nothing if the control interface is not turned on */
+       if (iface == NULL)
+               return;
+
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
+                   wpa_s->dbus_new_path, MAC2STR(src));
+       path = peer_obj_path;
+
+       msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+                                     WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                                     "GONegotiationRequest");
+       if (msg == NULL)
+               return;
+
+       dbus_message_iter_init_append(msg, &iter);
+
+       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+                                           &path) ||
+           !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
+                                           &dev_passwd_id))
+               wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+       else
+               dbus_connection_send(iface->con, msg, NULL);
+
+       dbus_message_unref(msg);
 }
 
 
-/**
- * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
- * @global: wpa_global structure
- *
- * Sends ProertyChanged signals informing that debug timestamp has changed.
- */
-void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
+static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
+                                       const struct wpa_ssid *ssid,
+                                       char *group_obj_path)
 {
-       wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
-                                      WPAS_DBUS_NEW_INTERFACE,
-                                      "DebugTimestamp");
+       char group_name[3];
+
+       if (os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
+               return -1;
+
+       memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
+       group_name[2] = '\0';
+
+       os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
+                   wpa_s->dbus_new_path, group_name);
+
+       return 0;
 }
 
 
 /**
- * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
- * @global: wpa_global structure
+ * wpas_dbus_signal_p2p_group_started - Signals P2P group has
+ * started.Emitted when a group is succesfully started
+ * irrespective of the role (client/GO) of the current device
  *
- * Sends ProertyChanged signals informing that debug show_keys has changed.
+ * @wpa_s: %wpa_supplicant network interface data
+ * @ssid: SSID object
+ * @client: this device is P2P client
+ * @network_id: network id of the group started, use instead of ssid->id
+ *     to account for persistent groups
  */
-void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
+void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
+                                       const struct wpa_ssid *ssid,
+                                       int client, int network_id)
 {
-       wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
-                                      WPAS_DBUS_NEW_INTERFACE,
-                                      "DebugShowKeys");
-}
+       DBusMessage *msg;
+       DBusMessageIter iter, dict_iter;
+       struct wpas_dbus_priv *iface;
+       char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+       char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
 
+       iface = wpa_s->parent->global->dbus;
 
-static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
-                              void *priv,
-                              WPADBusArgumentFreeFunction priv_free,
-                              const struct wpa_dbus_method_desc *methods,
-                              const struct wpa_dbus_property_desc *properties,
-                              const struct wpa_dbus_signal_desc *signals)
-{
-       int n;
+       /* Do nothing if the control interface is not turned on */
+       if (iface == NULL)
+               return;
 
-       obj_desc->user_data = priv;
-       obj_desc->user_data_free_func = priv_free;
-       obj_desc->methods = methods;
-       obj_desc->properties = properties;
-       obj_desc->signals = signals;
+       if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
+               return;
 
-       for (n = 0; properties && properties->dbus_property; properties++)
-               n++;
+       /* New interface has been created for this group */
+       msg = dbus_message_new_signal(wpa_s->parent->dbus_new_path,
+                                     WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                                     "GroupStarted");
 
-       obj_desc->prop_changed_flags = os_zalloc(n);
-       if (!obj_desc->prop_changed_flags)
-               wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
-                          __func__);
-}
+       if (msg == NULL)
+               return;
 
+       dbus_message_iter_init_append(msg, &iter);
+       if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
+               goto nomem;
 
-static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
-       { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
-         {
-                 { "args", "a{sv}", ARG_IN },
-                 { "path", "o", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
-         {
-                 { "path", "o", ARG_IN },
-                 END_ARGS
-         }
-       },
-       { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
-         {
-                 { "ifname", "s", ARG_IN },
-                 { "path", "o", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { NULL, NULL, NULL, { END_ARGS } }
-};
+       /*
+        * In case the device supports creating a separate interface the
+        * DBus client will need to know the object path for the interface
+        * object this group was created on, so include it here.
+        */
+       if (!wpa_dbus_dict_append_object_path(&dict_iter,
+                                       "interface_object",
+                                       wpa_s->dbus_new_path))
+               goto nomem;
 
-static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
-       { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
-         RW
-       },
-       { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
-         RW
-       },
-       { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
-         RW
-       },
-       { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
-         (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
-         NULL,
-         R
-       },
-       { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
-         NULL,
-         R
-       },
-       { NULL, NULL, NULL, NULL, NULL, 0 }
-};
+       if (!wpa_dbus_dict_append_string(&dict_iter, "role",
+                                        client ? "client" : "GO"))
+               goto nomem;
 
-static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
-       { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
-         {
-                 { "path", "o", ARG_OUT },
-                 { "properties", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
-         {
-                 { "path", "o", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
-         {
-                 { "properties", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { NULL, NULL, { END_ARGS } }
-};
+       os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
+                   wpa_s->parent->dbus_new_path, network_id);
+
+       if (!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
+                                            group_obj_path) ||
+          !wpa_dbus_dict_append_object_path(&dict_iter, "network_object",
+                                            net_obj_path) ||
+          !wpa_dbus_dict_close_write(&iter, &dict_iter))
+               goto nomem;
+
+       dbus_connection_send(iface->con, msg, NULL);
+
+nomem:
+       dbus_message_unref(msg);
+}
 
 
 /**
- * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
- * @global: Pointer to global data from wpa_supplicant_init()
- * Returns: 0 on success or -1 on failure
  *
- * Initialize the dbus control interface for wpa_supplicantand and start
- * receiving commands from external programs over the bus.
+ * Method to emit GONeogtiation Success or Failure signals based
+ * on status.
+ * @status: Status of the GO neg request. 0 for success, other for errors.
  */
-int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
+void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s, int status)
 {
-       struct wpa_dbus_object_desc *obj_desc;
-       int ret;
+       DBusMessage *msg;
+       DBusMessageIter iter;
+       struct wpas_dbus_priv *iface;
 
-       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
-       if (!obj_desc) {
-               wpa_printf(MSG_ERROR, "Not enough memory "
-                          "to create object description");
-               return -1;
-       }
+       iface = wpa_s->global->dbus;
 
-       wpas_dbus_register(obj_desc, priv->global, NULL,
-                          wpas_dbus_global_methods,
-                          wpas_dbus_global_properties,
-                          wpas_dbus_global_signals);
+       /* Do nothing if the control interface is not turned on */
+       if (iface == NULL)
+               return;
 
-       wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
-                  WPAS_DBUS_NEW_PATH);
-       ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
-                                      WPAS_DBUS_NEW_SERVICE,
-                                      obj_desc);
-       if (ret < 0)
-               free_dbus_object_desc(obj_desc);
-       else
-               priv->dbus_new_initialized = 1;
+       msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+                                     WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                                     status ? "GONegotiationFailure" :
+                                              "GONegotiationSuccess");
+       if (msg == NULL)
+               return;
 
-       return ret;
+       if (status) {
+               dbus_message_iter_init_append(msg, &iter);
+               if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
+                                                   &status)) {
+                       wpa_printf(MSG_ERROR,
+                                  "dbus: Failed to construct signal");
+                       goto err;
+               }
+       }
+
+       dbus_connection_send(iface->con, msg, NULL);
+err:
+       dbus_message_unref(msg);
 }
 
 
 /**
- * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
- * wpa_supplicant
- * @iface: Pointer to dbus private data from wpas_dbus_init()
  *
- * Deinitialize the dbus control interface that was initialized with
- * wpas_dbus_ctrl_iface_init().
+ * Method to emit Invitation Result signal based on status and
+ * bssid
+ * @status: Status of the Invite request. 0 for success, other
+ * for errors
+ * @bssid : Basic Service Set Identifier
  */
-void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
+void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
+                                           int status, const u8 *bssid)
 {
-       if (!iface->dbus_new_initialized)
+       DBusMessage *msg;
+       DBusMessageIter iter, dict_iter;
+       struct wpas_dbus_priv *iface;
+
+       wpa_printf(MSG_INFO, "%s\n", __func__);
+
+       iface = wpa_s->global->dbus;
+       /* Do nothing if the control interface is not turned on */
+       if (iface == NULL)
                return;
-       wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
-                  WPAS_DBUS_NEW_PATH);
-       dbus_connection_unregister_object_path(iface->con,
-                                              WPAS_DBUS_NEW_PATH);
-}
 
+       msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+                                     WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                                     "InvitationResult");
 
-static void wpa_dbus_free(void *ptr)
-{
-       os_free(ptr);
-}
+       if (msg == NULL)
+               return;
 
+       dbus_message_iter_init_append(msg, &iter);
+       if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
+               goto nomem;
 
-static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
-       { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
-         RW
-       },
-       { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
-         RW
-       },
-       { NULL, NULL, NULL, NULL, NULL, 0 }
-};
+       if (!wpa_dbus_dict_append_int32(&dict_iter, "status", status))
+               goto nomem;
+       if (bssid) {
+               if (!wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
+                                                    (const char *) bssid,
+                                                    ETH_ALEN))
+                       goto nomem;
+       }
+       if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
+               goto nomem;
 
+       dbus_connection_send(iface->con, msg, NULL);
 
-static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
-       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
-         {
-                 { "properties", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { NULL, NULL, { END_ARGS } }
-};
+nomem:
+       dbus_message_unref(msg);
+}
 
 
 /**
- * wpas_dbus_register_network - Register a configured network with dbus
- * @wpa_s: wpa_supplicant interface structure
- * @ssid: network configuration data
- * Returns: 0 on success, -1 on failure
  *
- * Registers network representing object with dbus
+ * Method to emit a signal for a peer joining the group.
+ * The signal will carry path to the group member object
+ * constructed using p2p i/f addr used for connecting.
+ *
+ * @wpa_s: %wpa_supplicant network interface data
+ * @member_addr: addr (p2p i/f) of the peer joining the group
  */
-int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
-                              struct wpa_ssid *ssid)
+void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
+                                     const u8 *member)
 {
-       struct wpas_dbus_priv *ctrl_iface;
-       struct wpa_dbus_object_desc *obj_desc;
-       struct network_handler_args *arg;
-       char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
-
-       /* Do nothing if the control interface is not turned on */
-       if (wpa_s == NULL || wpa_s->global == NULL)
-               return 0;
-       ctrl_iface = wpa_s->global->dbus;
-       if (ctrl_iface == NULL)
-               return 0;
+       struct wpas_dbus_priv *iface;
+       DBusMessage *msg;
+       DBusMessageIter iter;
+       char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
 
-       os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-                   "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
-                   wpa_s->dbus_new_path, ssid->id);
+       iface = wpa_s->global->dbus;
 
-       wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
-                  net_obj_path);
-       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
-       if (!obj_desc) {
-               wpa_printf(MSG_ERROR, "Not enough memory "
-                          "to create object description");
-               goto err;
-       }
+       /* Do nothing if the control interface is not turned on */
+       if (iface == NULL)
+               return;
 
-       /* allocate memory for handlers arguments */
-       arg = os_zalloc(sizeof(struct network_handler_args));
-       if (!arg) {
-               wpa_printf(MSG_ERROR, "Not enough memory "
-                          "to create arguments for method");
-               goto err;
-       }
+       if (!wpa_s->dbus_groupobj_path)
+               return;
 
-       arg->wpa_s = wpa_s;
-       arg->ssid = ssid;
+       os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                       "%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
+                       COMPACT_MACSTR,
+                       wpa_s->dbus_groupobj_path, MAC2STR(member));
 
-       wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
-                          wpas_dbus_network_properties,
-                          wpas_dbus_network_signals);
+       msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
+                                     WPAS_DBUS_NEW_IFACE_P2P_GROUP,
+                                     "PeerJoined");
+       if (msg == NULL)
+               return;
 
-       if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
-                                              wpa_s->ifname, obj_desc))
+       dbus_message_iter_init_append(msg, &iter);
+       path = groupmember_obj_path;
+       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+                                           &path))
                goto err;
 
-       wpas_dbus_signal_network_added(wpa_s, ssid->id);
+       dbus_connection_send(iface->con, msg, NULL);
 
-       return 0;
+       dbus_message_unref(msg);
+       return;
 
 err:
-       free_dbus_object_desc(obj_desc);
-       return -1;
+       wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+       dbus_message_unref(msg);
 }
 
 
 /**
- * wpas_dbus_unregister_network - Unregister a configured network from dbus
- * @wpa_s: wpa_supplicant interface structure
- * @nid: network id
- * Returns: 0 on success, -1 on failure
  *
- * Unregisters network representing object from dbus
+ * Method to emit a signal for a peer disconnecting the group.
+ * The signal will carry path to the group member object
+ * constructed using p2p i/f addr used for connecting.
+ *
+ * @wpa_s: %wpa_supplicant network interface data
+ * @member_addr: addr (p2p i/f) of the peer joining the group
  */
-int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
+void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
+                                     const u8 *member)
 {
-       struct wpas_dbus_priv *ctrl_iface;
-       char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
-       int ret;
+       struct wpas_dbus_priv *iface;
+       DBusMessage *msg;
+       DBusMessageIter iter;
+       char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+
+       iface = wpa_s->global->dbus;
 
        /* Do nothing if the control interface is not turned on */
-       if (wpa_s == NULL || wpa_s->global == NULL ||
-           wpa_s->dbus_new_path == NULL)
-               return 0;
-       ctrl_iface = wpa_s->global->dbus;
-       if (ctrl_iface == NULL)
-               return 0;
+       if (iface == NULL)
+               return;
 
-       os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-                   "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
-                   wpa_s->dbus_new_path, nid);
+       if (!wpa_s->dbus_groupobj_path)
+               return;
 
-       wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
-                  net_obj_path);
-       ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
+       os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                       "%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
+                       COMPACT_MACSTR,
+                       wpa_s->dbus_groupobj_path, MAC2STR(member));
 
-       if (!ret)
-               wpas_dbus_signal_network_removed(wpa_s, nid);
-
-       return ret;
-}
+       msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
+                                     WPAS_DBUS_NEW_IFACE_P2P_GROUP,
+                                     "PeerDisconnected");
+       if (msg == NULL)
+               return;
 
+       dbus_message_iter_init_append(msg, &iter);
+       path = groupmember_obj_path;
+       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+                                           &path))
+               goto err;
 
-static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
-       { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
-         NULL,
-         R
-       },
-       { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
-         NULL,
-         R
-       },
-       { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
-         NULL,
-         R
-       },
-       { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
-         NULL,
-         R
-       },
-       { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
-         NULL,
-         R
-       },
-       { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
-         NULL,
-         R
-       },
-       { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates,
-         NULL,
-         R
-       },
-       { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpa,
-         NULL,
-         R
-       },
-       { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsn,
-         NULL,
-         R
-       },
-       { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ies,
-         NULL,
-         R
-       },
-       { NULL, NULL, NULL, NULL, NULL, 0 }
-};
+       dbus_connection_send(iface->con, msg, NULL);
 
+       dbus_message_unref(msg);
+       return;
 
-static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
-       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
-         {
-                 { "properties", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { NULL, NULL, { END_ARGS } }
-};
+err:
+       wpa_printf(MSG_ERROR, "dbus: Failed to construct PeerDisconnected "
+                             "signal");
+       dbus_message_unref(msg);
+}
 
 
 /**
- * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
- * @wpa_s: wpa_supplicant interface structure
- * @bssid: scanned network bssid
- * @id: unique BSS identifier
- * Returns: 0 on success, -1 on failure
  *
- * Unregisters BSS representing object from dbus
+ * Method to emit a signal for a service discovery request.
+ * The signal will carry station address, frequency, dialog token,
+ * update indicator and it tlvs
+ *
+ * @wpa_s: %wpa_supplicant network interface data
+ * @sa: station addr (p2p i/f) of the peer
+ * @dialog_token: service discovery request dialog token
+ * @update_indic: service discovery request update indicator
+ * @tlvs: service discovery request genrated byte array of tlvs
+ * @tlvs_len: service discovery request tlvs length
  */
-int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
-                            u8 bssid[ETH_ALEN], unsigned int id)
+void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
+                                    int freq, const u8 *sa, u8 dialog_token,
+                                    u16 update_indic, const u8 *tlvs,
+                                    size_t tlvs_len)
 {
-       struct wpas_dbus_priv *ctrl_iface;
-       char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+       DBusMessage *msg;
+       DBusMessageIter iter, dict_iter;
+       struct wpas_dbus_priv *iface;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+       iface = wpa_s->global->dbus;
 
        /* Do nothing if the control interface is not turned on */
-       if (wpa_s == NULL || wpa_s->global == NULL)
-               return 0;
-       ctrl_iface = wpa_s->global->dbus;
-       if (ctrl_iface == NULL)
-               return 0;
+       if (iface == NULL)
+               return;
 
-       os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-                   "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
-                   wpa_s->dbus_new_path, id);
+       msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+                                     WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                                     "ServiceDiscoveryRequest");
+       if (msg == NULL)
+               return;
 
-       wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
-                  bss_obj_path);
-       if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
-               wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
-                          bss_obj_path);
-               return -1;
-       }
+       /* Check if this is a known peer */
+       if (p2p_get_peer_info(wpa_s->global->p2p, sa, 0, NULL, 0) < 0)
+               goto error;
 
-       wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
-       wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
+                   COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
 
-       return 0;
+       path = peer_obj_path;
+
+       dbus_message_iter_init_append(msg, &iter);
+       if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
+               goto error;
+
+
+       if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
+                                             path) ||
+           !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
+           !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
+                                       dialog_token) ||
+           !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
+                                        update_indic) ||
+           !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
+                                            (const char *) tlvs,
+                                            tlvs_len) ||
+           !wpa_dbus_dict_close_write(&iter, &dict_iter))
+               goto error;
+
+       dbus_connection_send(iface->con, msg, NULL);
+       dbus_message_unref(msg);
+       return;
+error:
+       wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+       dbus_message_unref(msg);
 }
 
 
 /**
- * wpas_dbus_register_bss - Register a scanned BSS with dbus
- * @wpa_s: wpa_supplicant interface structure
- * @bssid: scanned network bssid
- * @id: unique BSS identifier
- * Returns: 0 on success, -1 on failure
  *
- * Registers BSS representing object with dbus
+ * Method to emit a signal for a service discovery response.
+ * The signal will carry station address, update indicator and it
+ * tlvs
+ *
+ * @wpa_s: %wpa_supplicant network interface data
+ * @sa: station addr (p2p i/f) of the peer
+ * @update_indic: service discovery request update indicator
+ * @tlvs: service discovery request genrated byte array of tlvs
+ * @tlvs_len: service discovery request tlvs length
  */
-int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
-                          u8 bssid[ETH_ALEN], unsigned int id)
+void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
+                                     const u8 *sa, u16 update_indic,
+                                     const u8 *tlvs, size_t tlvs_len)
 {
-       struct wpas_dbus_priv *ctrl_iface;
-       struct wpa_dbus_object_desc *obj_desc;
-       char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
-       struct bss_handler_args *arg;
+       DBusMessage *msg;
+       DBusMessageIter iter, dict_iter;
+       struct wpas_dbus_priv *iface;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+       iface = wpa_s->global->dbus;
 
        /* Do nothing if the control interface is not turned on */
-       if (wpa_s == NULL || wpa_s->global == NULL)
-               return 0;
-       ctrl_iface = wpa_s->global->dbus;
-       if (ctrl_iface == NULL)
-               return 0;
-
-       os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-                   "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
-                   wpa_s->dbus_new_path, id);
+       if (iface == NULL)
+               return;
 
-       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
-       if (!obj_desc) {
-               wpa_printf(MSG_ERROR, "Not enough memory "
-                          "to create object description");
-               goto err;
-       }
+       msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+                                     WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                               "ServiceDiscoveryResponse");
+       if (msg == NULL)
+               return;
 
-       arg = os_zalloc(sizeof(struct bss_handler_args));
-       if (!arg) {
-               wpa_printf(MSG_ERROR, "Not enough memory "
-                          "to create arguments for handler");
-               goto err;
-       }
-       arg->wpa_s = wpa_s;
-       arg->id = id;
+       /* Check if this is a known peer */
+       if (p2p_get_peer_info(wpa_s->global->p2p, sa, 0, NULL, 0) < 0)
+               goto error;
 
-       wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
-                          wpas_dbus_bss_properties,
-                          wpas_dbus_bss_signals);
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
+                   COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
 
-       wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
-                  bss_obj_path);
-       if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
-                                              wpa_s->ifname, obj_desc)) {
-               wpa_printf(MSG_ERROR,
-                          "Cannot register BSSID dbus object %s.",
-                          bss_obj_path);
-               goto err;
-       }
+       path = peer_obj_path;
 
-       wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
-       wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
+       dbus_message_iter_init_append(msg, &iter);
+       if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
+               goto error;
+
+       if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
+                                             path) ||
+           !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
+                                        update_indic) ||
+           !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
+                                            (const char *) tlvs,
+                                            tlvs_len) ||
+           !wpa_dbus_dict_close_write(&iter, &dict_iter))
+               goto error;
 
-       return 0;
 
-err:
-       free_dbus_object_desc(obj_desc);
-       return -1;
+       dbus_connection_send(iface->con, msg, NULL);
+       dbus_message_unref(msg);
+       return;
+error:
+       wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+       dbus_message_unref(msg);
 }
 
+#endif /*CONFIG_P2P*/
 
-static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
-       { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_scan,
-         {
-                 { "args", "a{sv}", ARG_IN },
-                 END_ARGS
-         }
-       },
-       { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
-         {
-                 END_ARGS
-         }
-       },
-       { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
-         {
-                 { "args", "a{sv}", ARG_IN },
-                 { "path", "o", ARG_OUT },
+
+/**
+ * wpas_dbus_signal_prop_changed - Signals change of property
+ * @wpa_s: %wpa_supplicant network interface data
+ * @property: indicates which property has changed
+ *
+ * Sends ProertyChanged signals with path, interface and arguments
+ * depending on which property has changed.
+ */
+void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
+                                  enum wpas_dbus_prop property)
+{
+       WPADBusPropertyAccessor getter;
+       char *prop;
+
+       if (wpa_s->dbus_new_path == NULL)
+               return; /* Skip signal since D-Bus setup is not yet ready */
+
+       switch (property) {
+       case WPAS_DBUS_PROP_AP_SCAN:
+               getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
+               prop = "ApScan";
+               break;
+       case WPAS_DBUS_PROP_SCANNING:
+               getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
+               prop = "Scanning";
+               break;
+       case WPAS_DBUS_PROP_STATE:
+               getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state;
+               prop = "State";
+               break;
+       case WPAS_DBUS_PROP_CURRENT_BSS:
+               getter = (WPADBusPropertyAccessor)
+                       wpas_dbus_getter_current_bss;
+               prop = "CurrentBSS";
+               break;
+       case WPAS_DBUS_PROP_CURRENT_NETWORK:
+               getter = (WPADBusPropertyAccessor)
+                       wpas_dbus_getter_current_network;
+               prop = "CurrentNetwork";
+               break;
+       case WPAS_DBUS_PROP_BSSS:
+               getter = (WPADBusPropertyAccessor) wpas_dbus_getter_bsss;
+               prop = "BSSs";
+               break;
+       case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
+               getter = (WPADBusPropertyAccessor)
+                       wpas_dbus_getter_current_auth_mode;
+               prop = "CurrentAuthMode";
+               break;
+       default:
+               wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
+                          __func__, property);
+               return;
+       }
+
+       wpa_dbus_mark_property_changed(wpa_s->global->dbus,
+                                      wpa_s->dbus_new_path,
+                                      WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
+}
+
+
+/**
+ * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
+ * @wpa_s: %wpa_supplicant network interface data
+ * @property: indicates which property has changed
+ * @id: unique BSS identifier
+ *
+ * Sends PropertyChanged signals with path, interface, and arguments depending
+ * on which property has changed.
+ */
+void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
+                                      enum wpas_dbus_bss_prop property,
+                                      unsigned int id)
+{
+       char path[WPAS_DBUS_OBJECT_PATH_MAX];
+       char *prop;
+
+       switch (property) {
+       case WPAS_DBUS_BSS_PROP_SIGNAL:
+               prop = "Signal";
+               break;
+       case WPAS_DBUS_BSS_PROP_FREQ:
+               prop = "Frequency";
+               break;
+       case WPAS_DBUS_BSS_PROP_MODE:
+               prop = "Mode";
+               break;
+       case WPAS_DBUS_BSS_PROP_PRIVACY:
+               prop = "Privacy";
+               break;
+       case WPAS_DBUS_BSS_PROP_RATES:
+               prop = "Rates";
+               break;
+       case WPAS_DBUS_BSS_PROP_WPA:
+               prop = "WPA";
+               break;
+       case WPAS_DBUS_BSS_PROP_RSN:
+               prop = "RSN";
+               break;
+       case WPAS_DBUS_BSS_PROP_IES:
+               prop = "IEs";
+               break;
+       default:
+               wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
+                          __func__, property);
+               return;
+       }
+
+       os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+                   wpa_s->dbus_new_path, id);
+
+       wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
+                                      WPAS_DBUS_NEW_IFACE_BSS, prop);
+}
+
+
+/**
+ * wpas_dbus_signal_debug_level_changed - Signals change of debug param
+ * @global: wpa_global structure
+ *
+ * Sends ProertyChanged signals informing that debug level has changed.
+ */
+void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
+{
+       wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+                                      WPAS_DBUS_NEW_INTERFACE,
+                                      "DebugLevel");
+}
+
+
+/**
+ * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
+ * @global: wpa_global structure
+ *
+ * Sends ProertyChanged signals informing that debug timestamp has changed.
+ */
+void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
+{
+       wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+                                      WPAS_DBUS_NEW_INTERFACE,
+                                      "DebugTimestamp");
+}
+
+
+/**
+ * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
+ * @global: wpa_global structure
+ *
+ * Sends ProertyChanged signals informing that debug show_keys has changed.
+ */
+void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
+{
+       wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+                                      WPAS_DBUS_NEW_INTERFACE,
+                                      "DebugShowKeys");
+}
+
+
+static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
+                              void *priv,
+                              WPADBusArgumentFreeFunction priv_free,
+                              const struct wpa_dbus_method_desc *methods,
+                              const struct wpa_dbus_property_desc *properties,
+                              const struct wpa_dbus_signal_desc *signals)
+{
+       int n;
+
+       obj_desc->user_data = priv;
+       obj_desc->user_data_free_func = priv_free;
+       obj_desc->methods = methods;
+       obj_desc->properties = properties;
+       obj_desc->signals = signals;
+
+       for (n = 0; properties && properties->dbus_property; properties++)
+               n++;
+
+       obj_desc->prop_changed_flags = os_zalloc(n);
+       if (!obj_desc->prop_changed_flags)
+               wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
+                          __func__);
+}
+
+
+static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
+       { "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 { "path", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
+         {
+                 { "path", "o", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "GetInterface", WPAS_DBUS_NEW_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
+         {
+                 { "ifname", "s", ARG_IN },
+                 { "path", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { NULL, NULL, NULL, { END_ARGS } }
+};
+
+static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
+       { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
+         RW
+       },
+       { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
+         RW
+       },
+       { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
+         RW
+       },
+       { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
+         (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
+         NULL,
+         R
+       },
+       { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
+         NULL,
+         R
+       },
+       { NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
+       { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
+         {
+                 { "path", "o", ARG_OUT },
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
+         {
+                 { "path", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
+         {
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { NULL, NULL, { END_ARGS } }
+};
+
+
+/**
+ * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * Returns: 0 on success or -1 on failure
+ *
+ * Initialize the dbus control interface for wpa_supplicantand and start
+ * receiving commands from external programs over the bus.
+ */
+int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
+{
+       struct wpa_dbus_object_desc *obj_desc;
+       int ret;
+
+       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+       if (!obj_desc) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create object description");
+               return -1;
+       }
+
+       wpas_dbus_register(obj_desc, priv->global, NULL,
+                          wpas_dbus_global_methods,
+                          wpas_dbus_global_properties,
+                          wpas_dbus_global_signals);
+
+       wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
+                  WPAS_DBUS_NEW_PATH);
+       ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
+                                      WPAS_DBUS_NEW_SERVICE,
+                                      obj_desc);
+       if (ret < 0)
+               free_dbus_object_desc(obj_desc);
+       else
+               priv->dbus_new_initialized = 1;
+
+       return ret;
+}
+
+
+/**
+ * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
+ * wpa_supplicant
+ * @iface: Pointer to dbus private data from wpas_dbus_init()
+ *
+ * Deinitialize the dbus control interface that was initialized with
+ * wpas_dbus_ctrl_iface_init().
+ */
+void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
+{
+       if (!iface->dbus_new_initialized)
+               return;
+       wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
+                  WPAS_DBUS_NEW_PATH);
+       dbus_connection_unregister_object_path(iface->con,
+                                              WPAS_DBUS_NEW_PATH);
+}
+
+
+static void wpa_dbus_free(void *ptr)
+{
+       os_free(ptr);
+}
+
+
+static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
+       { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
+         RW
+       },
+       { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
+         RW
+       },
+       { NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+
+static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
+       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
+         {
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { NULL, NULL, { END_ARGS } }
+};
+
+
+/**
+ * wpas_dbus_register_network - Register a configured network with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @ssid: network configuration data
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers network representing object with dbus
+ */
+int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
+                              struct wpa_ssid *ssid)
+{
+       struct wpas_dbus_priv *ctrl_iface;
+       struct wpa_dbus_object_desc *obj_desc;
+       struct network_handler_args *arg;
+       char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL)
+               return 0;
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return 0;
+
+       os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
+                   wpa_s->dbus_new_path, ssid->id);
+
+       wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
+                  net_obj_path);
+       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+       if (!obj_desc) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create object description");
+               goto err;
+       }
+
+       /* allocate memory for handlers arguments */
+       arg = os_zalloc(sizeof(struct network_handler_args));
+       if (!arg) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create arguments for method");
+               goto err;
+       }
+
+       arg->wpa_s = wpa_s;
+       arg->ssid = ssid;
+
+       wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
+                          wpas_dbus_network_properties,
+                          wpas_dbus_network_signals);
+
+       if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
+                                              wpa_s->ifname, obj_desc))
+               goto err;
+
+       wpas_dbus_signal_network_added(wpa_s, ssid->id);
+
+       return 0;
+
+err:
+       free_dbus_object_desc(obj_desc);
+       return -1;
+}
+
+
+/**
+ * wpas_dbus_unregister_network - Unregister a configured network from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @nid: network id
+ * Returns: 0 on success, -1 on failure
+ *
+ * Unregisters network representing object from dbus
+ */
+int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
+{
+       struct wpas_dbus_priv *ctrl_iface;
+       char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+       int ret;
+
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL ||
+           wpa_s->dbus_new_path == NULL)
+               return 0;
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return 0;
+
+       os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
+                   wpa_s->dbus_new_path, nid);
+
+       wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
+                  net_obj_path);
+       ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
+
+       if (!ret)
+               wpas_dbus_signal_network_removed(wpa_s, nid);
+
+       return ret;
+}
+
+
+static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
+       { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
+         NULL,
+         R
+       },
+       { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
+         NULL,
+         R
+       },
+       { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
+         NULL,
+         R
+       },
+       { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
+         NULL,
+         R
+       },
+       { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
+         NULL,
+         R
+       },
+       { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
+         NULL,
+         R
+       },
+       { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates,
+         NULL,
+         R
+       },
+       { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpa,
+         NULL,
+         R
+       },
+       { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsn,
+         NULL,
+         R
+       },
+       { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ies,
+         NULL,
+         R
+       },
+       { NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+
+static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
+       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
+         {
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { NULL, NULL, { END_ARGS } }
+};
+
+
+/**
+ * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @bssid: scanned network bssid
+ * @id: unique BSS identifier
+ * Returns: 0 on success, -1 on failure
+ *
+ * Unregisters BSS representing object from dbus
+ */
+int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
+                            u8 bssid[ETH_ALEN], unsigned int id)
+{
+       struct wpas_dbus_priv *ctrl_iface;
+       char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL)
+               return 0;
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return 0;
+
+       os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+                   wpa_s->dbus_new_path, id);
+
+       wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
+                  bss_obj_path);
+       if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
+               wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
+                          bss_obj_path);
+               return -1;
+       }
+
+       wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
+       wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
+
+       return 0;
+}
+
+
+/**
+ * wpas_dbus_register_bss - Register a scanned BSS with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @bssid: scanned network bssid
+ * @id: unique BSS identifier
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers BSS representing object with dbus
+ */
+int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
+                          u8 bssid[ETH_ALEN], unsigned int id)
+{
+       struct wpas_dbus_priv *ctrl_iface;
+       struct wpa_dbus_object_desc *obj_desc;
+       char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+       struct bss_handler_args *arg;
+
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL)
+               return 0;
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return 0;
+
+       os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+                   wpa_s->dbus_new_path, id);
+
+       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+       if (!obj_desc) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create object description");
+               goto err;
+       }
+
+       arg = os_zalloc(sizeof(struct bss_handler_args));
+       if (!arg) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create arguments for handler");
+               goto err;
+       }
+       arg->wpa_s = wpa_s;
+       arg->id = id;
+
+       wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
+                          wpas_dbus_bss_properties,
+                          wpas_dbus_bss_signals);
+
+       wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
+                  bss_obj_path);
+       if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
+                                              wpa_s->ifname, obj_desc)) {
+               wpa_printf(MSG_ERROR,
+                          "Cannot register BSSID dbus object %s.",
+                          bss_obj_path);
+               goto err;
+       }
+
+       wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
+       wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
+
+       return 0;
+
+err:
+       free_dbus_object_desc(obj_desc);
+       return -1;
+}
+
+
+static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
+       { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_scan,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
+         {
+                 END_ARGS
+         }
+       },
+       { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 { "path", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
+         {
+                 { "path", "o", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks,
+         {
+                 END_ARGS
+         }
+       },
+       { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
+         {
+                 { "path", "o", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
+         {
+                 { "name", "s", ARG_IN },
+                 { "data", "ay", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
+         {
+                 { "name", "s", ARG_IN },
+                 { "data", "ay", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
+         {
+                 { "name", "s", ARG_IN },
+                 END_ARGS
+         }
+       },
+#ifdef CONFIG_WPS
+       { "Start", WPAS_DBUS_NEW_IFACE_WPS,
+         (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 { "output", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+       { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_find,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_stop_find,
+         {
+                 END_ARGS
+         }
+       },
+       { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_listen,
+         {
+                 { "timeout", "i", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_extendedlisten,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_presence_request,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_prov_disc_req,
+         {
+                 { "peer", "o", ARG_IN },
+                 { "config_method", "s", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_connect,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 { "generated_pin", "i", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_group_add,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_invite,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_disconnect,
+         {
+                 END_ARGS
+         }
+       },
+       { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_rejectpeer,
+         {
+                 { "peer", "o", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush,
+         {
+                 END_ARGS
+         }
+       },
+       { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_add_service,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_delete_service,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush_service,
+         {
+                 END_ARGS
+         }
+       },
+       { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_res,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_cancel_req,
+         {
+                 { "args", "t", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_update,
+         {
+                 END_ARGS
+         }
+       },
+       { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
+         {
+                 { "arg", "i", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
+         {
+                 { "arg", "i", ARG_IN },
+                 END_ARGS
+         }
+       },
+#endif /* CONFIG_P2P */
+       { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss,
+         {
+                 { "age", "u", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { NULL, NULL, NULL, { END_ARGS } }
+};
+
+static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
+       { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
+         NULL, R
+       },
+       { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_state,
+         NULL, R
+       },
+       { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
+         NULL, R
+       },
+       { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
+         RW
+       },
+       { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_expire_age,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_bss_expire_age,
+         RW
+       },
+       { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_expire_count,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_bss_expire_count,
+         RW
+       },
+       { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_country,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_country,
+         RW
+       },
+       { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
+         NULL, R
+       },
+       { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
+         NULL, R
+       },
+       { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
+         NULL, R
+       },
+       { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
+         NULL, R
+       },
+       { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
+         NULL, R
+       },
+       { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_current_auth_mode,
+         NULL, R
+       },
+       { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
+         NULL, R
+       },
+       { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
+         NULL, R
+       },
+       { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
+         NULL, R
+       },
+#ifdef CONFIG_WPS
+       { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
+         RW
+       },
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+       { "P2PDeviceProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_device_properties,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_p2p_device_properties,
+         RW
+       },
+       { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_peers,
+         NULL, R
+       },
+       { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_role,
+         NULL, R
+       },
+       { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_group,
+         NULL, R
+       },
+       { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_peergo,
+         NULL, R
+       },
+#endif /* CONFIG_P2P */
+       { NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
+       { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "success", "b", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "path", "o", ARG_OUT },
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "path", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "name", "s", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "name", "s", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "path", "o", ARG_OUT },
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "path", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "path", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         {
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+#ifdef CONFIG_WPS
+       { "Event", WPAS_DBUS_NEW_IFACE_WPS,
+         {
+                 { "name", "s", ARG_OUT },
+                 { "args", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
+         {
+                 { "credentials", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
+         {
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+       { "P2PStateChanged", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "states", "a{ss}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "path", "o", ARG_OUT },
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "path", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "peer_object", "o", ARG_OUT },
+                 { "pin", "s", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "peer_object", "o", ARG_OUT },
+                 { "pin", "s", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "peer_object", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "peer_object", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "peer_object", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "peer_object", "o", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "peer_object", "o", ARG_OUT },
+                 { "status", "i", ARG_OUT },
                  END_ARGS
          }
        },
-       { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
+       { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "path", "o", ARG_IN },
+                 { "properties", "a{sv}", ARG_OUT },
                  END_ARGS
          }
        },
-       { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks,
+       { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
                  END_ARGS
          }
        },
-       { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
+       { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "path", "o", ARG_IN },
+                 { "status", "i", ARG_OUT },
                  END_ARGS
          }
        },
-       { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
+       { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "name", "s", ARG_IN },
-                 { "data", "ay", ARG_IN },
+                 { "path", "o", ARG_OUT },
+                 { "dev_passwd_id", "i", ARG_OUT },
                  END_ARGS
          }
        },
-       { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
+       { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "name", "s", ARG_IN },
-                 { "data", "ay", ARG_OUT },
+                 { "invite_result", "a{sv}", ARG_OUT },
                  END_ARGS
          }
        },
-       { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
+       { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "name", "s", ARG_IN },
+                 { "ifname", "s", ARG_OUT },
+                 { "role", "s", ARG_OUT },
                  END_ARGS
          }
        },
-#ifdef CONFIG_WPS
-       { "Start", WPAS_DBUS_NEW_IFACE_WPS,
-         (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
+       { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "args", "a{sv}", ARG_IN },
-                 { "output", "a{sv}", ARG_OUT },
+                 { "sd_request", "a{sv}", ARG_OUT },
                  END_ARGS
          }
        },
-#endif /* CONFIG_WPS */
-       { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss,
+       { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "age", "u", ARG_IN },
+                 { "sd_response", "a{sv}", ARG_OUT },
                  END_ARGS
          }
        },
-       { NULL, NULL, NULL, { END_ARGS } }
+#endif /* CONFIG_P2P */
+       { NULL, NULL, { END_ARGS } }
 };
 
-static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
-       { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
-         NULL, R
-       },
-       { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_state,
-         NULL, R
-       },
-       { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
-         NULL, R
-       },
-       { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
-         RW
-       },
-       { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_expire_age,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_bss_expire_age,
-         RW
-       },
-       { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bss_expire_count,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_bss_expire_count,
-         RW
-       },
-       { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_country,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_country,
-         RW
-       },
-       { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
-         NULL, R
-       },
-       { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
-         NULL, R
-       },
-       { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
-         NULL, R
-       },
-       { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
-         NULL, R
-       },
-       { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
-         NULL, R
-       },
-       { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_current_auth_mode,
-         NULL, R
-       },
-       { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
+
+int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
+{
+
+       struct wpa_dbus_object_desc *obj_desc = NULL;
+       struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
+       int next;
+
+       /* Do nothing if the control interface is not turned on */
+       if (ctrl_iface == NULL)
+               return 0;
+
+       /* Create and set the interface's object path */
+       wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+       if (wpa_s->dbus_new_path == NULL)
+               return -1;
+       next = ctrl_iface->next_objid++;
+       os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
+                   next);
+
+       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+       if (!obj_desc) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create object description");
+               goto err;
+       }
+
+       wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
+                          wpas_dbus_interface_properties,
+                          wpas_dbus_interface_signals);
+
+       wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
+                  wpa_s->dbus_new_path);
+       if (wpa_dbus_register_object_per_iface(ctrl_iface,
+                                              wpa_s->dbus_new_path,
+                                              wpa_s->ifname, obj_desc))
+               goto err;
+
+       wpas_dbus_signal_interface_added(wpa_s);
+
+       return 0;
+
+err:
+       os_free(wpa_s->dbus_new_path);
+       wpa_s->dbus_new_path = NULL;
+       free_dbus_object_desc(obj_desc);
+       return -1;
+}
+
+
+int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+       struct wpas_dbus_priv *ctrl_iface;
+
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL)
+               return 0;
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return 0;
+
+       wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
+                  wpa_s->dbus_new_path);
+       if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
+                                                wpa_s->dbus_new_path))
+               return -1;
+
+       wpas_dbus_signal_interface_removed(wpa_s);
+
+       os_free(wpa_s->dbus_new_path);
+       wpa_s->dbus_new_path = NULL;
+
+       return 0;
+}
+
+#ifdef CONFIG_P2P
+
+static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
+       { "Properties", WPAS_DBUS_NEW_IFACE_P2P_PEER, "a{sv}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_peer_properties,
          NULL, R
        },
-       { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
+       { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_peer_ies,
          NULL, R
        },
-       { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
+       { NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
+
+       { NULL, NULL, { END_ARGS } }
+};
+
+/**
+ * wpas_dbus_signal_peer - Send a peer related event signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @dev: peer device object
+ * @interface: name of the interface emitting this signal.
+ *     In case of peer objects, it would be emitted by either
+ *     the "interface object" or by "peer objects"
+ * @sig_name: signal name - DeviceFound
+ *
+ * Notify listeners about event related with newly found p2p peer device
+ */
+static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
+                                 const u8 *dev_addr, const char *interface,
+                                 const char *sig_name)
+{
+       struct wpas_dbus_priv *iface;
+       DBusMessage *msg;
+       DBusMessageIter iter;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+
+       iface = wpa_s->global->dbus;
+
+       /* Do nothing if the control interface is not turned on */
+       if (iface == NULL)
+               return;
+
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
+                   wpa_s->dbus_new_path, MAC2STR(dev_addr));
+
+       msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
+                                     sig_name);
+       if (msg == NULL)
+               return;
+
+       dbus_message_iter_init_append(msg, &iter);
+       path = peer_obj_path;
+       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+                                           &path))
+               goto err;
+
+       dbus_connection_send(iface->con, msg, NULL);
+
+       dbus_message_unref(msg);
+       return;
+
+err:
+       wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+       dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_peer_found - Send a peer found signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @dev: peer device object
+ *
+ * Notify listeners about find a p2p peer device found
+ */
+void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
+                                       const u8 *dev_addr)
+{
+       wpas_dbus_signal_peer(wpa_s, dev_addr,
+                             WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                             "DeviceFound");
+}
+
+/**
+ * wpas_dbus_signal_peer_lost - Send a peer lost signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @dev: peer device object
+ *
+ * Notify listeners about lost a p2p peer device
+ */
+void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
+                                      const u8 *dev_addr)
+{
+       wpas_dbus_signal_peer(wpa_s, dev_addr,
+                             WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                             "DeviceLost");
+}
+
+/**
+ * wpas_dbus_register_peer - Register a discovered peer object with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @ssid: network configuration data
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers network representing object with dbus
+ */
+int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
+{
+       struct wpas_dbus_priv *ctrl_iface;
+       struct wpa_dbus_object_desc *obj_desc;
+       struct peer_handler_args *arg;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL)
+               return 0;
+
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return 0;
+
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
+                   wpa_s->dbus_new_path, MAC2STR(dev_addr));
+
+       wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
+                  peer_obj_path);
+       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+       if (!obj_desc) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create object description");
+               goto err;
+       }
+
+       /* allocate memory for handlers arguments */
+       arg = os_zalloc(sizeof(struct peer_handler_args));
+       if (!arg) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create arguments for method");
+               goto err;
+       }
+
+       arg->wpa_s = wpa_s;
+       os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
+
+       wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
+                          NULL,
+                          wpas_dbus_p2p_peer_properties,
+                          wpas_dbus_p2p_peer_signals);
+
+       if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
+                                              wpa_s->ifname, obj_desc))
+               goto err;
+
+       return 0;
+
+err:
+       free_dbus_object_desc(obj_desc);
+       return -1;
+}
+
+/**
+ * wpas_dbus_unregister_peer - Unregister a peer object with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @dev_addr: p2p device addr
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers network representing object with dbus
+ */
+int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
+                                 const u8 *dev_addr)
+{
+       struct wpas_dbus_priv *ctrl_iface;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+       int ret;
+
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL ||
+           wpa_s->dbus_new_path == NULL)
+               return 0;
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return 0;
+
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
+                   wpa_s->dbus_new_path, MAC2STR(dev_addr));
+
+       wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
+                  peer_obj_path);
+       ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
+
+       return ret;
+}
+
+
+static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
+       { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_group_members,
          NULL, R
        },
-#ifdef CONFIG_WPS
-       { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
-         (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
-         (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
+       { "Properties",
+         WPAS_DBUS_NEW_IFACE_P2P_GROUP, "a{sv}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_group_properties,
+         (WPADBusPropertyAccessor) wpas_dbus_setter_p2p_group_properties,
          RW
        },
-#endif /* CONFIG_WPS */
        { NULL, NULL, NULL, NULL, NULL, 0 }
 };
 
-static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
-       { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         {
-                 { "success", "b", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         {
-                 { "path", "o", ARG_OUT },
-                 { "properties", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
+       { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
          {
-                 { "path", "o", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         {
-                 { "name", "s", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         {
-                 { "name", "s", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         {
-                 { "path", "o", ARG_OUT },
-                 { "properties", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         {
-                 { "path", "o", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         {
-                 { "path", "o", ARG_OUT },
+                 { "peer", "o", ARG_OUT },
                  END_ARGS
          }
        },
-       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
-         {
-                 { "properties", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-#ifdef CONFIG_WPS
-       { "Event", WPAS_DBUS_NEW_IFACE_WPS,
-         {
-                 { "name", "s", ARG_OUT },
-                 { "args", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
-         {
-                 { "credentials", "a{sv}", ARG_OUT },
-                 END_ARGS
-         }
-       },
-       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
+       { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
          {
-                 { "properties", "a{sv}", ARG_OUT },
+                 { "peer", "o", ARG_OUT },
                  END_ARGS
          }
        },
-#endif /* CONFIG_WPS */
        { NULL, NULL, { END_ARGS } }
 };
 
+/**
+ * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @ssid: SSID struct
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers p2p group representing object with dbus
+ */
+void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
+                                 struct wpa_ssid *ssid)
+{
+       struct wpas_dbus_priv *ctrl_iface;
+       struct wpa_dbus_object_desc *obj_desc;
+       char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
 
-int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL)
+               return;
+
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return;
+
+       if (wpa_s->dbus_groupobj_path) {
+               wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
+                          __func__, wpa_s->dbus_groupobj_path);
+               return;
+       }
+
+       if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
+               return;
+
+       wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
+       if (wpa_s->dbus_groupobj_path == NULL)
+               return;
+
+       wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
+                  group_obj_path);
+       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+       if (!obj_desc) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create object description");
+               goto err;
+       }
+
+       wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
+                          wpas_dbus_p2p_group_properties,
+                          wpas_dbus_p2p_group_signals);
+
+       if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
+                                              wpa_s->ifname, obj_desc))
+               goto err;
+
+       return;
+
+err:
+       if (wpa_s->dbus_groupobj_path) {
+               os_free(wpa_s->dbus_groupobj_path);
+               wpa_s->dbus_groupobj_path = NULL;
+       }
+
+       free_dbus_object_desc(obj_desc);
+}
+
+/**
+ * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @ssid: network name of the p2p group started
+ */
+void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
+                                   const struct wpa_ssid *ssid)
 {
+       struct wpas_dbus_priv *ctrl_iface;
+
+       /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL)
+               return;
+
+       ctrl_iface = wpa_s->global->dbus;
+       if (ctrl_iface == NULL)
+               return;
+
+       if (!wpa_s->dbus_groupobj_path) {
+               wpa_printf(MSG_DEBUG,
+                          "%s: Group object '%s' already unregistered",
+                          __func__, wpa_s->dbus_groupobj_path);
+               return;
+       }
+
+       wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
+                  wpa_s->dbus_groupobj_path);
+
+       wpa_dbus_unregister_object_per_iface(ctrl_iface,
+                                            wpa_s->dbus_groupobj_path);
+
+       os_free(wpa_s->dbus_groupobj_path);
+       wpa_s->dbus_groupobj_path = NULL;
+}
+
+static const struct wpa_dbus_property_desc
+wpas_dbus_p2p_groupmember_properties[] = {
+       { "Properties", WPAS_DBUS_NEW_IFACE_P2P_GROUPMEMBER, "a{sv}",
+         (WPADBusPropertyAccessor) wpas_dbus_getter_p2p_group_properties,
+         NULL, R
+       },
+       { NULL, NULL, NULL, NULL, NULL, 0 }
+};
 
+/**
+ * wpas_dbus_register_p2p_groupmember - Register a p2p groupmember
+ * object with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @p2p_if_addr: i/f addr of the device joining this group
+ *
+ * Registers p2p groupmember representing object with dbus
+ */
+void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
+                                       const u8 *p2p_if_addr)
+{
+       struct wpas_dbus_priv *ctrl_iface;
        struct wpa_dbus_object_desc *obj_desc = NULL;
-       struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
-       int next;
+       struct groupmember_handler_args *arg;
+       char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
 
        /* Do nothing if the control interface is not turned on */
+       if (wpa_s == NULL || wpa_s->global == NULL)
+               return;
+
+       ctrl_iface = wpa_s->global->dbus;
        if (ctrl_iface == NULL)
-               return 0;
+               return;
 
-       /* Create and set the interface's object path */
-       wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
-       if (wpa_s->dbus_new_path == NULL)
-               return -1;
-       next = ctrl_iface->next_objid++;
-       os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
-                   WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
-                   next);
+       if (!wpa_s->dbus_groupobj_path)
+               return;
+
+       os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+               "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
+               wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
 
        obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
        if (!obj_desc) {
@@ -1556,50 +2896,62 @@ int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
                goto err;
        }
 
-       wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
-                          wpas_dbus_interface_properties,
-                          wpas_dbus_interface_signals);
+       /* allocate memory for handlers arguments */
+       arg = os_zalloc(sizeof(struct groupmember_handler_args));
+       if (!arg) {
+               wpa_printf(MSG_ERROR, "Not enough memory "
+                          "to create arguments for method");
+               goto err;
+       }
 
-       wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
-                  wpa_s->dbus_new_path);
-       if (wpa_dbus_register_object_per_iface(ctrl_iface,
-                                              wpa_s->dbus_new_path,
+       arg->wpa_s = wpa_s;
+       os_memcpy(arg->member_addr, p2p_if_addr, ETH_ALEN);
+
+       wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
+                          wpas_dbus_p2p_groupmember_properties, NULL);
+
+       if (wpa_dbus_register_object_per_iface(ctrl_iface, groupmember_obj_path,
                                               wpa_s->ifname, obj_desc))
                goto err;
 
-       wpas_dbus_signal_interface_added(wpa_s);
-
-       return 0;
+       wpa_printf(MSG_INFO,
+                  "dbus: Registered group member object '%s' successfully",
+                  groupmember_obj_path);
+       return;
 
 err:
-       os_free(wpa_s->dbus_new_path);
-       wpa_s->dbus_new_path = NULL;
        free_dbus_object_desc(obj_desc);
-       return -1;
 }
 
-
-int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
+/**
+ * wpas_dbus_unregister_p2p_groupmember - Unregister a p2p groupmember
+ * object with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @p2p_if_addr: i/f addr of the device joining this group
+ *
+ * Unregisters p2p groupmember representing object with dbus
+ */
+void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
+                                         const u8 *p2p_if_addr)
 {
        struct wpas_dbus_priv *ctrl_iface;
+       char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
 
        /* Do nothing if the control interface is not turned on */
        if (wpa_s == NULL || wpa_s->global == NULL)
-               return 0;
+               return;
+
        ctrl_iface = wpa_s->global->dbus;
        if (ctrl_iface == NULL)
-               return 0;
-
-       wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
-                  wpa_s->dbus_new_path);
-       if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
-                                                wpa_s->dbus_new_path))
-               return -1;
+               return;
 
-       wpas_dbus_signal_interface_removed(wpa_s);
+       if (!wpa_s->dbus_groupobj_path)
+               return;
 
-       os_free(wpa_s->dbus_new_path);
-       wpa_s->dbus_new_path = NULL;
+       os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+               "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
+               wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
 
-       return 0;
+       wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path);
 }
+#endif /* CONFIG_P2P */
index 377e381..e8376fe 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef CTRL_IFACE_DBUS_NEW_H
 #define CTRL_IFACE_DBUS_NEW_H
 
+#include "p2p/p2p.h"
+
 struct wpa_global;
 struct wpa_supplicant;
 struct wpa_ssid;
@@ -61,6 +63,21 @@ enum wpas_dbus_bss_prop {
 #define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
 #define WPAS_DBUS_NEW_IFACE_BSS        WPAS_DBUS_NEW_INTERFACE ".BSS"
 
+#define WPAS_DBUS_NEW_IFACE_P2PDEVICE  \
+               WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice"
+
+/*
+ * Groups correspond to P2P groups where this device is a GO (owner)
+ */
+#define WPAS_DBUS_NEW_P2P_GROUPS_PART  "Groups"
+#define        WPAS_DBUS_NEW_IFACE_P2P_GROUP WPAS_DBUS_NEW_INTERFACE ".Group"
+
+#define WPAS_DBUS_NEW_P2P_PEERS_PART   "Peers"
+#define        WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer"
+
+#define WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART    "Members"
+#define        WPAS_DBUS_NEW_IFACE_P2P_GROUPMEMBER \
+       WPAS_DBUS_NEW_INTERFACE ".GroupMember"
 
 /* Errors */
 #define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
@@ -78,6 +95,13 @@ enum wpas_dbus_bss_prop {
 #define WPAS_DBUS_ERROR_NETWORK_UNKNOWN \
        WPAS_DBUS_NEW_INTERFACE ".NetworkUnknown"
 
+#define WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE \
+       WPAS_DBUS_NEW_INTERFACE ".ConnectChannelUnavailable"
+#define WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED \
+       WPAS_DBUS_NEW_INTERFACE ".ConnectChannelUnsupported"
+#define WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR \
+       WPAS_DBUS_NEW_INTERFACE ".ConnectUnspecifiedError"
+
 #define WPAS_DBUS_ERROR_BLOB_EXISTS \
        WPAS_DBUS_NEW_INTERFACE ".BlobExists"
 #define WPAS_DBUS_ERROR_BLOB_UNKNOWN \
@@ -122,6 +146,48 @@ void wpas_dbus_signal_debug_level_changed(struct wpa_global *global);
 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global);
 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global);
 
+int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr);
+void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
+                                          const u8 *dev_addr);
+int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
+                                 const u8 *dev_addr);
+void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
+                                          const u8 *dev_addr);
+void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
+                                       const char *role);
+void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
+                                             const u8 *dev_addr, int request,
+                                             enum p2p_prov_disc_status status,
+                                             u16 config_methods,
+                                             unsigned int generated_pin);
+void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
+                                    const u8 *src, u16 dev_passwd_id);
+void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
+                                       const struct wpa_ssid *ssid,
+                                       int client, int network_id);
+void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
+                                 struct wpa_ssid *ssid);
+void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s, int status);
+void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
+                                   const struct wpa_ssid *ssid);
+void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
+                                           int status, const u8 *bssid);
+void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
+                                       const u8 *p2p_if_addr);
+void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
+                                         const u8 *p2p_if_addr);
+void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
+                                           const u8 *member);
+void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
+                                    int freq, const u8 *sa, u8 dialog_token,
+                                    u16 update_indic, const u8 *tlvs,
+                                    size_t tlvs_len);
+void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
+                                     const u8 *sa, u16 update_indic,
+                                     const u8 *tlvs, size_t tlvs_len);
+void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
+                               const u8 *member);
+
 #else /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
 static inline int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
@@ -231,6 +297,119 @@ static inline void wpas_dbus_signal_debug_show_keys_changed(
 {
 }
 
+static inline int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s,
+                                         const u8 *dev_addr)
+{
+       return 0;
+}
+
+static inline int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
+                                           const u8 *dev_addr)
+{
+       return 0;
+}
+
+static inline void
+wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
+                                  const char *role)
+{
+}
+
+static inline void
+wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
+                                        const u8 *dev_addr, int request,
+                                        enum p2p_prov_disc_status status,
+                                        u16 config_methods,
+                                        unsigned int generated_pin)
+{
+}
+
+static inline void wpas_dbus_signal_p2p_go_neg_req(
+                               struct wpa_supplicant *wpa_s,
+                               const u8 *src,
+                               u16 dev_passwd_id)
+{
+}
+
+static inline void
+wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
+                                  const struct wpa_ssid *ssid,
+                                  int client, int network_id)
+{
+}
+
+static inline void
+wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
+                            struct wpa_ssid *ssid)
+{
+}
+
+static inline void
+wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s, int status)
+{
+}
+
+static inline void
+wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
+                              const struct wpa_ssid *ssid)
+{
+}
+
+static inline void wpas_dbus_signal_p2p_invitation_result(
+                               struct wpa_supplicant *wpa_s, int status,
+                               const u8 *bssid)
+{
+}
+
+static inline void
+wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
+                                  const u8 *p2p_if_addr)
+{
+}
+
+static inline void
+wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, int freq,
+                               const u8 *sa, u8 dialog_token, u16 update_indic,
+                               const u8 *tlvs, size_t tlvs_len)
+{
+}
+
+static inline void
+wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
+                                const u8 *sa, u16 update_indic,
+                                const u8 *tlvs, size_t tlvs_len)
+{
+}
+
+static inline void
+wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
+                                    const u8 *p2p_if_addr)
+{
+}
+
+static inline void
+wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
+                                const u8 *member)
+{
+}
+
+static inline void
+wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
+                                  const u8 *dev_addr)
+{
+}
+
+static inline void
+wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
+                                 const u8 *dev_addr)
+{
+}
+
+static inline void
+wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
+                                      const u8 *member)
+{
+}
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
 #endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
new file mode 100644 (file)
index 0000000..ec43d0c
--- /dev/null
@@ -0,0 +1,1772 @@
+/*
+ * WPA Supplicant / dbus-based control interface (P2P)
+ *
+ * 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.
+ */
+
+#include "includes.h"
+
+#include "utils/includes.h"
+#include "common.h"
+#include "../config.h"
+#include "../wpa_supplicant_i.h"
+#include "../wps_supplicant.h"
+#include "dbus_new_helpers.h"
+#include "dbus_new.h"
+#include "dbus_new_handlers.h"
+#include "dbus_new_handlers_p2p.h"
+#include "dbus_dict_helpers.h"
+#include "p2p/p2p.h"
+#include "common/ieee802_11_defs.h"
+#include "ap/hostapd.h"
+#include "ap/ap_config.h"
+#include "ap/wps_hostapd.h"
+
+#include "../p2p_supplicant.h"
+
+/**
+ * Parses out the mac address from the peer object path.
+ * @peer_path - object path of the form
+ *     /fi/w1/wpa_supplicant1/Interfaces/n/Peers/00112233445566 (no colons)
+ * @addr - out param must be of ETH_ALEN size
+ * Returns 0 if valid (including MAC), -1 otherwise
+ */
+static int parse_peer_object_path(char *peer_path, u8 addr[ETH_ALEN])
+{
+       char *p;
+
+       if (!peer_path)
+               return -1;
+       p = strrchr(peer_path, '/');
+       if (!p)
+               return -1;
+       p++;
+       return hwaddr_compact_aton(p, addr);
+}
+
+DBusMessage *wpas_dbus_handler_p2p_find(DBusMessage * message,
+                                       struct wpa_supplicant * wpa_s)
+{
+       struct wpa_dbus_dict_entry entry;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       DBusMessageIter iter_dict;
+       unsigned int timeout = 0;
+       unsigned int searchonly = 0;
+       enum p2p_discovery_type type = P2P_FIND_ONLY_SOCIAL;
+       int num_req_dev_types = 0;
+       unsigned int i;
+       u8 *req_dev_types = NULL;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto error;
+
+       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, "Timeout") &&
+                   (entry.type == DBUS_TYPE_INT32)) {
+                       timeout = entry.uint32_value;
+               } else if (!os_strcmp(entry.key, "SearchOnly") &&
+                          (entry.type == DBUS_TYPE_BOOLEAN)) {
+                       searchonly = (entry.bool_value == TRUE) ? 1 : 0;
+               } else if (os_strcmp(entry.key, "RequestedDeviceTypes") == 0) {
+                       if ((entry.type != DBUS_TYPE_ARRAY) ||
+                           (entry.array_type != WPAS_DBUS_TYPE_BINARRAY))
+                               goto error_clear;
+
+                       req_dev_types =
+                               os_malloc(WPS_DEV_TYPE_LEN * entry.array_len);
+                       if (!req_dev_types)
+                               goto error_clear;
+
+                       for (i = 0; i < entry.array_len; i++) {
+                               if (wpabuf_len(entry.binarray_value[i]) !=
+                                                       WPS_DEV_TYPE_LEN)
+                                       goto error_clear;
+                               os_memcpy(req_dev_types + i * WPS_DEV_TYPE_LEN,
+                                         wpabuf_head(entry.binarray_value[i]),
+                                         WPS_DEV_TYPE_LEN);
+                       }
+
+                       num_req_dev_types = entry.array_len;
+               } else
+                       goto error_clear;
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+
+       wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types);
+       return reply;
+
+error_clear:
+       os_free(req_dev_types);
+       wpa_dbus_dict_entry_clear(&entry);
+error:
+       reply = wpas_dbus_error_invalid_args(message, entry.key);
+       return reply;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_stop_find(DBusMessage * message,
+                                            struct wpa_supplicant * wpa_s)
+{
+       wpas_p2p_stop_find(wpa_s);
+       return NULL;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_rejectpeer(DBusMessage * message,
+                                             struct wpa_supplicant * wpa_s)
+{
+       DBusMessageIter iter;
+       char *peer_object_path = NULL;
+       u8 peer_addr[ETH_ALEN];
+
+       dbus_message_iter_init(message, &iter);
+       dbus_message_iter_get_basic(&iter, &peer_object_path);
+
+       if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
+               return wpas_dbus_error_invalid_args(message, NULL);
+
+       if (wpas_p2p_reject(wpa_s, peer_addr) < 0)
+               return wpas_dbus_error_unknown_error(message,
+                               "Failed to call wpas_p2p_reject method.");
+
+       return NULL;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_listen(DBusMessage * message,
+                                         struct wpa_supplicant * wpa_s)
+{
+       dbus_int32_t timeout = 0;
+
+       if (!dbus_message_get_args(message, NULL, DBUS_TYPE_INT32, &timeout,
+                                  DBUS_TYPE_INVALID))
+               return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+                                             NULL);
+
+       if (wpas_p2p_listen(wpa_s, (unsigned int)timeout))
+               return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+                                             NULL);
+
+       return NULL;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_extendedlisten(DBusMessage * message,
+                                                 struct wpa_supplicant * wpa_s)
+{
+       unsigned int period = 0, interval = 0;
+       struct wpa_dbus_dict_entry entry;
+       DBusMessageIter iter;
+       DBusMessageIter iter_dict;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto error;
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto error;
+
+               if (!strcmp(entry.key, "period") &&
+                   (entry.type == DBUS_TYPE_INT32))
+                       period = entry.uint32_value;
+               else if (!strcmp(entry.key, "interval") &&
+                        (entry.type == DBUS_TYPE_INT32))
+                       interval = entry.uint32_value;
+               else
+                       goto error_clear;
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+
+       if (wpas_p2p_ext_listen(wpa_s, period, interval))
+               return wpas_dbus_error_unknown_error(message,
+                                       "failed to initiate a p2p_ext_listen.");
+
+       return NULL;
+
+error_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+error:
+       return wpas_dbus_error_invalid_args(message, entry.key);
+}
+
+DBusMessage *wpas_dbus_handler_p2p_presence_request(DBusMessage * message,
+                                                   struct wpa_supplicant *
+                                                   wpa_s)
+{
+       unsigned int dur1 = 0, int1 = 0, dur2 = 0, int2 = 0;
+       struct wpa_dbus_dict_entry entry;
+       DBusMessageIter iter;
+       DBusMessageIter iter_dict;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto error;
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto error;
+
+               if (!strcmp(entry.key, "duration1") &&
+                   (entry.type == DBUS_TYPE_INT32))
+                       dur1 = entry.uint32_value;
+               else if (!strcmp(entry.key, "interval1") &&
+                        entry.type == DBUS_TYPE_INT32)
+                       int1 = entry.uint32_value;
+               else if (!strcmp(entry.key, "duration2") &&
+                        entry.type == DBUS_TYPE_INT32)
+                       dur2 = entry.uint32_value;
+               else if (!strcmp(entry.key, "interval2") &&
+                        entry.type == DBUS_TYPE_INT32)
+                       int2 = entry.uint32_value;
+               else
+                       goto error_clear;
+
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+       if (wpas_p2p_presence_req(wpa_s, dur1, int1, dur2, int2) < 0)
+               return wpas_dbus_error_unknown_error(message,
+                               "Failed to invoke presence request.");
+
+       return NULL;
+
+error_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+error:
+       return wpas_dbus_error_invalid_args(message, entry.key);
+}
+
+DBusMessage *wpas_dbus_handler_p2p_group_add(DBusMessage * message,
+                                            struct wpa_supplicant * wpa_s)
+{
+       DBusMessageIter iter_dict;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       struct wpa_dbus_dict_entry entry;
+       char *network_object_path = NULL;
+       int persistent_group = 0;
+       int freq = 0;
+       char *iface = NULL;
+       char *net_id_str = NULL;
+       unsigned int group_id = 0;
+       struct wpa_ssid *ssid;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto inv_args;
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto inv_args;
+
+               if (!strcmp(entry.key, "persistent") &&
+                   (entry.type == DBUS_TYPE_BOOLEAN)) {
+                       persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
+               } else if (!strcmp(entry.key, "frequency") &&
+                          (entry.type == DBUS_TYPE_INT32)) {
+                       freq = entry.int32_value;
+                       if (freq <= 0)
+                               goto inv_args_clear;
+               } else if (!strcmp(entry.key, "network_object") &&
+                          entry.type == DBUS_TYPE_OBJECT_PATH)
+                       network_object_path = os_strdup(entry.str_value);
+               else
+                       goto inv_args_clear;
+
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+
+       if (network_object_path != NULL) {
+               /*
+                * A Network Object Path is defined meaning we want to re-invoke
+                * a persisatnt group.
+                */
+
+               iface = wpas_dbus_new_decompose_object_path(network_object_path,
+                                                           &net_id_str, NULL);
+               if (iface == NULL ||
+                   os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
+                       reply =
+                           wpas_dbus_error_invalid_args(message,
+                                                        network_object_path);
+                       goto out;
+               }
+
+               group_id = strtoul(net_id_str, NULL, 10);
+               if (errno == EINVAL) {
+                       reply = wpas_dbus_error_invalid_args(
+                                               message, network_object_path);
+                       goto out;
+               }
+
+               /* Get the SSID structure form the persistant group id */
+               ssid = wpa_config_get_network(wpa_s->conf, group_id);
+               if (ssid == NULL || ssid->disabled != 2)
+                       goto inv_args;
+
+               if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq)) {
+                       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))
+               goto inv_args;
+
+out:
+       os_free(network_object_path);
+       os_free(net_id_str);
+       os_free(iface);
+       return reply;
+inv_args_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+inv_args:
+       reply = wpas_dbus_error_invalid_args(message, NULL);
+       goto out;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_disconnect(DBusMessage *message,
+                                             struct wpa_supplicant *wpa_s)
+{
+       if (wpas_p2p_disconnect(wpa_s))
+               return wpas_dbus_error_unknown_error(message,
+                                               "failed to disconnect");
+
+       return NULL;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_flush(DBusMessage * message,
+                                        struct wpa_supplicant * wpa_s)
+{
+       os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
+       wpa_s->force_long_sd = 0;
+       p2p_flush(wpa_s->global->p2p);
+
+       return NULL;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_connect(DBusMessage * message,
+                                          struct wpa_supplicant * wpa_s)
+{
+       DBusMessageIter iter_dict;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       struct wpa_dbus_dict_entry entry;
+       char *peer_object_path = NULL;
+       int persistent_group = 0;
+       int join = 0;
+       int authorize_only = 0;
+       int go_intent = -1;
+       int freq = 0;
+       u8 addr[ETH_ALEN];
+       char *pin = NULL;
+       enum p2p_wps_method wps_method = WPS_NOT_READY;
+       int new_pin;
+       char *err_msg = NULL;
+       char *iface = NULL;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto inv_args;
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto inv_args;
+
+               if (!strcmp(entry.key, "peer") &&
+                   (entry.type == DBUS_TYPE_OBJECT_PATH)) {
+                       peer_object_path = os_strdup(entry.str_value);
+               } else if (!strcmp(entry.key, "persistent") &&
+                          (entry.type == DBUS_TYPE_BOOLEAN)) {
+                       persistent_group = (entry.bool_value == TRUE) ? 1 : 0;
+               } else if (!strcmp(entry.key, "join") &&
+                          (entry.type == DBUS_TYPE_BOOLEAN)) {
+                       join = (entry.bool_value == TRUE) ? 1 : 0;
+               } else if (!strcmp(entry.key, "authorize_only") &&
+                          (entry.type == DBUS_TYPE_BOOLEAN)) {
+                       authorize_only = (entry.bool_value == TRUE) ? 1 : 0;
+               } else if (!strcmp(entry.key, "frequency") &&
+                          (entry.type == DBUS_TYPE_INT32)) {
+                       freq = entry.int32_value;
+                       if (freq <= 0)
+                               goto inv_args_clear;
+               } else if (!strcmp(entry.key, "go_intent") &&
+                          (entry.type == DBUS_TYPE_INT32)) {
+                       go_intent = entry.int32_value;
+                       if ((go_intent < 0) || (go_intent > 15))
+                               goto inv_args_clear;
+               } else if (!strcmp(entry.key, "wps_method") &&
+                          (entry.type == DBUS_TYPE_STRING)) {
+                       if (!strcmp(entry.str_value, "pbc"))
+                               wps_method = WPS_PBC;
+                       else if (!strcmp(entry.str_value, "pin"))
+                               wps_method = WPS_PIN_DISPLAY;
+                       else if (!strcmp(entry.str_value, "label"))
+                               wps_method = WPS_PIN_LABEL;
+                       else if (!strcmp(entry.str_value, "display"))
+                               wps_method = WPS_PIN_DISPLAY;
+                       else if (!strcmp(entry.str_value, "keypad"))
+                               wps_method = WPS_PIN_KEYPAD;
+                       else
+                               goto inv_args_clear;
+               } else if (!strcmp(entry.key, "pin") &&
+                          (entry.type == DBUS_TYPE_STRING)) {
+                       pin = os_strdup(entry.str_value);
+               } else
+                       goto inv_args_clear;
+
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+
+       if (!peer_object_path || (wps_method == WPS_NOT_READY) ||
+           (parse_peer_object_path(peer_object_path, addr) < 0) ||
+           (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0)) {
+               reply = wpas_dbus_error_invalid_args(message, NULL);
+               goto inv_args;
+       }
+
+       /*
+        * Validate the wps_method specified and the pin value.
+        */
+       if ((!pin || !pin[0]) &&
+           ((wps_method == WPS_PIN_LABEL) || (wps_method == WPS_PIN_KEYPAD)))
+               goto inv_args;
+
+       new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
+                                  persistent_group, join, authorize_only,
+                                  go_intent, freq);
+
+       if (new_pin >= 0) {
+               reply = dbus_message_new_method_return(message);
+               dbus_message_append_args(reply, DBUS_TYPE_INT32,
+                                        &new_pin, DBUS_TYPE_INVALID);
+       } else {
+               switch (new_pin) {
+               case -2:
+                       err_msg = "connect failed due to"
+                                       " channel unavailability.";
+                       iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNAVAILABLE;
+                       break;
+
+               case -3:
+                       err_msg = "connect failed due to"
+                                       " unsupported channel.";
+                       iface = WPAS_DBUS_ERROR_CONNECT_CHANNEL_UNSUPPORTED;
+                       break;
+
+               default:
+                       err_msg = "connect failed due to"
+                                       " unspecified error.";
+                       iface = WPAS_DBUS_ERROR_CONNECT_UNSPECIFIED_ERROR;
+                       break;
+               }
+               /*
+                * TODO::
+                * Do we need specialized errors corresponding to above
+                * error conditions as against just returning a different
+                * error message?
+                */
+               reply = dbus_message_new_error(message, iface, err_msg);
+       }
+
+out:
+       os_free(peer_object_path);
+       os_free(pin);
+       return reply;
+inv_args_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+inv_args:
+       reply = wpas_dbus_error_invalid_args(message, NULL);
+       goto out;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_invite(DBusMessage * message,
+                                         struct wpa_supplicant *wpa_s)
+{
+       DBusMessageIter iter_dict;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       struct wpa_dbus_dict_entry entry;
+       char *peer_object_path = NULL;
+       char *network_object_path = NULL;
+       char *iface = NULL;
+       char *net_id_str = NULL;
+       u8 peer_addr[ETH_ALEN];
+       unsigned int group_id = 0;
+       int persistent = 0;
+       struct wpa_ssid *ssid;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto err;
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto err;
+
+               if (!strcmp(entry.key, "peer") &&
+                   (entry.type == DBUS_TYPE_OBJECT_PATH)) {
+                       peer_object_path = os_strdup(entry.str_value);
+                       wpa_dbus_dict_entry_clear(&entry);
+               } else if (!strcmp(entry.key, "network_object") &&
+                          (entry.type == DBUS_TYPE_OBJECT_PATH)) {
+                       network_object_path = os_strdup(entry.str_value);
+                       persistent = 1;
+                       wpa_dbus_dict_entry_clear(&entry);
+               } else {
+                       wpa_dbus_dict_entry_clear(&entry);
+                       goto err;
+               }
+       }
+
+       if (!peer_object_path ||
+           (parse_peer_object_path(peer_object_path, peer_addr) < 0) ||
+           (p2p_get_peer_info(wpa_s->global->p2p,
+                              peer_addr, 0, NULL, 0) < 0)) {
+               goto err;
+       }
+
+       if (persistent) {
+               /*
+                * A group ID is defined meaning we want to re-invoke a
+                * persisatnt group
+                */
+
+               iface = wpas_dbus_new_decompose_object_path(network_object_path,
+                                                           &net_id_str, NULL);
+               if (iface == NULL ||
+                   os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
+                       reply =
+                           wpas_dbus_error_invalid_args(message,
+                                                        network_object_path);
+                       goto out;
+               }
+
+               group_id = strtoul(net_id_str, NULL, 10);
+               if (errno == EINVAL) {
+                       reply = wpas_dbus_error_invalid_args(
+                                               message, network_object_path);
+                       goto out;
+               }
+
+               /* Get the SSID structure form the persistant group id */
+               ssid = wpa_config_get_network(wpa_s->conf, group_id);
+               if (ssid == NULL || ssid->disabled != 2)
+                       goto err;
+
+               if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL) < 0) {
+                       reply = wpas_dbus_error_unknown_error(
+                                       message,
+                                       "Failed to reinvoke a persistent group");
+                       goto out;
+               }
+       } else {
+               /*
+                * No group ID means propose to a peer to join my active group
+                */
+               if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname,
+                                        peer_addr, NULL)) {
+                       reply = wpas_dbus_error_unknown_error(
+                                       message,
+                                       "Failed to join to an active group");
+                       goto out;
+               }
+       }
+
+out:
+       os_free(network_object_path);
+       os_free(peer_object_path);
+       return reply;
+
+err:
+       reply = wpas_dbus_error_invalid_args(message, NULL);
+       goto out;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_prov_disc_req(DBusMessage * message,
+                                                struct wpa_supplicant *wpa_s)
+{
+       DBusMessageIter iter;
+       char *peer_object_path = NULL;
+       char *config_method = NULL;
+       u8 peer_addr[ETH_ALEN];
+
+       dbus_message_iter_init(message, &iter);
+       dbus_message_iter_get_basic(&iter, &peer_object_path);
+
+       if (parse_peer_object_path(peer_object_path, peer_addr) < 0)
+               return wpas_dbus_error_invalid_args(message, NULL);
+
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_get_basic(&iter, &config_method);
+
+       /*
+        * Validation checks on config_method are being duplicated here
+        * to be able to return invalid args reply since the error code
+        * from p2p module are not granular enough (yet).
+        */
+       if (os_strcmp(config_method, "display") &&
+           os_strcmp(config_method, "keypad") &&
+           os_strcmp(config_method, "pbc") &&
+           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)
+               return wpas_dbus_error_unknown_error(message,
+                               "Failed to send provision discovery request");
+
+       return NULL;
+}
+
+/*
+ * P2P Device property accessor methods.
+ */
+
+DBusMessage *wpas_dbus_getter_p2p_device_properties(DBusMessage * message,
+                                                   struct wpa_supplicant *
+                                                   wpa_s)
+{
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter, variant_iter, dict_iter;
+       const char *dev_name;
+       int num_sec_dev_types = 0;
+       int num_vendor_extensions = 0;
+       int i;
+       const struct wpabuf *vendor_ext[P2P_MAX_WPS_VENDOR_EXT];
+
+       if (message == NULL)
+               reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+       else
+               reply = dbus_message_new_method_return(message);
+
+       if (!reply)
+               goto err_no_mem;
+
+       dbus_message_iter_init_append(reply, &iter);
+
+       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;
+
+       /* DeviceName */
+       dev_name = wpa_s->conf->device_name;
+       if (dev_name &&
+           !wpa_dbus_dict_append_string(&dict_iter, "DeviceName", dev_name))
+               goto err_no_mem;
+
+       /* Primary device type */
+       if (!wpa_dbus_dict_append_byte_array(&dict_iter, "PrimaryDeviceType",
+                                            (char *)wpa_s->conf->device_type,
+                                            WPS_DEV_TYPE_LEN))
+               goto err_no_mem;
+
+       /* Secondary device types */
+       for (i = 0; i < MAX_SEC_DEVICE_TYPES; i++) {
+               if (wpa_s->conf->sec_device_type[i] == NULL)
+                       break;
+               num_sec_dev_types++;
+       }
+
+       if (!wpa_dbus_dict_append_string_array(
+                       &dict_iter, "SecondaryDeviceTypes",
+                       (const char **)wpa_s->conf->sec_device_type,
+                       num_sec_dev_types))
+               goto err_no_mem;
+
+       /* Vendor Extensions */
+       for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
+               if (wpa_s->conf->wps_vendor_ext[i] == NULL)
+                       continue;
+               vendor_ext[num_vendor_extensions++] =
+                       wpa_s->conf->wps_vendor_ext[i];
+       }
+
+       if (num_vendor_extensions &&
+           !wpa_dbus_dict_append_wpabuf_array(&dict_iter,
+                                              "VendorExtension",
+                                              vendor_ext,
+                                              num_vendor_extensions))
+               goto err_no_mem;
+
+       /* GO Intent */
+       if (!wpa_dbus_dict_append_uint32(&dict_iter, "GOIntent",
+                                        wpa_s->conf->p2p_go_intent))
+               goto err_no_mem;
+
+       /* Persistant Reconnect */
+       if (!wpa_dbus_dict_append_bool(&dict_iter, "PersistantReconnect",
+                                      wpa_s->conf->persistent_reconnect))
+               goto err_no_mem;
+
+       /* Listen Reg Class */
+       if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenRegClass",
+                                        wpa_s->conf->p2p_listen_reg_class))
+               goto err_no_mem;
+
+       /* Listen Channel */
+       if (!wpa_dbus_dict_append_uint32(&dict_iter, "ListenChannel",
+                                        wpa_s->conf->p2p_listen_channel))
+               goto err_no_mem;
+
+       /* Oper Reg Class */
+       if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperRegClass",
+                                        wpa_s->conf->p2p_oper_reg_class))
+               goto err_no_mem;
+
+       /* Oper Channel */
+       if (!wpa_dbus_dict_append_uint32(&dict_iter, "OperChannel",
+                                        wpa_s->conf->p2p_oper_channel))
+               goto err_no_mem;
+
+       /* SSID Postfix */
+       if (wpa_s->conf->p2p_ssid_postfix &&
+           !wpa_dbus_dict_append_string(&dict_iter, "SsidPostfix",
+                                        wpa_s->conf->p2p_ssid_postfix))
+               goto err_no_mem;
+
+       /* Intra Bss */
+       if (!wpa_dbus_dict_append_bool(&dict_iter, "IntraBss",
+                                      wpa_s->conf->p2p_intra_bss))
+               goto err_no_mem;
+
+       /* Group Idle */
+       if (!wpa_dbus_dict_append_uint32(&dict_iter, "GroupIdle",
+                                        wpa_s->conf->p2p_group_idle))
+               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 reply;
+err_no_mem:
+       dbus_message_unref(reply);
+       return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
+}
+
+DBusMessage *wpas_dbus_setter_p2p_device_properties(DBusMessage * message,
+                                                   struct wpa_supplicant *
+                                                   wpa_s)
+{
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter, variant_iter;
+       struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
+       DBusMessageIter iter_dict;
+       unsigned int i;
+
+       dbus_message_iter_init(message, &iter);
+
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_next(&iter);
+
+       dbus_message_iter_recurse(&iter, &variant_iter);
+
+       if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict))
+               return wpas_dbus_error_invalid_args(message, NULL);
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       return wpas_dbus_error_invalid_args(message, NULL);
+
+               if (os_strcmp(entry.key, "DeviceName") == 0) {
+                       char *devname;
+
+                       if (entry.type != DBUS_TYPE_STRING)
+                               goto error_clear;
+
+                       devname = os_strdup(entry.str_value);
+                       if (devname == NULL)
+                               goto err_no_mem_clear;
+
+                       os_free(wpa_s->conf->device_name);
+                       wpa_s->conf->device_name = devname;
+
+                       wpa_s->conf->changed_parameters |=
+                                                       CFG_CHANGED_DEVICE_NAME;
+               } else if (os_strcmp(entry.key, "PrimaryDeviceType") == 0) {
+                       if (entry.type != DBUS_TYPE_ARRAY ||
+                           entry.array_type != DBUS_TYPE_BYTE ||
+                           entry.array_len != WPS_DEV_TYPE_LEN)
+                               goto error_clear;
+
+                       os_memcpy(wpa_s->conf->device_type,
+                                 entry.bytearray_value,
+                                 WPS_DEV_TYPE_LEN);
+                       wpa_s->conf->changed_parameters |=
+                               CFG_CHANGED_DEVICE_TYPE;
+               } else if (os_strcmp(entry.key, "SecondaryDeviceTypes") == 0) {
+                       if (entry.type != DBUS_TYPE_ARRAY ||
+                           entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
+                           entry.array_len > MAX_SEC_DEVICE_TYPES)
+                               goto error;
+
+                       for (i = 0; i < entry.array_len; i++)
+                               if (wpabuf_len(entry.binarray_value[i]) != WPS_DEV_TYPE_LEN)
+                                       goto err_no_mem_clear;
+                       for (i = 0; i < entry.array_len; i++)
+                               os_memcpy(wpa_s->conf->sec_device_type[i],
+                                         wpabuf_head(entry.binarray_value[i]),
+                                         WPS_DEV_TYPE_LEN);
+                       wpa_s->conf->num_sec_device_types = entry.array_len;
+                       wpa_s->conf->changed_parameters |=
+                                       CFG_CHANGED_SEC_DEVICE_TYPE;
+               } else if (os_strcmp(entry.key, "VendorExtension") == 0) {
+                       if ((entry.type != DBUS_TYPE_ARRAY) ||
+                           (entry.array_type != WPAS_DBUS_TYPE_BINARRAY) ||
+                           (entry.array_len > P2P_MAX_WPS_VENDOR_EXT))
+                               goto error_clear;
+
+                       wpa_s->conf->changed_parameters |=
+                                       CFG_CHANGED_VENDOR_EXTENSION;
+
+                       for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
+                               wpabuf_free(wpa_s->conf->wps_vendor_ext[i]);
+                               if (i < entry.array_len) {
+                                       wpa_s->conf->wps_vendor_ext[i] =
+                                               entry.binarray_value[i];
+                                       entry.binarray_value[i] = NULL;
+                               } else
+                                       wpa_s->conf->wps_vendor_ext[i] = NULL;
+                       }
+               } else if ((os_strcmp(entry.key, "GOIntent") == 0) &&
+                          (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) &&
+                        (entry.type == DBUS_TYPE_BOOLEAN))
+                       wpa_s->conf->persistent_reconnect = entry.bool_value;
+
+               else if ((os_strcmp(entry.key, "ListenRegClass") == 0) &&
+                        (entry.type == DBUS_TYPE_UINT32))
+                       wpa_s->conf->p2p_listen_reg_class = entry.uint32_value;
+
+               else if ((os_strcmp(entry.key, "ListenChannel") == 0) &&
+                        (entry.type == DBUS_TYPE_UINT32))
+                       wpa_s->conf->p2p_listen_channel = entry.uint32_value;
+
+               else if ((os_strcmp(entry.key, "OperRegClass") == 0) &&
+                        (entry.type == DBUS_TYPE_UINT32))
+                       wpa_s->conf->p2p_oper_reg_class = entry.uint32_value;
+
+               else if ((os_strcmp(entry.key, "OperChannel") == 0) &&
+                        (entry.type == DBUS_TYPE_UINT32))
+                       wpa_s->conf->p2p_oper_channel = entry.uint32_value;
+
+               else if (os_strcmp(entry.key, "SsidPostfix") == 0) {
+                       char *postfix;
+
+                       if (entry.type != DBUS_TYPE_STRING)
+                               goto error_clear;
+
+                       postfix = os_strdup(entry.str_value);
+                       if (!postfix)
+                               goto err_no_mem_clear;
+
+                       os_free(wpa_s->conf->p2p_ssid_postfix);
+                       wpa_s->conf->p2p_ssid_postfix = postfix;
+
+                       wpa_s->conf->changed_parameters |=
+                                       CFG_CHANGED_P2P_SSID_POSTFIX;
+               } else if ((os_strcmp(entry.key, "IntraBss") == 0) &&
+                          (entry.type == DBUS_TYPE_BOOLEAN)) {
+                       wpa_s->conf->p2p_intra_bss = entry.bool_value;
+                       wpa_s->conf->changed_parameters |=
+                                                     CFG_CHANGED_P2P_INTRA_BSS;
+               } else if ((os_strcmp(entry.key, "GroupIdle") == 0) &&
+                          (entry.type == DBUS_TYPE_UINT32))
+                       wpa_s->conf->p2p_group_idle = entry.uint32_value;
+               else
+                       goto error_clear;
+
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+
+       if (wpa_s->conf->changed_parameters) {
+               /* Some changed parameters requires to update config*/
+               wpa_supplicant_update_config(wpa_s);
+       }
+
+       return reply;
+
+ error_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+ error:
+       reply = wpas_dbus_error_invalid_args(message, entry.key);
+       wpa_dbus_dict_entry_clear(&entry);
+
+       return reply;
+ err_no_mem_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+       return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
+}
+
+DBusMessage *wpas_dbus_getter_p2p_peers(DBusMessage * message,
+                                       struct wpa_supplicant * wpa_s)
+{
+       DBusMessage *reply = NULL;
+       struct p2p_data *p2p = wpa_s->global->p2p;
+       int next = 0, i = 0;
+       int num = 0, out_of_mem = 0;
+       const u8 *addr;
+       const struct p2p_peer_info *peer_info = NULL;
+
+       struct dl_list peer_objpath_list;
+       struct peer_objpath_node {
+               struct dl_list list;
+               char path[WPAS_DBUS_OBJECT_PATH_MAX];
+       } *node, *tmp;
+
+       char **peer_obj_paths = NULL;
+
+       dl_list_init(&peer_objpath_list);
+
+       /* Get the first peer info */
+       peer_info = p2p_get_peer_found(p2p, NULL, next);
+
+       /* Get next and accumulate them */
+       next = 1;
+       while (peer_info != NULL) {
+               node = os_zalloc(sizeof(struct peer_objpath_node));
+               if (!node) {
+                       out_of_mem = 1;
+                       goto error;
+               }
+
+               addr = peer_info->p2p_device_addr;
+               os_snprintf(node->path, WPAS_DBUS_OBJECT_PATH_MAX,
+                           "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART
+                           "/" COMPACT_MACSTR,
+                           wpa_s->dbus_new_path, MAC2STR(addr));
+               dl_list_add_tail(&peer_objpath_list, &node->list);
+               num++;
+
+               peer_info = p2p_get_peer_found(p2p, addr, next);
+       }
+
+       /*
+        * Now construct the peer object paths in a form suitable for
+        * array_property_getter helper below.
+        */
+       peer_obj_paths = os_zalloc(num * sizeof(char *));
+
+       if (!peer_obj_paths) {
+               out_of_mem = 1;
+               goto error;
+       }
+
+       dl_list_for_each_safe(node, tmp, &peer_objpath_list,
+                             struct peer_objpath_node, list)
+               peer_obj_paths[i++] = node->path;
+
+       reply = wpas_dbus_simple_array_property_getter(message,
+                                                      DBUS_TYPE_OBJECT_PATH,
+                                                      peer_obj_paths, num);
+
+error:
+       if (peer_obj_paths)
+               os_free(peer_obj_paths);
+
+       dl_list_for_each_safe(node, tmp, &peer_objpath_list,
+                             struct peer_objpath_node, list) {
+               dl_list_del(&node->list);
+               os_free(node);
+       }
+       if (out_of_mem)
+               reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+                                              NULL);
+
+       return reply;
+}
+
+enum wpas_p2p_role {
+       WPAS_P2P_ROLE_DEVICE,
+       WPAS_P2P_ROLE_GO,
+       WPAS_P2P_ROLE_CLIENT,
+};
+
+static enum wpas_p2p_role wpas_get_p2p_role(struct wpa_supplicant *wpa_s)
+{
+       struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+       if (!ssid)
+               return WPAS_P2P_ROLE_DEVICE;
+       if (wpa_s->wpa_state != WPA_COMPLETED)
+               return WPAS_P2P_ROLE_DEVICE;
+
+       switch (ssid->mode) {
+       case WPAS_MODE_P2P_GO:
+       case WPAS_MODE_P2P_GROUP_FORMATION:
+               return WPAS_P2P_ROLE_GO;
+       case WPAS_MODE_INFRA:
+               if (ssid->p2p_group)
+                       return WPAS_P2P_ROLE_CLIENT;
+               return WPAS_P2P_ROLE_DEVICE;
+       default:
+               return WPAS_P2P_ROLE_DEVICE;
+       }
+}
+
+DBusMessage *wpas_dbus_getter_p2p_role(DBusMessage * message,
+                                      struct wpa_supplicant * wpa_s)
+{
+       char *str;
+
+       switch (wpas_get_p2p_role(wpa_s)) {
+       case WPAS_P2P_ROLE_GO:
+               str = "GO";
+               break;
+       case WPAS_P2P_ROLE_CLIENT:
+               str = "client";
+               break;
+       default:
+               str = "device";
+       }
+
+       return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
+                                               &str);
+}
+
+DBusMessage *wpas_dbus_getter_p2p_group(DBusMessage * message,
+                                       struct wpa_supplicant * wpa_s)
+{
+       if (wpa_s->dbus_groupobj_path == NULL)
+               return NULL;
+
+       return wpas_dbus_simple_property_getter(message,
+                                               DBUS_TYPE_OBJECT_PATH,
+                                               &wpa_s->dbus_groupobj_path);
+}
+
+DBusMessage *wpas_dbus_getter_p2p_peergo(DBusMessage * message,
+                                        struct wpa_supplicant * wpa_s)
+{
+       char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+
+       if (wpas_get_p2p_role(wpa_s) != WPAS_P2P_ROLE_CLIENT)
+               return NULL;
+
+       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(message,
+                                               DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+/*
+ * Peer object properties accessor methods
+ */
+
+DBusMessage *wpas_dbus_getter_p2p_peer_properties(DBusMessage * message,
+                                                 struct peer_handler_args *
+                                                 peer_args)
+{
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter, variant_iter, dict_iter;
+       const struct p2p_peer_info *info = NULL;
+       char devtype[WPS_DEV_TYPE_BUFSIZE];
+
+       /* get the peer info */
+       info = p2p_get_peer_found(peer_args->wpa_s->global->p2p,
+                                 peer_args->p2p_device_addr, 0);
+       if (info == NULL)
+               return NULL;
+
+       if (message == NULL)
+               reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+       else
+               reply = dbus_message_new_method_return(message);
+
+       if (!reply)
+               goto err_no_mem;
+
+       dbus_message_iter_init_append(reply, &iter);
+       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;
+
+       /* Fill out the dictionary */
+       wps_dev_type_bin2str(info->pri_dev_type, devtype, sizeof(devtype));
+       if (!wpa_dbus_dict_append_string(&dict_iter, "DeviceName",
+                                        info->device_name))
+               goto err_no_mem;
+       if (!wpa_dbus_dict_append_string(&dict_iter, "PrimaryDeviceType",
+                                        devtype))
+               goto err_no_mem;
+       if (!wpa_dbus_dict_append_uint16(&dict_iter, "config_method",
+                                        info->config_methods))
+               goto err_no_mem;
+       if (!wpa_dbus_dict_append_byte(&dict_iter, "devicecapability",
+                                      info->dev_capab))
+               goto err_no_mem;
+       if (!wpa_dbus_dict_append_byte(&dict_iter, "groupcapability",
+                                      info->group_capab))
+               goto err_no_mem;
+
+       if (info->wps_sec_dev_type_list_len) {
+               char *sec_dev_types[MAX_SEC_DEVICE_TYPES];
+               u8 *sec_dev_type_list = NULL;
+               char secdevtype[WPS_DEV_TYPE_BUFSIZE];
+               int num_sec_dev_types = 0;
+               int i;
+
+               sec_dev_type_list = os_zalloc(info->wps_sec_dev_type_list_len);
+
+               if (sec_dev_type_list == NULL)
+                       goto err_no_mem;
+
+               os_memcpy(sec_dev_type_list, info->wps_sec_dev_type_list,
+                         info->wps_sec_dev_type_list_len);
+
+               for (i = 0; i < MAX_SEC_DEVICE_TYPES &&
+                      i < (int) (info->wps_sec_dev_type_list_len /
+                                 WPS_DEV_TYPE_LEN);
+                    i++) {
+                       sec_dev_types[i] = os_zalloc(sizeof(secdevtype));
+
+                       if (!sec_dev_types[i] ||
+                           wps_dev_type_bin2str(
+                                       &sec_dev_type_list[i *
+                                                          WPS_DEV_TYPE_LEN],
+                                       sec_dev_types[i],
+                                       sizeof(secdevtype)) == NULL) {
+                               while (--i >= 0)
+                                       os_free(sec_dev_types[i]);
+                               os_free(sec_dev_type_list);
+                               goto err_no_mem;
+                       }
+
+                       num_sec_dev_types++;
+               }
+
+               os_free(sec_dev_type_list);
+
+               if (num_sec_dev_types) {
+                       if (!wpa_dbus_dict_append_string_array(&dict_iter,
+                                               "SecondaryDeviceTypes",
+                                               (const char **)sec_dev_types,
+                                               num_sec_dev_types)) {
+                               for (i = 0; i < num_sec_dev_types; i++)
+                                       os_free(sec_dev_types[i]);
+                               goto err_no_mem;
+                       }
+
+                       for (i = 0; i < num_sec_dev_types; i++)
+                               os_free(sec_dev_types[i]);
+               }
+       }
+
+       {
+               /* Add WPS vendor extensions attribute */
+               const struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
+               int i, num = 0;
+
+               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 (!wpa_dbus_dict_append_wpabuf_array(
+                                       &dict_iter, "VendorExtension",
+                                       vendor_extension, num))
+                       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 reply;
+err_no_mem:
+       dbus_message_unref(reply);
+       return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
+}
+
+DBusMessage *wpas_dbus_getter_p2p_peer_ies(DBusMessage * message,
+                                          struct peer_handler_args * peer_args)
+{
+       return NULL;
+}
+
+
+/*
+ * Group object properties accessor methods
+ */
+
+DBusMessage *wpas_dbus_getter_p2p_group_members(DBusMessage * message,
+                                               struct wpa_supplicant * wpa_s)
+{
+       DBusMessage *reply = NULL;
+       struct wpa_ssid *ssid;
+       unsigned int num_members;
+       char **paths;
+       unsigned int i;
+       void *next = NULL;
+       const u8 *addr;
+
+       /* Ensure we are a GO */
+       if (wpa_s->wpa_state != WPA_COMPLETED)
+               goto out;
+
+       ssid = wpa_s->conf->ssid;
+       /* At present WPAS P2P_GO mode only applicable for p2p_go */
+       if (ssid->mode != WPAS_MODE_P2P_GO &&
+           ssid->mode != WPAS_MODE_AP &&
+           ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
+               goto out;
+
+       num_members = p2p_get_group_num_members(wpa_s->p2p_group);
+
+       paths = os_zalloc(num_members * sizeof(char *));
+       if (!paths)
+               goto out_of_memory;
+
+       i = 0;
+       while ((addr = p2p_iterate_group_members(wpa_s->p2p_group, &next))) {
+               paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+               if (!paths[i])
+                       goto out_of_memory;
+               os_snprintf(paths[i], WPAS_DBUS_OBJECT_PATH_MAX,
+                           "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART
+                           "/" COMPACT_MACSTR,
+                           wpa_s->dbus_groupobj_path, MAC2STR(addr));
+               i++;
+       }
+
+       reply = wpas_dbus_simple_array_property_getter(message,
+                                                      DBUS_TYPE_OBJECT_PATH,
+                                                      paths, num_members);
+
+out_free:
+       for (i = 0; i < num_members; i++)
+               os_free(paths[i]);
+       os_free(paths);
+out:
+       return reply;
+out_of_memory:
+       reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
+       goto out_free;
+}
+
+
+DBusMessage *wpas_dbus_getter_p2p_group_properties(
+       DBusMessage *message,
+       struct wpa_supplicant *wpa_s)
+{
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter, variant_iter, dict_iter;
+       struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
+       const struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
+       int num_vendor_ext = 0;
+       int i;
+
+       if (!hapd) {
+               reply = dbus_message_new_error(message, DBUS_ERROR_FAILED,
+                                              NULL);
+               return reply;
+       }
+
+       if (message == NULL)
+               reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+       else
+               reply = dbus_message_new_method_return(message);
+
+       if (!reply)
+               goto err_no_mem;
+
+       dbus_message_iter_init_append(reply, &iter);
+
+       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;
+
+       /* Parse WPS Vendor Extensions sent in Beacon/Probe Response */
+       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;
+
+       if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
+           !dbus_message_iter_close_container(&iter, &variant_iter))
+               goto err_no_mem;
+
+       return reply;
+
+err_no_mem:
+       dbus_message_unref(reply);
+       return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
+}
+
+DBusMessage *wpas_dbus_setter_p2p_group_properties(
+       DBusMessage *message,
+       struct wpa_supplicant *wpa_s)
+{
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter, variant_iter;
+       struct wpa_dbus_dict_entry entry = {.type = DBUS_TYPE_STRING };
+       DBusMessageIter iter_dict;
+       unsigned int i;
+
+       struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
+
+       if (!hapd)
+               goto error;
+
+       dbus_message_iter_init(message, &iter);
+
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_next(&iter);
+
+       dbus_message_iter_recurse(&iter, &variant_iter);
+
+       if (!wpa_dbus_dict_open_read(&variant_iter, &iter_dict))
+               return wpas_dbus_error_invalid_args(message, NULL);
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
+                       reply = wpas_dbus_error_invalid_args(message, NULL);
+                       break;
+               }
+
+               if (os_strcmp(entry.key, "WPSVendorExtensions") == 0) {
+                       if (entry.type != DBUS_TYPE_ARRAY ||
+                           entry.array_type != WPAS_DBUS_TYPE_BINARRAY ||
+                           entry.array_len > MAX_WPS_VENDOR_EXTENSIONS)
+                               goto error;
+
+                       for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+                               if (i < entry.array_len) {
+                                       hapd->conf->wps_vendor_ext[i] =
+                                               entry.binarray_value[i];
+                                       entry.binarray_value[i] = NULL;
+                               } else
+                                       hapd->conf->wps_vendor_ext[i] = NULL;
+                       }
+
+                       hostapd_update_wps(hapd);
+               } else
+                       goto error;
+
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+
+       return reply;
+
+error:
+       reply = wpas_dbus_error_invalid_args(message, entry.key);
+       wpa_dbus_dict_entry_clear(&entry);
+
+       return reply;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_add_service(DBusMessage * message,
+                                              struct wpa_supplicant * wpa_s)
+{
+       DBusMessageIter iter_dict;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       struct wpa_dbus_dict_entry entry;
+       int upnp = 0;
+       int bonjour = 0;
+       char *service = NULL;
+       struct wpabuf *query = NULL;
+       struct wpabuf *resp = NULL;
+       u8 version = 0;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto error;
+
+       if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto error;
+
+               if (!strcmp(entry.key, "service_type") &&
+                   (entry.type == DBUS_TYPE_STRING)) {
+                       if (!strcmp(entry.str_value, "upnp"))
+                               upnp = 1;
+                       else if (!strcmp(entry.str_value, "bonjour"))
+                               bonjour = 1;
+                       else
+                               goto error_clear;
+                       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 (!strcmp(entry.key, "version") &&
+                           entry.type == DBUS_TYPE_INT32)
+                               version = entry.uint32_value;
+                       else if (!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 (!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 (!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);
+                       goto error;
+               }
+       } else
+               goto error;
+
+       return reply;
+error_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+error:
+       return wpas_dbus_error_invalid_args(message, NULL);
+}
+
+DBusMessage *wpas_dbus_handler_p2p_delete_service(DBusMessage * message,
+                                                 struct wpa_supplicant * wpa_s)
+{
+       DBusMessageIter iter_dict;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       struct wpa_dbus_dict_entry entry;
+       int upnp = 0;
+       int bonjour = 0;
+       int ret = 0;
+       char *service = NULL;
+       struct wpabuf *query = NULL;
+       u8 version = 0;
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto error;
+
+       if (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto error;
+
+               if (!strcmp(entry.key, "service_type") &&
+                   (entry.type == DBUS_TYPE_STRING)) {
+                       if (!strcmp(entry.str_value, "upnp"))
+                               upnp = 1;
+                       else if (!strcmp(entry.str_value, "bonjour"))
+                               bonjour = 1;
+                       else
+                               goto error_clear;
+                       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 (!strcmp(entry.key, "version") &&
+                           entry.type == DBUS_TYPE_INT32)
+                               version = entry.uint32_value;
+                       else if (!strcmp(entry.key, "service") &&
+                                entry.type == DBUS_TYPE_STRING)
+                               service = os_strdup(entry.str_value);
+                       else
+                               goto error_clear;
+
+                       wpa_dbus_dict_entry_clear(&entry);
+               }
+
+               if (version <= 0 || service == NULL)
+                       goto error;
+
+               ret = wpas_p2p_service_del_upnp(wpa_s, version, service);
+               os_free(service);
+               if (ret != 0)
+                       goto error;
+       } 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 (!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
+                               goto error_clear;
+
+                       wpa_dbus_dict_entry_clear(&entry);
+               }
+
+               if (query == NULL)
+                       goto error;
+
+               ret = wpas_p2p_service_del_bonjour(wpa_s, query);
+               if (ret != 0)
+                       goto error;
+               wpabuf_free(query);
+       } else
+               goto error;
+
+       return reply;
+error_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+error:
+       return wpas_dbus_error_invalid_args(message, NULL);
+}
+
+DBusMessage *wpas_dbus_handler_p2p_flush_service(DBusMessage * message,
+                                                struct wpa_supplicant * wpa_s)
+{
+       wpas_p2p_service_flush(wpa_s);
+       return NULL;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_service_sd_req(DBusMessage * message,
+                                                 struct wpa_supplicant * wpa_s)
+{
+       DBusMessageIter iter_dict;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       struct wpa_dbus_dict_entry entry;
+       int upnp = 0;
+       char *service = NULL;
+       char *peer_object_path = NULL;
+       struct wpabuf *tlv = NULL;
+       u8 version = 0;
+       u64 ref = 0;
+       u8 addr[ETH_ALEN];
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto error;
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto error;
+               if (!strcmp(entry.key, "peer_object") &&
+                   entry.type == DBUS_TYPE_OBJECT_PATH) {
+                       peer_object_path = os_strdup(entry.str_value);
+               } else if (!strcmp(entry.key, "service_type") &&
+                          entry.type == DBUS_TYPE_STRING) {
+                       if (!strcmp(entry.str_value, "upnp"))
+                               upnp = 1;
+                       else
+                               goto error_clear;
+               } else if (!strcmp(entry.key, "version") &&
+                          entry.type == DBUS_TYPE_INT32) {
+                       version = entry.uint32_value;
+               } else if (!strcmp(entry.key, "service") &&
+                          entry.type == DBUS_TYPE_STRING) {
+                       service = os_strdup(entry.str_value);
+               } else if (!strcmp(entry.key, "tlv")) {
+                       if (entry.type != DBUS_TYPE_ARRAY ||
+                           entry.array_type != DBUS_TYPE_BYTE)
+                               goto error_clear;
+                       tlv = wpabuf_alloc_copy(entry.bytearray_value,
+                                               entry.array_len);
+               } else
+                       goto error_clear;
+
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+
+       if (!peer_object_path ||
+           (parse_peer_object_path(peer_object_path, addr) < 0) ||
+           (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0))
+               goto error;
+
+       if (upnp == 1) {
+               if (version <= 0 || service == NULL)
+                       goto error;
+
+               ref = (unsigned long)wpas_p2p_sd_request_upnp(wpa_s, addr,
+                                                             version, service);
+       } else {
+               if (tlv == NULL)
+                       goto error;
+               ref = (unsigned long)wpas_p2p_sd_request(wpa_s, addr, tlv);
+               wpabuf_free(tlv);
+       }
+
+       if (ref != 0) {
+               reply = dbus_message_new_method_return(message);
+               dbus_message_append_args(reply, DBUS_TYPE_UINT64,
+                                        &ref, DBUS_TYPE_INVALID);
+       } else {
+               reply = wpas_dbus_error_unknown_error(message,
+                               "Unable to send SD request");
+       }
+out:
+       os_free(service);
+       os_free(peer_object_path);
+       return reply;
+error_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+error:
+       if (tlv)
+               wpabuf_free(tlv);
+       reply = wpas_dbus_error_invalid_args(message, NULL);
+       goto out;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_service_sd_res(
+       DBusMessage *message, struct wpa_supplicant *wpa_s)
+{
+       DBusMessageIter iter_dict;
+       DBusMessage *reply = NULL;
+       DBusMessageIter iter;
+       struct wpa_dbus_dict_entry entry;
+       char *peer_object_path = NULL;
+       struct wpabuf *tlv = NULL;
+       int freq = 0;
+       int dlg_tok = 0;
+       u8 addr[ETH_ALEN];
+
+       dbus_message_iter_init(message, &iter);
+
+       if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+               goto error;
+
+       while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+               if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+                       goto error;
+
+               if (!strcmp(entry.key, "peer_object") &&
+                   entry.type == DBUS_TYPE_OBJECT_PATH) {
+                       peer_object_path = os_strdup(entry.str_value);
+               } else if (!strcmp(entry.key, "frequency") &&
+                          entry.type == DBUS_TYPE_INT32) {
+                       freq = entry.uint32_value;
+               } else if (!strcmp(entry.key, "dialog_token") &&
+                          entry.type == DBUS_TYPE_UINT32) {
+                       dlg_tok = entry.uint32_value;
+               } else if (!strcmp(entry.key, "tlvs")) {
+                       if (entry.type != DBUS_TYPE_ARRAY ||
+                           entry.array_type != DBUS_TYPE_BYTE)
+                               goto error_clear;
+                       tlv = wpabuf_alloc_copy(entry.bytearray_value,
+                                               entry.array_len);
+               } else
+                       goto error_clear;
+
+               wpa_dbus_dict_entry_clear(&entry);
+       }
+       if (!peer_object_path ||
+           (parse_peer_object_path(peer_object_path, addr) < 0) ||
+           (p2p_get_peer_info(wpa_s->global->p2p, addr, 0, NULL, 0) < 0))
+               goto error;
+
+       if (tlv == NULL)
+               goto error;
+
+       wpas_p2p_sd_response(wpa_s, freq, addr, (u8) dlg_tok, tlv);
+       wpabuf_free(tlv);
+out:
+       os_free(peer_object_path);
+       return reply;
+error_clear:
+       wpa_dbus_dict_entry_clear(&entry);
+error:
+       reply = wpas_dbus_error_invalid_args(message, NULL);
+       goto out;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_service_sd_cancel_req(DBusMessage * message, struct wpa_supplicant
+                                                        *wpa_s)
+{
+       DBusMessageIter iter;
+       u64 req = 0;
+
+       dbus_message_iter_init(message, &iter);
+       dbus_message_iter_get_basic(&iter, &req);
+
+       if (req == 0)
+               goto error;
+
+       if (!wpas_p2p_sd_cancel_request(wpa_s, (void *)(unsigned long)req))
+               goto error;
+
+       return NULL;
+error:
+       return wpas_dbus_error_invalid_args(message, NULL);
+}
+
+DBusMessage *wpas_dbus_handler_p2p_service_update(DBusMessage * message,
+                                                 struct wpa_supplicant * wpa_s)
+{
+       wpas_p2p_sd_service_update(wpa_s);
+       return NULL;
+}
+
+DBusMessage *wpas_dbus_handler_p2p_serv_disc_external(DBusMessage * message,
+                                                     struct wpa_supplicant *
+                                                     wpa_s)
+{
+       DBusMessageIter iter;
+       int ext = 0;
+
+       dbus_message_iter_init(message, &iter);
+       dbus_message_iter_get_basic(&iter, &ext);
+
+       wpa_s->p2p_sd_over_ctrl_iface = ext;
+
+       return NULL;
+
+}
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.h b/wpa_supplicant/dbus/dbus_new_handlers_p2p.h
new file mode 100644 (file)
index 0000000..b0c1929
--- /dev/null
@@ -0,0 +1,142 @@
+
+/*
+ * WPA Supplicant / dbus-based control interface for p2p
+ *
+ * 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.
+ */
+
+#ifndef DBUS_NEW_HANDLERS_P2P_H
+#define DBUS_NEW_HANDLERS_P2P_H
+
+struct peer_handler_args {
+       struct wpa_supplicant *wpa_s;
+       u8 p2p_device_addr[ETH_ALEN];
+};
+
+struct groupmember_handler_args {
+       struct wpa_supplicant *wpa_s;
+       u8 member_addr[ETH_ALEN];
+};
+
+/*
+ * P2P Device methods
+ */
+
+DBusMessage *wpas_dbus_handler_p2p_find(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_stop_find(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_rejectpeer(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_listen(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_extendedlisten(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_presence_request(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_prov_disc_req(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_group_add(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_connect(
+               DBusMessage *message,
+               struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_invite(
+               DBusMessage *message,
+               struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_disconnect(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_flush(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_add_service(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_delete_service(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_flush_service(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_service_sd_req(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_service_sd_res(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_service_sd_cancel_req(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_service_update(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_handler_p2p_serv_disc_external(
+       DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+/*
+ * P2P Device property accessor methods.
+ */
+DBusMessage *wpas_dbus_setter_p2p_device_properties(DBusMessage *message,
+                                     struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_getter_p2p_device_properties(DBusMessage *message,
+                                     struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_getter_p2p_peers(DBusMessage *message,
+                                         struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_getter_p2p_role(DBusMessage *message,
+                                         struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_getter_p2p_group(DBusMessage *message,
+                                         struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_getter_p2p_peergo(DBusMessage *message,
+                                         struct wpa_supplicant *wpa_s);
+
+/*
+ * P2P Peer properties.
+ */
+DBusMessage *wpas_dbus_getter_p2p_peer_properties(
+               DBusMessage *message,
+               struct peer_handler_args *peer);
+
+DBusMessage *wpas_dbus_getter_p2p_peer_ies(
+               DBusMessage *message,
+               struct peer_handler_args *peer);
+
+/*
+ * P2P Group properties
+ */
+
+DBusMessage *wpas_dbus_getter_p2p_group_members(
+               DBusMessage *message,
+               struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_getter_p2p_group_properties(
+               DBusMessage *message,
+               struct wpa_supplicant *wpa_s);
+
+DBusMessage *wpas_dbus_setter_p2p_group_properties(
+               DBusMessage *message,
+               struct wpa_supplicant *wpa_s);
+
+#endif /* DBUS_NEW_HANDLERS_P2P_H */
index 14741f6..6d11a3d 100644 (file)
@@ -368,12 +368,23 @@ void wpas_notify_resume(struct wpa_global *global)
 void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s,
                                  const u8 *dev_addr, int new_device)
 {
+       if (new_device) {
+               /* Create the new peer object */
+               wpas_dbus_register_peer(wpa_s, dev_addr);
+       }
+
+       /* Notify a new peer has been detected*/
+       wpas_dbus_signal_peer_device_found(wpa_s, dev_addr);
 }
 
 
 void wpas_notify_p2p_device_lost(struct wpa_supplicant *wpa_s,
                                 const u8 *dev_addr)
 {
+       wpas_dbus_unregister_peer(wpa_s, dev_addr);
+
+       /* Create signal on interface object*/
+       wpas_dbus_signal_peer_device_lost(wpa_s, dev_addr);
 }
 
 
@@ -381,23 +392,29 @@ void wpas_notify_p2p_group_removed(struct wpa_supplicant *wpa_s,
                                   const struct wpa_ssid *ssid,
                                   const char *role)
 {
+       wpas_dbus_unregister_p2p_group(wpa_s, ssid);
+
+       wpas_dbus_signal_p2p_group_removed(wpa_s, role);
 }
 
 
 void wpas_notify_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
                                const u8 *src, u16 dev_passwd_id)
 {
+       wpas_dbus_signal_p2p_go_neg_req(wpa_s, src, dev_passwd_id);
 }
 
 
 void wpas_notify_p2p_go_neg_completed(struct wpa_supplicant *wpa_s, int status)
 {
+       wpas_dbus_signal_p2p_go_neg_resp(wpa_s, status);
 }
 
 
 void wpas_notify_p2p_invitation_result(struct wpa_supplicant *wpa_s,
                                       int status, const u8 *bssid)
 {
+       wpas_dbus_signal_p2p_invitation_result(wpa_s, status, bssid);
 }
 
 
@@ -406,6 +423,8 @@ void wpas_notify_p2p_sd_request(struct wpa_supplicant *wpa_s,
                                u16 update_indic, const u8 *tlvs,
                                size_t tlvs_len)
 {
+       wpas_dbus_signal_p2p_sd_request(wpa_s, freq, sa, dialog_token,
+                                       update_indic, tlvs, tlvs_len);
 }
 
 
@@ -413,6 +432,8 @@ void wpas_notify_p2p_sd_response(struct wpa_supplicant *wpa_s,
                                 const u8 *sa, u16 update_indic,
                                 const u8 *tlvs, size_t tlvs_len)
 {
+       wpas_dbus_signal_p2p_sd_response(wpa_s, sa, update_indic,
+                                        tlvs, tlvs_len);
 }
 
 
@@ -435,6 +456,9 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
                                         u16 config_methods,
                                         unsigned int generated_pin)
 {
+       wpas_dbus_signal_p2p_provision_discovery(wpa_s, dev_addr, request,
+                                                status, config_methods,
+                                                generated_pin);
 }
 
 
@@ -442,6 +466,10 @@ void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
                                   struct wpa_ssid *ssid, int network_id,
                                   int client)
 {
+       /* Notify a group has been started */
+       wpas_dbus_register_p2p_group(wpa_s, ssid);
+
+       wpas_dbus_signal_p2p_group_started(wpa_s, ssid, client, network_id);
 }
 #endif /* CONFIG_P2P */
 
@@ -449,12 +477,35 @@ void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
 static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
                                          const u8 *sta)
 {
+       /*
+        * Register a group member object corresponding to this peer and
+        * emit a PeerJoined signal. This will check if it really is a
+        * P2P group.
+        */
+       wpas_dbus_register_p2p_groupmember(wpa_s, sta);
+
+       /*
+        * Create 'peer-joined' signal on group object -- will also
+        * check P2P itself.
+        */
+       wpas_dbus_signal_p2p_peer_joined(wpa_s, sta);
 }
 
 
 static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s,
                                            const u8 *sta)
 {
+       /*
+        * Unregister a group member object corresponding to this peer
+        * if this is a P2P group.
+        */
+       wpas_dbus_unregister_p2p_groupmember(wpa_s, sta);
+
+       /*
+        * Create 'peer-disconnected' signal on group object if this
+        * is a P2P group.
+        */
+       wpas_dbus_signal_p2p_peer_disconnected(wpa_s, sta);
 }
 
 
index b18d6d9..281c5f6 100644 (file)
@@ -342,6 +342,7 @@ struct wpa_supplicant {
 #endif /* CONFIG_CTRL_IFACE_DBUS */
 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
        char *dbus_new_path;
+       char *dbus_groupobj_path;
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
        char bridge_ifname[16];