D-Bus: Add DeviceFoundProperties signal for discovered peers
[mech_eap.git] / wpa_supplicant / dbus / dbus_new.c
index 9125665..6d73bbc 100644 (file)
@@ -633,6 +633,10 @@ void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
            !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
            !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
+           !wpa_dbus_dict_append_int32(&dict_iter, "config_error",
+                                       fail->config_error) ||
+           !wpa_dbus_dict_append_int32(&dict_iter, "error_indication",
+                                       fail->error_indication) ||
            !wpa_dbus_dict_close_write(&iter, &dict_iter))
                wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
        else
@@ -1203,7 +1207,7 @@ static int match_group_where_peer_is_client(struct p2p_group *group,
                                         cfg->ssid_len);
        if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
                wpas_dbus_signal_peer_groups_changed(
-                       data->wpa_s->parent, data->info->p2p_device_addr);
+                       data->wpa_s->p2pdev, data->info->p2p_device_addr);
                return 0;
        }
 
@@ -1220,7 +1224,7 @@ static void signal_peer_groups_changed(struct p2p_peer_info *info,
        wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
                                             info->p2p_device_addr);
        if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
-               wpas_dbus_signal_peer_groups_changed(data->wpa_s->parent,
+               wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
                                                     info->p2p_device_addr);
                return;
        }
@@ -1250,14 +1254,11 @@ static void peer_groups_changed(struct wpa_supplicant *wpa_s)
  * irrespective of the role (client/GO) of the current device
  *
  * @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
+ * @persistent: 0 - non persistent group, 1 - persistent group
  */
 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
-                                       const struct wpa_ssid *ssid,
-                                       int client, int network_id)
+                                       int client, int persistent)
 {
        DBusMessage *msg;
        DBusMessageIter iter, dict_iter;
@@ -1296,6 +1297,7 @@ void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
                                              wpa_s->dbus_new_path) ||
            !wpa_dbus_dict_append_string(&dict_iter, "role",
                                         client ? "client" : "GO") ||
+           !wpa_dbus_dict_append_bool(&dict_iter, "persistent", persistent) ||
            !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
                                              wpa_s->dbus_groupobj_path) ||
            !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
@@ -1424,12 +1426,10 @@ err:
 
 
 /**
- *
- * 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
+ * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @status: Status of invitation process
+ * @bssid: Basic Service Set Identifier
  */
 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
                                            int status, const u8 *bssid)
@@ -1859,6 +1859,99 @@ void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
        dbus_message_unref(msg);
 }
 
+
+/**
+ * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event
+ * @wpa_s: %wpa_supplicant network interface data
+ * @reason: indicates the reason code for group formation failure
+ *
+ * Sends Event dbus signal and string reason code when available.
+ */
+void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
+                                                 const char *reason)
+{
+       DBusMessage *msg;
+       struct wpas_dbus_priv *iface;
+
+       iface = wpa_s->global->dbus;
+
+       /* 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,
+                                     "GroupFormationFailure");
+       if (msg == NULL)
+               return;
+
+       if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
+                                    DBUS_TYPE_INVALID))
+               dbus_connection_send(iface->con, msg, NULL);
+       else
+               wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+
+       dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @sa: Source address of the Invitation Request
+ * @dev_add: GO Device Address
+ * @bssid: P2P Group BSSID or %NULL if not received
+ * @id: Persistent group id or %0 if not persistent group
+ * @op_freq: Operating frequency for the group
+ */
+
+void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
+                                             const u8 *sa, const u8 *dev_addr,
+                                             const u8 *bssid, int id,
+                                             int op_freq)
+{
+       DBusMessage *msg;
+       DBusMessageIter iter, dict_iter;
+       struct wpas_dbus_priv *iface;
+
+       iface = wpa_s->global->dbus;
+
+       /* 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,
+                                     "InvitationReceived");
+       if (msg == NULL)
+               return;
+
+       dbus_message_iter_init_append(msg, &iter);
+       if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+           (sa &&
+            !wpa_dbus_dict_append_byte_array(&dict_iter, "sa",
+                                             (const char *) sa, ETH_ALEN)) ||
+           (dev_addr &&
+            !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr",
+                                             (const char *) dev_addr,
+                                             ETH_ALEN)) ||
+           (bssid &&
+            !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
+                                             (const char *) bssid,
+                                             ETH_ALEN)) ||
+           (id &&
+            !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) ||
+           !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) ||
+           !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
+               dbus_message_unref(msg);
+               return;
+       }
+
+       dbus_connection_send(iface->con, msg, NULL);
+       dbus_message_unref(msg);
+}
+
+
 #endif /* CONFIG_P2P */
 
 
@@ -1906,6 +1999,10 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
                prop = "DisconnectReason";
                flush = TRUE;
                break;
+       case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
+               prop = "AssocStatusCode";
+               flush = TRUE;
+               break;
        default:
                wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
                           __func__, property);
@@ -2078,41 +2175,54 @@ static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
                  END_ARGS
          }
        },
+       { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
+         (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
+         {
+               END_ARGS
+         }
+       },
        { NULL, NULL, NULL, { END_ARGS } }
 };
 
 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
        { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
          wpas_dbus_getter_debug_level,
-         wpas_dbus_setter_debug_level
+         wpas_dbus_setter_debug_level,
+         NULL
        },
        { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
          wpas_dbus_getter_debug_timestamp,
-         wpas_dbus_setter_debug_timestamp
+         wpas_dbus_setter_debug_timestamp,
+         NULL
        },
        { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
          wpas_dbus_getter_debug_show_keys,
-         wpas_dbus_setter_debug_show_keys
+         wpas_dbus_setter_debug_show_keys,
+         NULL
        },
        { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
          wpas_dbus_getter_interfaces,
+         NULL,
          NULL
        },
        { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
          wpas_dbus_getter_eap_methods,
+         NULL,
          NULL
        },
        { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
          wpas_dbus_getter_global_capabilities,
+         NULL,
          NULL
        },
 #ifdef CONFIG_WIFI_DISPLAY
        { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
          wpas_dbus_getter_global_wfd_ies,
-         wpas_dbus_setter_global_wfd_ies
+         wpas_dbus_setter_global_wfd_ies,
+         NULL
        },
 #endif /* CONFIG_WIFI_DISPLAY */
-       { NULL, NULL, NULL, NULL, NULL }
+       { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
@@ -2140,12 +2250,50 @@ static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
 };
 
 
+static char * uscore_to_dbus(const char *uscore)
+{
+       const char *p = uscore;
+       char *str, *s;
+       dbus_bool_t last_was_uscore = TRUE;
+
+       s = str = os_zalloc(os_strlen(uscore) + 1);
+       if (!str)
+               return NULL;
+       while (p && *p) {
+               if (*p == '_') {
+                       last_was_uscore = TRUE;
+               } else {
+                       *s++ = last_was_uscore ? toupper(*p) : *p;
+                       last_was_uscore = FALSE;
+               }
+               p++;
+       }
+
+       return str;
+}
+
+
+static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
+
+
+static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
+{
+       int idx = priv->globals_start;
+
+       /* Free all allocated property values */
+       while (priv->all_interface_properties[idx].dbus_property)
+               os_free((char *)
+                       priv->all_interface_properties[idx++].dbus_property);
+       os_free((char *) priv->all_interface_properties);
+}
+
+
 /**
  * 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
+ * Initialize the dbus control interface for wpa_supplicant and start
  * receiving commands from external programs over the bus.
  */
 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
@@ -2153,11 +2301,18 @@ int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
        struct wpa_dbus_object_desc *obj_desc;
        int ret;
 
+       ret = wpa_dbus_ctrl_iface_props_init(priv);
+       if (ret < 0) {
+               wpa_printf(MSG_ERROR,
+                          "dbus: Not enough memory to init interface properties");
+               return -1;
+       }
+
        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;
+               goto error;
        }
 
        wpas_dbus_register(obj_desc, priv->global, NULL,
@@ -2170,31 +2325,36 @@ int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
        ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
                                       WPAS_DBUS_NEW_SERVICE,
                                       obj_desc);
-       if (ret < 0)
+       if (ret < 0) {
                free_dbus_object_desc(obj_desc);
-       else
-               priv->dbus_new_initialized = 1;
+               goto error;
+       }
 
-       return ret;
+       priv->dbus_new_initialized = 1;
+       return 0;
+
+error:
+       wpa_dbus_ctrl_iface_props_deinit(priv);
+       return -1;
 }
 
 
 /**
  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
  * wpa_supplicant
- * @iface: Pointer to dbus private data from wpas_dbus_init()
+ * @priv: 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)
+void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
 {
-       if (!iface->dbus_new_initialized)
+       if (!priv->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);
+       dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
+       wpa_dbus_ctrl_iface_props_deinit(priv);
 }
 
 
@@ -2207,13 +2367,15 @@ static void wpa_dbus_free(void *ptr)
 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
        { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
          wpas_dbus_getter_network_properties,
-         wpas_dbus_setter_network_properties
+         wpas_dbus_setter_network_properties,
+         NULL
        },
        { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
          wpas_dbus_getter_enabled,
-         wpas_dbus_setter_enabled
+         wpas_dbus_setter_enabled,
+         NULL
        },
-       { NULL, NULL, NULL, NULL, NULL }
+       { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 
@@ -2352,53 +2514,65 @@ int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
        { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
          wpas_dbus_getter_bss_ssid,
+         NULL,
          NULL
        },
        { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
          wpas_dbus_getter_bss_bssid,
+         NULL,
          NULL
        },
        { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
          wpas_dbus_getter_bss_privacy,
+         NULL,
          NULL
        },
        { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
          wpas_dbus_getter_bss_mode,
+         NULL,
          NULL
        },
        { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
          wpas_dbus_getter_bss_signal,
+         NULL,
          NULL
        },
        { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
          wpas_dbus_getter_bss_frequency,
+         NULL,
          NULL
        },
        { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
          wpas_dbus_getter_bss_rates,
+         NULL,
          NULL
        },
        { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
          wpas_dbus_getter_bss_wpa,
+         NULL,
          NULL
        },
        { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
          wpas_dbus_getter_bss_rsn,
+         NULL,
          NULL
        },
        { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
          wpas_dbus_getter_bss_wps,
+         NULL,
          NULL
        },
        { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
          wpas_dbus_getter_bss_ies,
+         NULL,
          NULL
        },
        { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
          wpas_dbus_getter_bss_age,
+         NULL,
          NULL
        },
-       { NULL, NULL, NULL, NULL, NULL }
+       { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 
@@ -2734,6 +2908,13 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
                  END_ARGS
          }
        },
+       { "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
+         {
+                 { "args", "a{sv}", ARG_IN },
+                 END_ARGS
+         }
+       },
        { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
          {
@@ -2891,131 +3072,197 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
          }
        },
 #endif /* CONFIG_TDLS */
+       { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
+         {
+                 { "frame_id", "i", ARG_IN },
+                 { "ielems", "ay", ARG_IN },
+                 END_ARGS
+         }
+       },
+       { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
+         {
+                 { "frame_id", "i", ARG_IN },
+                 { "ielems", "ay", ARG_OUT },
+                 END_ARGS
+         }
+       },
+       { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
+         {
+                 { "frame_id", "i", ARG_IN },
+                 { "ielems", "ay", ARG_IN },
+                 END_ARGS
+         }
+       },
+#ifndef CONFIG_NO_CONFIG_WRITE
+       { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
+         (WPADBusMethodHandler) wpas_dbus_handler_save_config,
+         {
+                 END_ARGS
+         }
+       },
+#endif /* CONFIG_NO_CONFIG_WRITE */
        { NULL, NULL, NULL, { END_ARGS } }
 };
 
 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
        { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
          wpas_dbus_getter_capabilities,
+         NULL,
          NULL
        },
        { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_state,
+         NULL,
          NULL
        },
        { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
          wpas_dbus_getter_scanning,
+         NULL,
          NULL
        },
        { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
          wpas_dbus_getter_ap_scan,
-         wpas_dbus_setter_ap_scan
+         wpas_dbus_setter_ap_scan,
+         NULL
        },
        { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
          wpas_dbus_getter_bss_expire_age,
-         wpas_dbus_setter_bss_expire_age
+         wpas_dbus_setter_bss_expire_age,
+         NULL
        },
        { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
          wpas_dbus_getter_bss_expire_count,
-         wpas_dbus_setter_bss_expire_count
+         wpas_dbus_setter_bss_expire_count,
+         NULL
        },
        { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_country,
-         wpas_dbus_setter_country
+         wpas_dbus_setter_country,
+         NULL
        },
        { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_ifname,
+         NULL,
          NULL
        },
        { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_driver,
+         NULL,
          NULL
        },
        { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_bridge_ifname,
+         NULL,
          NULL
        },
        { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
          wpas_dbus_getter_current_bss,
+         NULL,
          NULL
        },
        { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
          wpas_dbus_getter_current_network,
+         NULL,
          NULL
        },
        { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_current_auth_mode,
+         NULL,
          NULL
        },
        { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
          wpas_dbus_getter_blobs,
+         NULL,
          NULL
        },
        { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
          wpas_dbus_getter_bsss,
+         NULL,
          NULL
        },
        { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
          wpas_dbus_getter_networks,
+         NULL,
          NULL
        },
        { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
          wpas_dbus_getter_fast_reauth,
-         wpas_dbus_setter_fast_reauth
+         wpas_dbus_setter_fast_reauth,
+         NULL
        },
        { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
          wpas_dbus_getter_scan_interval,
-         wpas_dbus_setter_scan_interval
+         wpas_dbus_setter_scan_interval,
+         NULL
        },
        { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_pkcs11_engine_path,
+         NULL,
          NULL
        },
        { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
          wpas_dbus_getter_pkcs11_module_path,
+         NULL,
          NULL
        },
 #ifdef CONFIG_WPS
        { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
          wpas_dbus_getter_process_credentials,
-         wpas_dbus_setter_process_credentials
+         wpas_dbus_setter_process_credentials,
+         NULL
        },
        { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
          wpas_dbus_getter_config_methods,
-         wpas_dbus_setter_config_methods
+         wpas_dbus_setter_config_methods,
+         NULL
        },
 #endif /* CONFIG_WPS */
 #ifdef CONFIG_P2P
        { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
          wpas_dbus_getter_p2p_device_config,
-         wpas_dbus_setter_p2p_device_config
+         wpas_dbus_setter_p2p_device_config,
+         NULL
        },
        { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
          wpas_dbus_getter_p2p_peers,
+         NULL,
          NULL
        },
        { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
          wpas_dbus_getter_p2p_role,
+         NULL,
          NULL
        },
        { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
          wpas_dbus_getter_p2p_group,
+         NULL,
          NULL
        },
        { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
          wpas_dbus_getter_p2p_peergo,
+         NULL,
          NULL
        },
        { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
          wpas_dbus_getter_persistent_groups,
+         NULL,
          NULL
        },
 #endif /* CONFIG_P2P */
        { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
          wpas_dbus_getter_disconnect_reason,
+         NULL,
+         NULL
+       },
+       { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
+         wpas_dbus_getter_assoc_status_code,
+         NULL,
          NULL
        },
-       { NULL, NULL, NULL, NULL, NULL }
+       { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
@@ -3105,6 +3352,13 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
                  END_ARGS
          }
        },
+       { "DeviceFoundProperties", 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 },
@@ -3167,6 +3421,12 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
                  END_ARGS
          }
        },
+       { "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "reason", "s", ARG_OUT },
+                 END_ARGS
+         }
+       },
        { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
                  { "properties", "a{sv}", ARG_OUT },
@@ -3182,7 +3442,7 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
        { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
                  { "path", "o", ARG_OUT },
-                 { "dev_passwd_id", "i", ARG_OUT },
+                 { "dev_passwd_id", "q", ARG_OUT },
                  { "device_go_intent", "y", ARG_OUT },
                  END_ARGS
          }
@@ -3231,6 +3491,12 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
                  END_ARGS
          }
        },
+       { "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+         {
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_AP
        { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
@@ -3277,9 +3543,84 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
 };
 
 
-int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
+static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
 {
+       size_t all_size;
+       unsigned int i, j, count, num_const, num_globals;
+       const char *global_name;
+       static const char * const ignored_globals[] = {
+               "bss_expiration_age", "bss_expiration_scan_count",
+               "ap_scan", "country", "fast_reauth",
+               "pkcs11_engine_path", "pkcs11_module_path"
+       };
+
+       /* wpas_dbus_interface_properties terminates with a NULL element */
+       num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
+
+       num_globals = wpa_config_get_num_global_field_names();
+       priv->globals_start = num_const;
+
+       /* allocate enough for all properties + terminating NULL element */
+       all_size = (num_globals + num_const + 1) *
+               sizeof(wpas_dbus_interface_properties[0]);
+       priv->all_interface_properties = os_zalloc(all_size);
+       if (!priv->all_interface_properties) {
+               wpa_printf(MSG_ERROR,
+                          "dbus: Not enough memory for interface properties");
+               return -1;
+       }
+
+       /* Copy constant interface properties to the start of the array */
+       os_memcpy(priv->all_interface_properties,
+                 wpas_dbus_interface_properties,
+                 sizeof(wpas_dbus_interface_properties));
+
+       /* Dynamically construct interface global properties */
+       for (i = 0, count = num_const; i < num_globals; i++) {
+               struct wpa_dbus_property_desc *desc;
+               int no_var = 0;
+
+               /* ignore globals that are actually just methods */
+               global_name = wpa_config_get_global_field_name(i, &no_var);
+               if (no_var)
+                       continue;
+               /* Ignore fields already explicitly exposed */
+               for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
+                       if (os_strcmp(global_name, ignored_globals[j]) == 0)
+                               break;
+               }
+               if (j < ARRAY_SIZE(ignored_globals))
+                       continue;
+
+               desc = &priv->all_interface_properties[count++];
+               desc->dbus_property = uscore_to_dbus(global_name);
+               if (!desc->dbus_property) {
+                       wpa_printf(MSG_ERROR,
+                                  "dbus: Not enough memory for D-Bus property name");
+                       goto error;
+               }
+               desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
+               desc->type = "s";
+               desc->getter = wpas_dbus_getter_iface_global;
+               desc->setter = wpas_dbus_setter_iface_global;
+               desc->data = global_name;
+       }
+
+       return 0;
+
+error:
+       wpa_dbus_ctrl_iface_props_deinit(priv);
+       return -1;
+}
 
+
+/**
+ * wpas_dbus_register_interface - Register an interface with D-Bus
+ * @wpa_s: wpa_supplicant interface structure
+ * Returns: 0 on success, -1 on failure
+ */
+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;
@@ -3305,7 +3646,7 @@ int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
        }
 
        wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
-                          wpas_dbus_interface_properties,
+                          ctrl_iface->all_interface_properties,
                           wpas_dbus_interface_signals);
 
        wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
@@ -3327,6 +3668,11 @@ err:
 }
 
 
+/**
+ * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
+ * @wpa_s: wpa_supplicant interface structure
+ * Returns: 0 on success, -1 on failure
+ */
 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
 {
        struct wpas_dbus_priv *ctrl_iface;
@@ -3366,65 +3712,80 @@ int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
        { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
          wpas_dbus_getter_p2p_peer_device_name,
+         NULL,
          NULL
        },
        { "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
          wpas_dbus_getter_p2p_peer_manufacturer,
+         NULL,
          NULL
        },
        { "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
          wpas_dbus_getter_p2p_peer_modelname,
+         NULL,
          NULL
        },
        { "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
          wpas_dbus_getter_p2p_peer_modelnumber,
+         NULL,
          NULL
        },
        { "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
          wpas_dbus_getter_p2p_peer_serialnumber,
+         NULL,
          NULL
        },
        { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
          wpas_dbus_getter_p2p_peer_primary_device_type,
+         NULL,
          NULL
        },
        { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
          wpas_dbus_getter_p2p_peer_config_method,
+         NULL,
          NULL
        },
        { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
          wpas_dbus_getter_p2p_peer_level,
+         NULL,
          NULL
        },
        { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
          wpas_dbus_getter_p2p_peer_device_capability,
+         NULL,
          NULL
        },
        { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
          wpas_dbus_getter_p2p_peer_group_capability,
+         NULL,
          NULL
        },
        { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
          wpas_dbus_getter_p2p_peer_secondary_device_types,
+         NULL,
          NULL
        },
        { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
          wpas_dbus_getter_p2p_peer_vendor_extension,
+         NULL,
          NULL
        },
        { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
          wpas_dbus_getter_p2p_peer_ies,
+         NULL,
          NULL
        },
        { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
          wpas_dbus_getter_p2p_peer_device_address,
+         NULL,
          NULL
        },
        { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
          wpas_dbus_getter_p2p_peer_groups,
+         NULL,
          NULL
        },
-       { NULL, NULL, NULL, NULL, NULL }
+       { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
@@ -3446,12 +3807,13 @@ static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
  *     In case of peer objects, it would be emitted by either
  *     the "interface object" or by "peer objects"
  * @sig_name: signal name - DeviceFound
+ * @properties: Whether to add a second argument with object properties
  *
- * Notify listeners about event related with newly found p2p peer device
+ * Notify listeners about event related with 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)
+                                 const char *sig_name, int properties)
 {
        struct wpas_dbus_priv *iface;
        DBusMessage *msg;
@@ -3479,7 +3841,10 @@ static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
        dbus_message_iter_init_append(msg, &iter);
        path = peer_obj_path;
        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
-                                           &path))
+                                           &path) ||
+           (properties && !wpa_dbus_get_object_properties(
+                   iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
+                   &iter)))
                wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
        else
                dbus_connection_send(iface->con, msg, NULL);
@@ -3491,7 +3856,7 @@ static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
 /**
  * wpas_dbus_signal_peer_found - Send a peer found signal
  * @wpa_s: %wpa_supplicant network interface data
- * @dev: peer device object
+ * @dev_addr: Peer P2P Device Address
  *
  * Notify listeners about find a p2p peer device found
  */
@@ -3500,13 +3865,17 @@ void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
 {
        wpas_dbus_signal_peer(wpa_s, dev_addr,
                              WPAS_DBUS_NEW_IFACE_P2PDEVICE,
-                             "DeviceFound");
+                             "DeviceFound", FALSE);
+
+       wpas_dbus_signal_peer(wpa_s, dev_addr,
+                             WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+                             "DeviceFoundProperties", TRUE);
 }
 
 /**
  * wpas_dbus_signal_peer_lost - Send a peer lost signal
  * @wpa_s: %wpa_supplicant network interface data
- * @dev: peer device object
+ * @dev_addr: Peer P2P Device Address
  *
  * Notify listeners about lost a p2p peer device
  */
@@ -3515,7 +3884,7 @@ void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
 {
        wpas_dbus_signal_peer(wpa_s, dev_addr,
                              WPAS_DBUS_NEW_IFACE_P2PDEVICE,
-                             "DeviceLost");
+                             "DeviceLost", FALSE);
 }
 
 /**
@@ -3653,6 +4022,13 @@ void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
 }
 
 
+/**
+ * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @dev_addr: P2P Device Address
+ *
+ * Notify listeners about peer Groups property changes.
+ */
 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
                                          const u8 *dev_addr)
 {
@@ -3675,41 +4051,50 @@ void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
        { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
          wpas_dbus_getter_p2p_group_members,
+         NULL,
          NULL
        },
        { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
          wpas_dbus_getter_p2p_group,
+         NULL,
          NULL
        },
        { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
          wpas_dbus_getter_p2p_role,
+         NULL,
          NULL
        },
        { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
          wpas_dbus_getter_p2p_group_ssid,
+         NULL,
          NULL
        },
        { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
          wpas_dbus_getter_p2p_group_bssid,
+         NULL,
          NULL
        },
        { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
          wpas_dbus_getter_p2p_group_frequency,
+         NULL,
          NULL
        },
        { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
          wpas_dbus_getter_p2p_group_passphrase,
+         NULL,
          NULL
        },
        { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
          wpas_dbus_getter_p2p_group_psk,
+         NULL,
          NULL
        },
        { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
          wpas_dbus_getter_p2p_group_vendor_ext,
-         wpas_dbus_setter_p2p_group_vendor_ext
+         wpas_dbus_setter_p2p_group_vendor_ext,
+         NULL
        },
-       { NULL, NULL, NULL, NULL, NULL }
+       { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
@@ -3836,9 +4221,10 @@ static const struct wpa_dbus_property_desc
        wpas_dbus_persistent_group_properties[] = {
        { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
          wpas_dbus_getter_persistent_group_properties,
-         wpas_dbus_setter_persistent_group_properties
+         wpas_dbus_setter_persistent_group_properties,
+         NULL
        },
-       { NULL, NULL, NULL, NULL, NULL }
+       { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 /* No signals intended for persistent group objects */