Home | History | Annotate | Download | only in dbus
      1 /*
      2  * WPA Supplicant / dbus-based control interface
      3  * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc.
      4  * Copyright (c) 2009-2010, Witold Sowa <witold.sowa (at) gmail.com>
      5  * Copyright (c) 2009, Jouni Malinen <j (at) w1.fi>
      6  *
      7  * This software may be distributed under the terms of the BSD license.
      8  * See README for more details.
      9  */
     10 
     11 #include "includes.h"
     12 
     13 #include "common.h"
     14 #include "common/ieee802_11_defs.h"
     15 #include "wps/wps.h"
     16 #include "../config.h"
     17 #include "../wpa_supplicant_i.h"
     18 #include "../bss.h"
     19 #include "../wpas_glue.h"
     20 #include "dbus_new_helpers.h"
     21 #include "dbus_dict_helpers.h"
     22 #include "dbus_new.h"
     23 #include "dbus_new_handlers.h"
     24 #include "dbus_common_i.h"
     25 #include "dbus_new_handlers_p2p.h"
     26 #include "p2p/p2p.h"
     27 #include "../p2p_supplicant.h"
     28 
     29 #ifdef CONFIG_AP /* until needed by something else */
     30 
     31 /*
     32  * NameOwnerChanged handling
     33  *
     34  * Some services we provide allow an application to register for
     35  * a signal that it needs. While it can also unregister, we must
     36  * be prepared for the case where the application simply crashes
     37  * and thus doesn't clean up properly. The way to handle this in
     38  * DBus is to register for the NameOwnerChanged signal which will
     39  * signal an owner change to NULL if the peer closes the socket
     40  * for whatever reason.
     41  *
     42  * Handle this signal via a filter function whenever necessary.
     43  * The code below also handles refcounting in case in the future
     44  * there will be multiple instances of this subscription scheme.
     45  */
     46 static const char wpas_dbus_noc_filter_str[] =
     47 	"interface=org.freedesktop.DBus,member=NameOwnerChanged";
     48 
     49 
     50 static DBusHandlerResult noc_filter(DBusConnection *conn,
     51 				    DBusMessage *message, void *data)
     52 {
     53 	struct wpas_dbus_priv *priv = data;
     54 
     55 	if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
     56 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     57 
     58 	if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
     59 				   "NameOwnerChanged")) {
     60 		const char *name;
     61 		const char *prev_owner;
     62 		const char *new_owner;
     63 		DBusError derr;
     64 		struct wpa_supplicant *wpa_s;
     65 
     66 		dbus_error_init(&derr);
     67 
     68 		if (!dbus_message_get_args(message, &derr,
     69 					   DBUS_TYPE_STRING, &name,
     70 					   DBUS_TYPE_STRING, &prev_owner,
     71 					   DBUS_TYPE_STRING, &new_owner,
     72 					   DBUS_TYPE_INVALID)) {
     73 			/* Ignore this error */
     74 			dbus_error_free(&derr);
     75 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     76 		}
     77 
     78 		for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
     79 			if (wpa_s->preq_notify_peer != NULL &&
     80 			    os_strcmp(name, wpa_s->preq_notify_peer) == 0 &&
     81 			    (new_owner == NULL || os_strlen(new_owner) == 0)) {
     82 				/* probe request owner disconnected */
     83 				os_free(wpa_s->preq_notify_peer);
     84 				wpa_s->preq_notify_peer = NULL;
     85 				wpas_dbus_unsubscribe_noc(priv);
     86 			}
     87 		}
     88 	}
     89 
     90 	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     91 }
     92 
     93 
     94 void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv)
     95 {
     96 	priv->dbus_noc_refcnt++;
     97 	if (priv->dbus_noc_refcnt > 1)
     98 		return;
     99 
    100 	if (!dbus_connection_add_filter(priv->con, noc_filter, priv, NULL)) {
    101 		wpa_printf(MSG_ERROR, "dbus: failed to add filter");
    102 		return;
    103 	}
    104 
    105 	dbus_bus_add_match(priv->con, wpas_dbus_noc_filter_str, NULL);
    106 }
    107 
    108 
    109 void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv)
    110 {
    111 	priv->dbus_noc_refcnt--;
    112 	if (priv->dbus_noc_refcnt > 0)
    113 		return;
    114 
    115 	dbus_bus_remove_match(priv->con, wpas_dbus_noc_filter_str, NULL);
    116 	dbus_connection_remove_filter(priv->con, noc_filter, priv);
    117 }
    118 
    119 #endif /* CONFIG_AP */
    120 
    121 
    122 /**
    123  * wpas_dbus_signal_interface - Send a interface related event signal
    124  * @wpa_s: %wpa_supplicant network interface data
    125  * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
    126  * @properties: Whether to add second argument with object properties
    127  *
    128  * Notify listeners about event related with interface
    129  */
    130 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
    131 				       const char *sig_name, int properties)
    132 {
    133 	struct wpas_dbus_priv *iface;
    134 	DBusMessage *msg;
    135 	DBusMessageIter iter;
    136 
    137 	iface = wpa_s->global->dbus;
    138 
    139 	/* Do nothing if the control interface is not turned on */
    140 	if (iface == NULL || !wpa_s->dbus_new_path)
    141 		return;
    142 
    143 	msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
    144 				      WPAS_DBUS_NEW_INTERFACE, sig_name);
    145 	if (msg == NULL)
    146 		return;
    147 
    148 	dbus_message_iter_init_append(msg, &iter);
    149 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
    150 					    &wpa_s->dbus_new_path) ||
    151 	    (properties &&
    152 	     !wpa_dbus_get_object_properties(
    153 		     iface, wpa_s->dbus_new_path,
    154 		     WPAS_DBUS_NEW_IFACE_INTERFACE, &iter)))
    155 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    156 	else
    157 		dbus_connection_send(iface->con, msg, NULL);
    158 	dbus_message_unref(msg);
    159 }
    160 
    161 
    162 /**
    163  * wpas_dbus_signal_interface_added - Send a interface created signal
    164  * @wpa_s: %wpa_supplicant network interface data
    165  *
    166  * Notify listeners about creating new interface
    167  */
    168 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
    169 {
    170 	wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
    171 }
    172 
    173 
    174 /**
    175  * wpas_dbus_signal_interface_removed - Send a interface removed signal
    176  * @wpa_s: %wpa_supplicant network interface data
    177  *
    178  * Notify listeners about removing interface
    179  */
    180 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
    181 {
    182 	wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
    183 
    184 }
    185 
    186 
    187 /**
    188  * wpas_dbus_signal_scan_done - send scan done signal
    189  * @wpa_s: %wpa_supplicant network interface data
    190  * @success: indicates if scanning succeed or failed
    191  *
    192  * Notify listeners about finishing a scan
    193  */
    194 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
    195 {
    196 	struct wpas_dbus_priv *iface;
    197 	DBusMessage *msg;
    198 	dbus_bool_t succ;
    199 
    200 	iface = wpa_s->global->dbus;
    201 
    202 	/* Do nothing if the control interface is not turned on */
    203 	if (iface == NULL || !wpa_s->dbus_new_path)
    204 		return;
    205 
    206 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    207 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    208 				      "ScanDone");
    209 	if (msg == NULL)
    210 		return;
    211 
    212 	succ = success ? TRUE : FALSE;
    213 	if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
    214 				     DBUS_TYPE_INVALID))
    215 		dbus_connection_send(iface->con, msg, NULL);
    216 	else
    217 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    218 	dbus_message_unref(msg);
    219 }
    220 
    221 
    222 /**
    223  * wpas_dbus_signal_bss - Send a BSS related event signal
    224  * @wpa_s: %wpa_supplicant network interface data
    225  * @bss_obj_path: BSS object path
    226  * @sig_name: signal name - BSSAdded or BSSRemoved
    227  * @properties: Whether to add second argument with object properties
    228  *
    229  * Notify listeners about event related with BSS
    230  */
    231 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
    232 				 const char *bss_obj_path,
    233 				 const char *sig_name, int properties)
    234 {
    235 	struct wpas_dbus_priv *iface;
    236 	DBusMessage *msg;
    237 	DBusMessageIter iter;
    238 
    239 	iface = wpa_s->global->dbus;
    240 
    241 	/* Do nothing if the control interface is not turned on */
    242 	if (iface == NULL || !wpa_s->dbus_new_path)
    243 		return;
    244 
    245 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    246 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    247 				      sig_name);
    248 	if (msg == NULL)
    249 		return;
    250 
    251 	dbus_message_iter_init_append(msg, &iter);
    252 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
    253 					    &bss_obj_path) ||
    254 	    (properties &&
    255 	     !wpa_dbus_get_object_properties(iface, bss_obj_path,
    256 					     WPAS_DBUS_NEW_IFACE_BSS,
    257 					     &iter)))
    258 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    259 	else
    260 		dbus_connection_send(iface->con, msg, NULL);
    261 	dbus_message_unref(msg);
    262 }
    263 
    264 
    265 /**
    266  * wpas_dbus_signal_bss_added - Send a BSS added signal
    267  * @wpa_s: %wpa_supplicant network interface data
    268  * @bss_obj_path: new BSS object path
    269  *
    270  * Notify listeners about adding new BSS
    271  */
    272 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
    273 				       const char *bss_obj_path)
    274 {
    275 	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
    276 }
    277 
    278 
    279 /**
    280  * wpas_dbus_signal_bss_removed - Send a BSS removed signal
    281  * @wpa_s: %wpa_supplicant network interface data
    282  * @bss_obj_path: BSS object path
    283  *
    284  * Notify listeners about removing BSS
    285  */
    286 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
    287 					 const char *bss_obj_path)
    288 {
    289 	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
    290 }
    291 
    292 
    293 /**
    294  * wpas_dbus_signal_blob - Send a blob related event signal
    295  * @wpa_s: %wpa_supplicant network interface data
    296  * @name: blob name
    297  * @sig_name: signal name - BlobAdded or BlobRemoved
    298  *
    299  * Notify listeners about event related with blob
    300  */
    301 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
    302 				  const char *name, const char *sig_name)
    303 {
    304 	struct wpas_dbus_priv *iface;
    305 	DBusMessage *msg;
    306 
    307 	iface = wpa_s->global->dbus;
    308 
    309 	/* Do nothing if the control interface is not turned on */
    310 	if (iface == NULL || !wpa_s->dbus_new_path)
    311 		return;
    312 
    313 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    314 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    315 				      sig_name);
    316 	if (msg == NULL)
    317 		return;
    318 
    319 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
    320 				     DBUS_TYPE_INVALID))
    321 		dbus_connection_send(iface->con, msg, NULL);
    322 	else
    323 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    324 	dbus_message_unref(msg);
    325 }
    326 
    327 
    328 /**
    329  * wpas_dbus_signal_blob_added - Send a blob added signal
    330  * @wpa_s: %wpa_supplicant network interface data
    331  * @name: blob name
    332  *
    333  * Notify listeners about adding a new blob
    334  */
    335 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
    336 				 const char *name)
    337 {
    338 	wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
    339 }
    340 
    341 
    342 /**
    343  * wpas_dbus_signal_blob_removed - Send a blob removed signal
    344  * @wpa_s: %wpa_supplicant network interface data
    345  * @name: blob name
    346  *
    347  * Notify listeners about removing blob
    348  */
    349 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
    350 				   const char *name)
    351 {
    352 	wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
    353 }
    354 
    355 
    356 /**
    357  * wpas_dbus_signal_network - Send a network related event signal
    358  * @wpa_s: %wpa_supplicant network interface data
    359  * @id: new network id
    360  * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
    361  * @properties: determines if add second argument with object properties
    362  *
    363  * Notify listeners about event related with configured network
    364  */
    365 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
    366 				     int id, const char *sig_name,
    367 				     int properties)
    368 {
    369 	struct wpas_dbus_priv *iface;
    370 	DBusMessage *msg;
    371 	DBusMessageIter iter;
    372 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
    373 
    374 	iface = wpa_s->global->dbus;
    375 
    376 	/* Do nothing if the control interface is not turned on */
    377 	if (iface == NULL || !wpa_s->dbus_new_path)
    378 		return;
    379 
    380 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
    381 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
    382 		    wpa_s->dbus_new_path, id);
    383 
    384 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    385 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    386 				      sig_name);
    387 	if (msg == NULL)
    388 		return;
    389 
    390 	dbus_message_iter_init_append(msg, &iter);
    391 	path = net_obj_path;
    392 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
    393 					    &path) ||
    394 	    (properties &&
    395 	     !wpa_dbus_get_object_properties(
    396 		     iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK,
    397 		     &iter)))
    398 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    399 	else
    400 		dbus_connection_send(iface->con, msg, NULL);
    401 	dbus_message_unref(msg);
    402 }
    403 
    404 
    405 /**
    406  * wpas_dbus_signal_network_added - Send a network added signal
    407  * @wpa_s: %wpa_supplicant network interface data
    408  * @id: new network id
    409  *
    410  * Notify listeners about adding new network
    411  */
    412 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
    413 					   int id)
    414 {
    415 	wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
    416 }
    417 
    418 
    419 /**
    420  * wpas_dbus_signal_network_removed - Send a network removed signal
    421  * @wpa_s: %wpa_supplicant network interface data
    422  * @id: network id
    423  *
    424  * Notify listeners about removing a network
    425  */
    426 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
    427 					     int id)
    428 {
    429 	wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
    430 }
    431 
    432 
    433 /**
    434  * wpas_dbus_signal_network_selected - Send a network selected signal
    435  * @wpa_s: %wpa_supplicant network interface data
    436  * @id: network id
    437  *
    438  * Notify listeners about selecting a network
    439  */
    440 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
    441 {
    442 	wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
    443 }
    444 
    445 
    446 /**
    447  * wpas_dbus_signal_network_request - Indicate that additional information
    448  * (EAP password, etc.) is required to complete the association to this SSID
    449  * @wpa_s: %wpa_supplicant network interface data
    450  * @rtype: The specific additional information required
    451  * @default_text: Optional description of required information
    452  *
    453  * Request additional information or passwords to complete an association
    454  * request.
    455  */
    456 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
    457 				      struct wpa_ssid *ssid,
    458 				      enum wpa_ctrl_req_type rtype,
    459 				      const char *default_txt)
    460 {
    461 	struct wpas_dbus_priv *iface;
    462 	DBusMessage *msg;
    463 	DBusMessageIter iter;
    464 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
    465 	const char *field, *txt = NULL, *net_ptr;
    466 
    467 	iface = wpa_s->global->dbus;
    468 
    469 	/* Do nothing if the control interface is not turned on */
    470 	if (iface == NULL || !wpa_s->dbus_new_path)
    471 		return;
    472 
    473 	field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt);
    474 	if (field == NULL)
    475 		return;
    476 
    477 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    478 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    479 				      "NetworkRequest");
    480 	if (msg == NULL)
    481 		return;
    482 
    483 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
    484 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
    485 		    wpa_s->dbus_new_path, ssid->id);
    486 	net_ptr = &net_obj_path[0];
    487 
    488 	dbus_message_iter_init_append(msg, &iter);
    489 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
    490 					    &net_ptr) ||
    491 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field) ||
    492 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt))
    493 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    494 	else
    495 		dbus_connection_send(iface->con, msg, NULL);
    496 	dbus_message_unref(msg);
    497 }
    498 
    499 
    500 /**
    501  * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
    502  * @wpa_s: %wpa_supplicant network interface data
    503  * @ssid: configured network which Enabled property has changed
    504  *
    505  * Sends PropertyChanged signals containing new value of Enabled property
    506  * for specified network
    507  */
    508 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
    509 					      struct wpa_ssid *ssid)
    510 {
    511 
    512 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
    513 
    514 	if (!wpa_s->dbus_new_path)
    515 		return;
    516 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
    517 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
    518 		    wpa_s->dbus_new_path, ssid->id);
    519 
    520 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
    521 				       WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
    522 }
    523 
    524 
    525 #ifdef CONFIG_WPS
    526 
    527 /**
    528  * wpas_dbus_signal_wps_event_pbc_overlap - Signals PBC overlap WPS event
    529  * @wpa_s: %wpa_supplicant network interface data
    530  *
    531  * Sends Event dbus signal with name "pbc-overlap" and empty dict as arguments
    532  */
    533 void wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
    534 {
    535 
    536 	DBusMessage *msg;
    537 	DBusMessageIter iter, dict_iter;
    538 	struct wpas_dbus_priv *iface;
    539 	char *key = "pbc-overlap";
    540 
    541 	iface = wpa_s->global->dbus;
    542 
    543 	/* Do nothing if the control interface is not turned on */
    544 	if (iface == NULL || !wpa_s->dbus_new_path)
    545 		return;
    546 
    547 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    548 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
    549 	if (msg == NULL)
    550 		return;
    551 
    552 	dbus_message_iter_init_append(msg, &iter);
    553 
    554 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
    555 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    556 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    557 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    558 	else
    559 		dbus_connection_send(iface->con, msg, NULL);
    560 
    561 	dbus_message_unref(msg);
    562 }
    563 
    564 
    565 /**
    566  * wpas_dbus_signal_wps_event_success - Signals Success WPS event
    567  * @wpa_s: %wpa_supplicant network interface data
    568  *
    569  * Sends Event dbus signal with name "success" and empty dict as arguments
    570  */
    571 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
    572 {
    573 
    574 	DBusMessage *msg;
    575 	DBusMessageIter iter, dict_iter;
    576 	struct wpas_dbus_priv *iface;
    577 	char *key = "success";
    578 
    579 	iface = wpa_s->global->dbus;
    580 
    581 	/* Do nothing if the control interface is not turned on */
    582 	if (iface == NULL || !wpa_s->dbus_new_path)
    583 		return;
    584 
    585 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    586 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
    587 	if (msg == NULL)
    588 		return;
    589 
    590 	dbus_message_iter_init_append(msg, &iter);
    591 
    592 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
    593 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    594 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    595 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    596 	else
    597 		dbus_connection_send(iface->con, msg, NULL);
    598 
    599 	dbus_message_unref(msg);
    600 }
    601 
    602 
    603 /**
    604  * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
    605  * @wpa_s: %wpa_supplicant network interface data
    606  * @fail: WPS failure information
    607  *
    608  * Sends Event dbus signal with name "fail" and dictionary containing
    609  * "msg field with fail message number (int32) as arguments
    610  */
    611 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
    612 				     struct wps_event_fail *fail)
    613 {
    614 
    615 	DBusMessage *msg;
    616 	DBusMessageIter iter, dict_iter;
    617 	struct wpas_dbus_priv *iface;
    618 	char *key = "fail";
    619 
    620 	iface = wpa_s->global->dbus;
    621 
    622 	/* Do nothing if the control interface is not turned on */
    623 	if (iface == NULL || !wpa_s->dbus_new_path)
    624 		return;
    625 
    626 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    627 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
    628 	if (msg == NULL)
    629 		return;
    630 
    631 	dbus_message_iter_init_append(msg, &iter);
    632 
    633 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
    634 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    635 	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
    636 	    !wpa_dbus_dict_append_int32(&dict_iter, "config_error",
    637 					fail->config_error) ||
    638 	    !wpa_dbus_dict_append_int32(&dict_iter, "error_indication",
    639 					fail->error_indication) ||
    640 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    641 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    642 	else
    643 		dbus_connection_send(iface->con, msg, NULL);
    644 
    645 	dbus_message_unref(msg);
    646 }
    647 
    648 
    649 /**
    650  * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
    651  * @wpa_s: %wpa_supplicant network interface data
    652  * @m2d: M2D event data information
    653  *
    654  * Sends Event dbus signal with name "m2d" and dictionary containing
    655  * fields of wps_event_m2d structure.
    656  */
    657 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
    658 				    struct wps_event_m2d *m2d)
    659 {
    660 
    661 	DBusMessage *msg;
    662 	DBusMessageIter iter, dict_iter;
    663 	struct wpas_dbus_priv *iface;
    664 	char *key = "m2d";
    665 
    666 	iface = wpa_s->global->dbus;
    667 
    668 	/* Do nothing if the control interface is not turned on */
    669 	if (iface == NULL || !wpa_s->dbus_new_path)
    670 		return;
    671 
    672 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    673 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
    674 	if (msg == NULL)
    675 		return;
    676 
    677 	dbus_message_iter_init_append(msg, &iter);
    678 
    679 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
    680 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    681 	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
    682 					 m2d->config_methods) ||
    683 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
    684 					     (const char *) m2d->manufacturer,
    685 					     m2d->manufacturer_len) ||
    686 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
    687 					     (const char *) m2d->model_name,
    688 					     m2d->model_name_len) ||
    689 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
    690 					     (const char *) m2d->model_number,
    691 					     m2d->model_number_len) ||
    692 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
    693 					     (const char *)
    694 					     m2d->serial_number,
    695 					     m2d->serial_number_len) ||
    696 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
    697 					     (const char *) m2d->dev_name,
    698 					     m2d->dev_name_len) ||
    699 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
    700 					     (const char *)
    701 					     m2d->primary_dev_type, 8) ||
    702 	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
    703 					 m2d->config_error) ||
    704 	    !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
    705 					 m2d->dev_password_id) ||
    706 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    707 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    708 	else
    709 		dbus_connection_send(iface->con, msg, NULL);
    710 
    711 	dbus_message_unref(msg);
    712 }
    713 
    714 
    715 /**
    716  * wpas_dbus_signal_wps_cred - Signals new credentials
    717  * @wpa_s: %wpa_supplicant network interface data
    718  * @cred: WPS Credential information
    719  *
    720  * Sends signal with credentials in directory argument
    721  */
    722 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
    723 			       const struct wps_credential *cred)
    724 {
    725 	DBusMessage *msg;
    726 	DBusMessageIter iter, dict_iter;
    727 	struct wpas_dbus_priv *iface;
    728 	char *auth_type[5]; /* we have five possible authentication types */
    729 	int at_num = 0;
    730 	char *encr_type[3]; /* we have three possible encryption types */
    731 	int et_num = 0;
    732 
    733 	iface = wpa_s->global->dbus;
    734 
    735 	/* Do nothing if the control interface is not turned on */
    736 	if (iface == NULL || !wpa_s->dbus_new_path)
    737 		return;
    738 
    739 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    740 				      WPAS_DBUS_NEW_IFACE_WPS,
    741 				      "Credentials");
    742 	if (msg == NULL)
    743 		return;
    744 
    745 	dbus_message_iter_init_append(msg, &iter);
    746 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
    747 		goto nomem;
    748 
    749 	if (cred->auth_type & WPS_AUTH_OPEN)
    750 		auth_type[at_num++] = "open";
    751 	if (cred->auth_type & WPS_AUTH_WPAPSK)
    752 		auth_type[at_num++] = "wpa-psk";
    753 	if (cred->auth_type & WPS_AUTH_WPA)
    754 		auth_type[at_num++] = "wpa-eap";
    755 	if (cred->auth_type & WPS_AUTH_WPA2)
    756 		auth_type[at_num++] = "wpa2-eap";
    757 	if (cred->auth_type & WPS_AUTH_WPA2PSK)
    758 		auth_type[at_num++] = "wpa2-psk";
    759 
    760 	if (cred->encr_type & WPS_ENCR_NONE)
    761 		encr_type[et_num++] = "none";
    762 	if (cred->encr_type & WPS_ENCR_TKIP)
    763 		encr_type[et_num++] = "tkip";
    764 	if (cred->encr_type & WPS_ENCR_AES)
    765 		encr_type[et_num++] = "aes";
    766 
    767 	if ((wpa_s->current_ssid &&
    768 	     !wpa_dbus_dict_append_byte_array(
    769 		     &dict_iter, "BSSID",
    770 		     (const char *) wpa_s->current_ssid->bssid, ETH_ALEN)) ||
    771 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
    772 					     (const char *) cred->ssid,
    773 					     cred->ssid_len) ||
    774 	    !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
    775 					       (const char **) auth_type,
    776 					       at_num) ||
    777 	    !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
    778 					       (const char **) encr_type,
    779 					       et_num) ||
    780 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
    781 					     (const char *) cred->key,
    782 					     cred->key_len) ||
    783 	    !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
    784 					 cred->key_idx) ||
    785 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    786 		goto nomem;
    787 
    788 	dbus_connection_send(iface->con, msg, NULL);
    789 
    790 nomem:
    791 	dbus_message_unref(msg);
    792 }
    793 
    794 #endif /* CONFIG_WPS */
    795 
    796 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
    797 				    int depth, const char *subject,
    798 				    const char *altsubject[],
    799 				    int num_altsubject,
    800 				    const char *cert_hash,
    801 				    const struct wpabuf *cert)
    802 {
    803 	struct wpas_dbus_priv *iface;
    804 	DBusMessage *msg;
    805 	DBusMessageIter iter, dict_iter;
    806 
    807 	iface = wpa_s->global->dbus;
    808 
    809 	/* Do nothing if the control interface is not turned on */
    810 	if (iface == NULL || !wpa_s->dbus_new_path)
    811 		return;
    812 
    813 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    814 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    815 				      "Certification");
    816 	if (msg == NULL)
    817 		return;
    818 
    819 	dbus_message_iter_init_append(msg, &iter);
    820 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    821 	    !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
    822 	    !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) ||
    823 	    (altsubject && num_altsubject &&
    824 	     !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject",
    825 						altsubject, num_altsubject)) ||
    826 	    (cert_hash &&
    827 	     !wpa_dbus_dict_append_string(&dict_iter, "cert_hash",
    828 					  cert_hash)) ||
    829 	    (cert &&
    830 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
    831 					      wpabuf_head(cert),
    832 					      wpabuf_len(cert))) ||
    833 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    834 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    835 	else
    836 		dbus_connection_send(iface->con, msg, NULL);
    837 	dbus_message_unref(msg);
    838 }
    839 
    840 
    841 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
    842 				 const char *status, const char *parameter)
    843 {
    844 	struct wpas_dbus_priv *iface;
    845 	DBusMessage *msg;
    846 	DBusMessageIter iter;
    847 
    848 	iface = wpa_s->global->dbus;
    849 
    850 	/* Do nothing if the control interface is not turned on */
    851 	if (iface == NULL || !wpa_s->dbus_new_path)
    852 		return;
    853 
    854 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    855 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    856 				      "EAP");
    857 	if (msg == NULL)
    858 		return;
    859 
    860 	dbus_message_iter_init_append(msg, &iter);
    861 
    862 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) ||
    863 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
    864 					    &parameter))
    865 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    866 	else
    867 		dbus_connection_send(iface->con, msg, NULL);
    868 	dbus_message_unref(msg);
    869 }
    870 
    871 
    872 /**
    873  * wpas_dbus_signal_sta - Send a station related event signal
    874  * @wpa_s: %wpa_supplicant network interface data
    875  * @sta: station mac address
    876  * @sig_name: signal name - StaAuthorized or StaDeauthorized
    877  *
    878  * Notify listeners about event related with station
    879  */
    880 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s,
    881 				 const u8 *sta, const char *sig_name)
    882 {
    883 	struct wpas_dbus_priv *iface;
    884 	DBusMessage *msg;
    885 	char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX];
    886 	char *dev_mac;
    887 
    888 	os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta));
    889 	dev_mac = sta_mac;
    890 
    891 	iface = wpa_s->global->dbus;
    892 
    893 	/* Do nothing if the control interface is not turned on */
    894 	if (iface == NULL || !wpa_s->dbus_new_path)
    895 		return;
    896 
    897 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    898 				      WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
    899 	if (msg == NULL)
    900 		return;
    901 
    902 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac,
    903 				     DBUS_TYPE_INVALID))
    904 		dbus_connection_send(iface->con, msg, NULL);
    905 	else
    906 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    907 	dbus_message_unref(msg);
    908 
    909 	wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'",
    910 		   sta_mac, sig_name);
    911 }
    912 
    913 
    914 /**
    915  * wpas_dbus_signal_sta_authorized - Send a STA authorized signal
    916  * @wpa_s: %wpa_supplicant network interface data
    917  * @sta: station mac address
    918  *
    919  * Notify listeners a new station has been authorized
    920  */
    921 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
    922 				     const u8 *sta)
    923 {
    924 	wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized");
    925 }
    926 
    927 
    928 /**
    929  * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal
    930  * @wpa_s: %wpa_supplicant network interface data
    931  * @sta: station mac address
    932  *
    933  * Notify listeners a station has been deauthorized
    934  */
    935 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
    936 				       const u8 *sta)
    937 {
    938 	wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized");
    939 }
    940 
    941 
    942 #ifdef CONFIG_P2P
    943 
    944 /**
    945  * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
    946  * @wpa_s: %wpa_supplicant network interface data
    947  * @role: role of this device (client or GO)
    948  * Sends signal with i/f name and role as string arguments
    949  */
    950 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
    951 					const char *role)
    952 {
    953 	DBusMessage *msg;
    954 	DBusMessageIter iter, dict_iter;
    955 	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
    956 	struct wpa_supplicant *parent;
    957 
    958 	/* Do nothing if the control interface is not turned on */
    959 	if (iface == NULL)
    960 		return;
    961 
    962 	parent = wpa_s->parent;
    963 	if (parent->p2p_mgmt)
    964 		parent = parent->parent;
    965 
    966 	if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path ||
    967 	    !parent->dbus_new_path)
    968 		return;
    969 
    970 	msg = dbus_message_new_signal(parent->dbus_new_path,
    971 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
    972 				      "GroupFinished");
    973 	if (msg == NULL)
    974 		return;
    975 
    976 	dbus_message_iter_init_append(msg, &iter);
    977 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    978 	    !wpa_dbus_dict_append_object_path(&dict_iter,
    979 					      "interface_object",
    980 					      wpa_s->dbus_new_path) ||
    981 	    !wpa_dbus_dict_append_string(&dict_iter, "role", role) ||
    982 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
    983 					      wpa_s->dbus_groupobj_path) ||
    984 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    985 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    986 	else
    987 		dbus_connection_send(iface->con, msg, NULL);
    988 	dbus_message_unref(msg);
    989 }
    990 
    991 
    992 /**
    993  * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
    994  *
    995  * @dev_addr - who sent the request or responded to our request.
    996  * @request - Will be 1 if request, 0 for response.
    997  * @status - valid only in case of response
    998  * @config_methods - wps config methods
    999  * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
   1000  *
   1001  * Sends following provision discovery related events:
   1002  *	ProvisionDiscoveryRequestDisplayPin
   1003  *	ProvisionDiscoveryResponseDisplayPin
   1004  *	ProvisionDiscoveryRequestEnterPin
   1005  *	ProvisionDiscoveryResponseEnterPin
   1006  *	ProvisionDiscoveryPBCRequest
   1007  *	ProvisionDiscoveryPBCResponse
   1008  *
   1009  *	TODO::
   1010  *	ProvisionDiscoveryFailure (timeout case)
   1011  */
   1012 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
   1013 					      const u8 *dev_addr, int request,
   1014 					      enum p2p_prov_disc_status status,
   1015 					      u16 config_methods,
   1016 					      unsigned int generated_pin)
   1017 {
   1018 	DBusMessage *msg;
   1019 	DBusMessageIter iter;
   1020 	struct wpas_dbus_priv *iface;
   1021 	char *_signal;
   1022 	int add_pin = 0;
   1023 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1024 	int error_ret = 1;
   1025 	char pin[9], *p_pin = NULL;
   1026 
   1027 	iface = wpa_s->global->dbus;
   1028 
   1029 	/* Do nothing if the control interface is not turned on */
   1030 	if (iface == NULL)
   1031 		return;
   1032 
   1033 	if (wpa_s->p2p_mgmt)
   1034 		wpa_s = wpa_s->parent;
   1035 	if (!wpa_s->dbus_new_path)
   1036 		return;
   1037 
   1038 	if (request || !status) {
   1039 		if (config_methods & WPS_CONFIG_DISPLAY)
   1040 			_signal = request ?
   1041 				 "ProvisionDiscoveryRequestDisplayPin" :
   1042 				 "ProvisionDiscoveryResponseEnterPin";
   1043 		else if (config_methods & WPS_CONFIG_KEYPAD)
   1044 			_signal = request ?
   1045 				 "ProvisionDiscoveryRequestEnterPin" :
   1046 				 "ProvisionDiscoveryResponseDisplayPin";
   1047 		else if (config_methods & WPS_CONFIG_PUSHBUTTON)
   1048 			_signal = request ? "ProvisionDiscoveryPBCRequest" :
   1049 				   "ProvisionDiscoveryPBCResponse";
   1050 		else
   1051 			return; /* Unknown or un-supported method */
   1052 	} else {
   1053 		/* Explicit check for failure response */
   1054 		_signal = "ProvisionDiscoveryFailure";
   1055 	}
   1056 
   1057 	add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
   1058 		   (!request && !status &&
   1059 			(config_methods & WPS_CONFIG_KEYPAD)));
   1060 
   1061 	if (add_pin) {
   1062 		os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
   1063 		p_pin = pin;
   1064 	}
   1065 
   1066 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1067 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
   1068 	if (msg == NULL)
   1069 		return;
   1070 
   1071 	/* Check if this is a known peer */
   1072 	if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
   1073 		goto error;
   1074 
   1075 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1076 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1077 			COMPACT_MACSTR,
   1078 			wpa_s->dbus_new_path, MAC2STR(dev_addr));
   1079 
   1080 	path = peer_obj_path;
   1081 
   1082 	dbus_message_iter_init_append(msg, &iter);
   1083 
   1084 	if (!dbus_message_iter_append_basic(&iter,
   1085 					    DBUS_TYPE_OBJECT_PATH,
   1086 					    &path))
   1087 			goto error;
   1088 
   1089 	if (!request && status)
   1090 		/* Attach status to ProvisionDiscoveryFailure */
   1091 		error_ret = !dbus_message_iter_append_basic(&iter,
   1092 						    DBUS_TYPE_INT32,
   1093 						    &status);
   1094 	else
   1095 		error_ret = (add_pin &&
   1096 				 !dbus_message_iter_append_basic(&iter,
   1097 							DBUS_TYPE_STRING,
   1098 							&p_pin));
   1099 
   1100 error:
   1101 	if (!error_ret)
   1102 		dbus_connection_send(iface->con, msg, NULL);
   1103 	else
   1104 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1105 
   1106 	dbus_message_unref(msg);
   1107 }
   1108 
   1109 
   1110 /**
   1111  * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX
   1112  * @wpa_s: %wpa_supplicant network interface data
   1113  * @src: Source address of the message triggering this notification
   1114  * @dev_passwd_id: WPS Device Password Id
   1115  * @go_intent: Peer's GO Intent value
   1116  *
   1117  * Sends signal to notify that a peer P2P Device is requesting group owner
   1118  * negotiation with us.
   1119  */
   1120 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
   1121 				     const u8 *src, u16 dev_passwd_id,
   1122 				     u8 go_intent)
   1123 {
   1124 	DBusMessage *msg;
   1125 	DBusMessageIter iter;
   1126 	struct wpas_dbus_priv *iface;
   1127 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1128 
   1129 	iface = wpa_s->global->dbus;
   1130 
   1131 	/* Do nothing if the control interface is not turned on */
   1132 	if (iface == NULL)
   1133 		return;
   1134 
   1135 	if (wpa_s->p2p_mgmt)
   1136 		wpa_s = wpa_s->parent;
   1137 	if (!wpa_s->dbus_new_path)
   1138 		return;
   1139 
   1140 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1141 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   1142 		    wpa_s->dbus_new_path, MAC2STR(src));
   1143 	path = peer_obj_path;
   1144 
   1145 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1146 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1147 				      "GONegotiationRequest");
   1148 	if (msg == NULL)
   1149 		return;
   1150 
   1151 	dbus_message_iter_init_append(msg, &iter);
   1152 
   1153 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   1154 					    &path) ||
   1155 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
   1156 					    &dev_passwd_id) ||
   1157 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
   1158 					    &go_intent))
   1159 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1160 	else
   1161 		dbus_connection_send(iface->con, msg, NULL);
   1162 
   1163 	dbus_message_unref(msg);
   1164 }
   1165 
   1166 
   1167 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
   1168 					const struct wpa_ssid *ssid,
   1169 					char *group_obj_path)
   1170 {
   1171 	char group_name[3];
   1172 
   1173 	if (!wpa_s->dbus_new_path ||
   1174 	    os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
   1175 		return -1;
   1176 
   1177 	os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
   1178 	group_name[2] = '\0';
   1179 
   1180 	os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1181 		    "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
   1182 		    wpa_s->dbus_new_path, group_name);
   1183 
   1184 	return 0;
   1185 }
   1186 
   1187 
   1188 struct group_changed_data {
   1189 	struct wpa_supplicant *wpa_s;
   1190 	struct p2p_peer_info *info;
   1191 };
   1192 
   1193 
   1194 static int match_group_where_peer_is_client(struct p2p_group *group,
   1195 					    void *user_data)
   1196 {
   1197 	struct group_changed_data *data = user_data;
   1198 	const struct p2p_group_config *cfg;
   1199 	struct wpa_supplicant *wpa_s_go;
   1200 
   1201 	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
   1202 		return 1;
   1203 
   1204 	cfg = p2p_group_get_config(group);
   1205 
   1206 	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
   1207 					 cfg->ssid_len);
   1208 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
   1209 		wpas_dbus_signal_peer_groups_changed(
   1210 			data->wpa_s->p2pdev, data->info->p2p_device_addr);
   1211 		return 0;
   1212 	}
   1213 
   1214 	return 1;
   1215 }
   1216 
   1217 
   1218 static void signal_peer_groups_changed(struct p2p_peer_info *info,
   1219 				       void *user_data)
   1220 {
   1221 	struct group_changed_data *data = user_data;
   1222 	struct wpa_supplicant *wpa_s_go;
   1223 
   1224 	wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
   1225 					     info->p2p_device_addr);
   1226 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
   1227 		wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
   1228 						     info->p2p_device_addr);
   1229 		return;
   1230 	}
   1231 
   1232 	data->info = info;
   1233 	p2p_loop_on_all_groups(data->wpa_s->global->p2p,
   1234 			       match_group_where_peer_is_client, data);
   1235 	data->info = NULL;
   1236 }
   1237 
   1238 
   1239 static void peer_groups_changed(struct wpa_supplicant *wpa_s)
   1240 {
   1241 	struct group_changed_data data;
   1242 
   1243 	os_memset(&data, 0, sizeof(data));
   1244 	data.wpa_s = wpa_s;
   1245 
   1246 	p2p_loop_on_known_peers(wpa_s->global->p2p,
   1247 				signal_peer_groups_changed, &data);
   1248 }
   1249 
   1250 
   1251 /**
   1252  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
   1253  * started. Emitted when a group is successfully started
   1254  * irrespective of the role (client/GO) of the current device
   1255  *
   1256  * @wpa_s: %wpa_supplicant network interface data
   1257  * @client: this device is P2P client
   1258  * @persistent: 0 - non persistent group, 1 - persistent group
   1259  * @ip: When group role is client, it contains local IP address, netmask, and
   1260  *	GO's IP address, if assigned; otherwise, NULL
   1261  */
   1262 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
   1263 					int client, int persistent,
   1264 					const u8 *ip)
   1265 {
   1266 	DBusMessage *msg;
   1267 	DBusMessageIter iter, dict_iter;
   1268 	struct wpas_dbus_priv *iface;
   1269 	struct wpa_supplicant *parent;
   1270 
   1271 	parent = wpa_s->parent;
   1272 	if (parent->p2p_mgmt)
   1273 		parent = parent->parent;
   1274 
   1275 	iface = parent->global->dbus;
   1276 
   1277 	/* Do nothing if the control interface is not turned on */
   1278 	if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path)
   1279 		return;
   1280 
   1281 	if (wpa_s->dbus_groupobj_path == NULL)
   1282 		return;
   1283 
   1284 	/* New interface has been created for this group */
   1285 	msg = dbus_message_new_signal(parent->dbus_new_path,
   1286 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1287 				      "GroupStarted");
   1288 	if (msg == NULL)
   1289 		return;
   1290 
   1291 	dbus_message_iter_init_append(msg, &iter);
   1292 	/*
   1293 	 * In case the device supports creating a separate interface the
   1294 	 * DBus client will need to know the object path for the interface
   1295 	 * object this group was created on, so include it here.
   1296 	 */
   1297 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1298 	    !wpa_dbus_dict_append_object_path(&dict_iter,
   1299 					      "interface_object",
   1300 					      wpa_s->dbus_new_path) ||
   1301 	    !wpa_dbus_dict_append_string(&dict_iter, "role",
   1302 					 client ? "client" : "GO") ||
   1303 	    !wpa_dbus_dict_append_bool(&dict_iter, "persistent", persistent) ||
   1304 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
   1305 					      wpa_s->dbus_groupobj_path) ||
   1306 	    (ip &&
   1307 	     (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr",
   1308 					       (char *) ip, 4) ||
   1309 	      !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
   1310 					       (char *) ip + 4, 4) ||
   1311 	      !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
   1312 					       (char *) ip + 8, 4))) ||
   1313 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
   1314 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1315 	} else {
   1316 		dbus_connection_send(iface->con, msg, NULL);
   1317 		if (client)
   1318 			peer_groups_changed(wpa_s);
   1319 	}
   1320 	dbus_message_unref(msg);
   1321 }
   1322 
   1323 
   1324 /**
   1325  * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal
   1326  * @wpa_s: %wpa_supplicant network interface data
   1327  * @res: Result of the GO Neg Request
   1328  */
   1329 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
   1330 				      struct p2p_go_neg_results *res)
   1331 {
   1332 	DBusMessage *msg;
   1333 	DBusMessageIter iter, dict_iter;
   1334 	DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
   1335 	struct wpas_dbus_priv *iface;
   1336 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1337 	dbus_int32_t freqs[P2P_MAX_CHANNELS];
   1338 	dbus_int32_t *f_array = freqs;
   1339 
   1340 
   1341 	iface = wpa_s->global->dbus;
   1342 
   1343 	if (wpa_s->p2p_mgmt)
   1344 		wpa_s = wpa_s->parent;
   1345 
   1346 	os_memset(freqs, 0, sizeof(freqs));
   1347 	/* Do nothing if the control interface is not turned on */
   1348 	if (iface == NULL || !wpa_s->dbus_new_path)
   1349 		return;
   1350 
   1351 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1352 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   1353 		    wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
   1354 	path = peer_obj_path;
   1355 
   1356 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1357 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1358 				      res->status ? "GONegotiationFailure" :
   1359 						    "GONegotiationSuccess");
   1360 	if (msg == NULL)
   1361 		return;
   1362 
   1363 	dbus_message_iter_init_append(msg, &iter);
   1364 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1365 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
   1366 					      path) ||
   1367 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
   1368 		goto err;
   1369 
   1370 	if (!res->status) {
   1371 		int i = 0;
   1372 		int freq_list_num = 0;
   1373 
   1374 		if ((res->role_go &&
   1375 		     !wpa_dbus_dict_append_string(&dict_iter, "passphrase",
   1376 						  res->passphrase)) ||
   1377 		    !wpa_dbus_dict_append_string(&dict_iter, "role_go",
   1378 						 res->role_go ? "GO" :
   1379 						 "client") ||
   1380 		    !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
   1381 						res->freq) ||
   1382 		    !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
   1383 						     (const char *) res->ssid,
   1384 						     res->ssid_len) ||
   1385 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
   1386 						     "peer_device_addr",
   1387 						     (const char *)
   1388 						     res->peer_device_addr,
   1389 						     ETH_ALEN) ||
   1390 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
   1391 						     "peer_interface_addr",
   1392 						     (const char *)
   1393 						     res->peer_interface_addr,
   1394 						     ETH_ALEN) ||
   1395 		    !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
   1396 						 p2p_wps_method_text(
   1397 							 res->wps_method)))
   1398 			goto err;
   1399 
   1400 		for (i = 0; i < P2P_MAX_CHANNELS; i++) {
   1401 			if (res->freq_list[i]) {
   1402 				freqs[i] = res->freq_list[i];
   1403 				freq_list_num++;
   1404 			}
   1405 		}
   1406 
   1407 		if (!wpa_dbus_dict_begin_array(&dict_iter,
   1408 					       "frequency_list",
   1409 					       DBUS_TYPE_INT32_AS_STRING,
   1410 					       &iter_dict_entry,
   1411 					       &iter_dict_val,
   1412 					       &iter_dict_array) ||
   1413 		    !dbus_message_iter_append_fixed_array(&iter_dict_array,
   1414 							  DBUS_TYPE_INT32,
   1415 							  &f_array,
   1416 							  freq_list_num) ||
   1417 		    !wpa_dbus_dict_end_array(&dict_iter,
   1418 					     &iter_dict_entry,
   1419 					     &iter_dict_val,
   1420 					     &iter_dict_array) ||
   1421 		    !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
   1422 						res->persistent_group) ||
   1423 		    !wpa_dbus_dict_append_uint32(&dict_iter,
   1424 						 "peer_config_timeout",
   1425 						 res->peer_config_timeout))
   1426 			goto err;
   1427 	}
   1428 
   1429 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
   1430 		goto err;
   1431 
   1432 	dbus_connection_send(iface->con, msg, NULL);
   1433 err:
   1434 	dbus_message_unref(msg);
   1435 }
   1436 
   1437 
   1438 /**
   1439  * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
   1440  * @wpa_s: %wpa_supplicant network interface data
   1441  * @status: Status of invitation process
   1442  * @bssid: Basic Service Set Identifier
   1443  */
   1444 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
   1445 					    int status, const u8 *bssid)
   1446 {
   1447 	DBusMessage *msg;
   1448 	DBusMessageIter iter, dict_iter;
   1449 	struct wpas_dbus_priv *iface;
   1450 
   1451 	wpa_printf(MSG_DEBUG, "%s", __func__);
   1452 
   1453 	iface = wpa_s->global->dbus;
   1454 	/* Do nothing if the control interface is not turned on */
   1455 	if (iface == NULL)
   1456 		return;
   1457 
   1458 	if (wpa_s->p2p_mgmt)
   1459 		wpa_s = wpa_s->parent;
   1460 	if (!wpa_s->dbus_new_path)
   1461 		return;
   1462 
   1463 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1464 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1465 				      "InvitationResult");
   1466 
   1467 	if (msg == NULL)
   1468 		return;
   1469 
   1470 	dbus_message_iter_init_append(msg, &iter);
   1471 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1472 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", status) ||
   1473 	    (bssid &&
   1474 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
   1475 					      (const char *) bssid,
   1476 					      ETH_ALEN)) ||
   1477 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   1478 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1479 	else
   1480 		dbus_connection_send(iface->con, msg, NULL);
   1481 	dbus_message_unref(msg);
   1482 }
   1483 
   1484 
   1485 /**
   1486  *
   1487  * Method to emit a signal for a peer joining the group.
   1488  * The signal will carry path to the group member object
   1489  * constructed using p2p i/f addr used for connecting.
   1490  *
   1491  * @wpa_s: %wpa_supplicant network interface data
   1492  * @peer_addr: P2P Device Address of the peer joining the group
   1493  */
   1494 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
   1495 				      const u8 *peer_addr)
   1496 {
   1497 	struct wpas_dbus_priv *iface;
   1498 	DBusMessage *msg;
   1499 	DBusMessageIter iter;
   1500 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1501 	struct wpa_supplicant *parent;
   1502 
   1503 	iface = wpa_s->global->dbus;
   1504 
   1505 	/* Do nothing if the control interface is not turned on */
   1506 	if (iface == NULL)
   1507 		return;
   1508 
   1509 	if (!wpa_s->dbus_groupobj_path)
   1510 		return;
   1511 
   1512 	parent = wpa_s->parent;
   1513 	if (parent->p2p_mgmt)
   1514 		parent = parent->parent;
   1515 	if (!parent->dbus_new_path)
   1516 		return;
   1517 
   1518 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1519 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1520 			COMPACT_MACSTR,
   1521 			parent->dbus_new_path, MAC2STR(peer_addr));
   1522 
   1523 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
   1524 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
   1525 				      "PeerJoined");
   1526 	if (msg == NULL)
   1527 		return;
   1528 
   1529 	dbus_message_iter_init_append(msg, &iter);
   1530 	path = peer_obj_path;
   1531 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   1532 					    &path)) {
   1533 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1534 	} else {
   1535 		dbus_connection_send(iface->con, msg, NULL);
   1536 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
   1537 	}
   1538 	dbus_message_unref(msg);
   1539 }
   1540 
   1541 
   1542 /**
   1543  *
   1544  * Method to emit a signal for a peer disconnecting the group.
   1545  * The signal will carry path to the group member object
   1546  * constructed using the P2P Device Address of the peer.
   1547  *
   1548  * @wpa_s: %wpa_supplicant network interface data
   1549  * @peer_addr: P2P Device Address of the peer joining the group
   1550  */
   1551 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
   1552 					    const u8 *peer_addr)
   1553 {
   1554 	struct wpas_dbus_priv *iface;
   1555 	DBusMessage *msg;
   1556 	DBusMessageIter iter;
   1557 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1558 	struct wpa_supplicant *parent;
   1559 
   1560 	iface = wpa_s->global->dbus;
   1561 
   1562 	/* Do nothing if the control interface is not turned on */
   1563 	if (iface == NULL)
   1564 		return;
   1565 
   1566 	if (!wpa_s->dbus_groupobj_path)
   1567 		return;
   1568 
   1569 	parent = wpa_s->parent;
   1570 	if (parent->p2p_mgmt)
   1571 		parent = parent->parent;
   1572 	if (!parent->dbus_new_path)
   1573 		return;
   1574 
   1575 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1576 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1577 			COMPACT_MACSTR,
   1578 			parent->dbus_new_path, MAC2STR(peer_addr));
   1579 
   1580 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
   1581 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
   1582 				      "PeerDisconnected");
   1583 	if (msg == NULL)
   1584 		return;
   1585 
   1586 	dbus_message_iter_init_append(msg, &iter);
   1587 	path = peer_obj_path;
   1588 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   1589 					    &path)) {
   1590 		wpa_printf(MSG_ERROR,
   1591 			   "dbus: Failed to construct PeerDisconnected signal");
   1592 	} else {
   1593 		dbus_connection_send(iface->con, msg, NULL);
   1594 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
   1595 	}
   1596 	dbus_message_unref(msg);
   1597 }
   1598 
   1599 
   1600 /**
   1601  *
   1602  * Method to emit a signal for a service discovery request.
   1603  * The signal will carry station address, frequency, dialog token,
   1604  * update indicator and it tlvs
   1605  *
   1606  * @wpa_s: %wpa_supplicant network interface data
   1607  * @sa: station addr (p2p i/f) of the peer
   1608  * @dialog_token: service discovery request dialog token
   1609  * @update_indic: service discovery request update indicator
   1610  * @tlvs: service discovery request genrated byte array of tlvs
   1611  * @tlvs_len: service discovery request tlvs length
   1612  */
   1613 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
   1614 				     int freq, const u8 *sa, u8 dialog_token,
   1615 				     u16 update_indic, const u8 *tlvs,
   1616 				     size_t tlvs_len)
   1617 {
   1618 	DBusMessage *msg;
   1619 	DBusMessageIter iter, dict_iter;
   1620 	struct wpas_dbus_priv *iface;
   1621 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1622 
   1623 	iface = wpa_s->global->dbus;
   1624 
   1625 	/* Do nothing if the control interface is not turned on */
   1626 	if (iface == NULL)
   1627 		return;
   1628 
   1629 	if (wpa_s->p2p_mgmt)
   1630 		wpa_s = wpa_s->parent;
   1631 	if (!wpa_s->dbus_new_path)
   1632 		return;
   1633 
   1634 	/* Check if this is a known peer */
   1635 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
   1636 		return;
   1637 
   1638 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1639 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1640 				      "ServiceDiscoveryRequest");
   1641 	if (msg == NULL)
   1642 		return;
   1643 
   1644 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1645 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1646 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
   1647 
   1648 	path = peer_obj_path;
   1649 
   1650 	dbus_message_iter_init_append(msg, &iter);
   1651 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1652 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
   1653 					      path) ||
   1654 	    !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
   1655 	    !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
   1656 					dialog_token) ||
   1657 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
   1658 					 update_indic) ||
   1659 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
   1660 					     (const char *) tlvs,
   1661 					     tlvs_len) ||
   1662 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   1663 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1664 	else
   1665 		dbus_connection_send(iface->con, msg, NULL);
   1666 	dbus_message_unref(msg);
   1667 }
   1668 
   1669 
   1670 /**
   1671  *
   1672  * Method to emit a signal for a service discovery response.
   1673  * The signal will carry station address, update indicator and it
   1674  * tlvs
   1675  *
   1676  * @wpa_s: %wpa_supplicant network interface data
   1677  * @sa: station addr (p2p i/f) of the peer
   1678  * @update_indic: service discovery request update indicator
   1679  * @tlvs: service discovery request genrated byte array of tlvs
   1680  * @tlvs_len: service discovery request tlvs length
   1681  */
   1682 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
   1683 				      const u8 *sa, u16 update_indic,
   1684 				      const u8 *tlvs, size_t tlvs_len)
   1685 {
   1686 	DBusMessage *msg;
   1687 	DBusMessageIter iter, dict_iter;
   1688 	struct wpas_dbus_priv *iface;
   1689 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1690 
   1691 	iface = wpa_s->global->dbus;
   1692 
   1693 	/* Do nothing if the control interface is not turned on */
   1694 	if (iface == NULL)
   1695 		return;
   1696 
   1697 	if (wpa_s->p2p_mgmt)
   1698 		wpa_s = wpa_s->parent;
   1699 	if (!wpa_s->dbus_new_path)
   1700 		return;
   1701 
   1702 	/* Check if this is a known peer */
   1703 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
   1704 		return;
   1705 
   1706 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1707 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1708 				      "ServiceDiscoveryResponse");
   1709 	if (msg == NULL)
   1710 		return;
   1711 
   1712 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1713 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1714 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
   1715 
   1716 	path = peer_obj_path;
   1717 
   1718 	dbus_message_iter_init_append(msg, &iter);
   1719 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1720 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
   1721 					      path) ||
   1722 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
   1723 					 update_indic) ||
   1724 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
   1725 					     (const char *) tlvs,
   1726 					     tlvs_len) ||
   1727 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   1728 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1729 	else
   1730 		dbus_connection_send(iface->con, msg, NULL);
   1731 	dbus_message_unref(msg);
   1732 }
   1733 
   1734 
   1735 /**
   1736  * wpas_dbus_signal_persistent_group - Send a persistent group related
   1737  *	event signal
   1738  * @wpa_s: %wpa_supplicant network interface data
   1739  * @id: new persistent group id
   1740  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
   1741  * @properties: determines if add second argument with object properties
   1742  *
   1743  * Notify listeners about an event related to persistent groups.
   1744  */
   1745 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
   1746 					      int id, const char *sig_name,
   1747 					      int properties)
   1748 {
   1749 	struct wpas_dbus_priv *iface;
   1750 	DBusMessage *msg;
   1751 	DBusMessageIter iter;
   1752 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1753 
   1754 	iface = wpa_s->global->dbus;
   1755 
   1756 	/* Do nothing if the control interface is not turned on */
   1757 	if (iface == NULL)
   1758 		return;
   1759 
   1760 	if (wpa_s->p2p_mgmt)
   1761 		wpa_s = wpa_s->parent;
   1762 	if (!wpa_s->dbus_new_path)
   1763 		return;
   1764 
   1765 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1766 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
   1767 		    wpa_s->dbus_new_path, id);
   1768 
   1769 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1770 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1771 				      sig_name);
   1772 	if (msg == NULL)
   1773 		return;
   1774 
   1775 	dbus_message_iter_init_append(msg, &iter);
   1776 	path = pgrp_obj_path;
   1777 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   1778 					    &path) ||
   1779 	    (properties &&
   1780 	     !wpa_dbus_get_object_properties(
   1781 		     iface, pgrp_obj_path,
   1782 		     WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
   1783 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1784 	else
   1785 		dbus_connection_send(iface->con, msg, NULL);
   1786 
   1787 	dbus_message_unref(msg);
   1788 }
   1789 
   1790 
   1791 /**
   1792  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
   1793  *	added signal
   1794  * @wpa_s: %wpa_supplicant network interface data
   1795  * @id: new persistent group id
   1796  *
   1797  * Notify listeners about addition of a new persistent group.
   1798  */
   1799 static void wpas_dbus_signal_persistent_group_added(
   1800 	struct wpa_supplicant *wpa_s, int id)
   1801 {
   1802 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
   1803 					  TRUE);
   1804 }
   1805 
   1806 
   1807 /**
   1808  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
   1809  *	removed signal
   1810  * @wpa_s: %wpa_supplicant network interface data
   1811  * @id: persistent group id
   1812  *
   1813  * Notify listeners about removal of a persistent group.
   1814  */
   1815 static void wpas_dbus_signal_persistent_group_removed(
   1816 	struct wpa_supplicant *wpa_s, int id)
   1817 {
   1818 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
   1819 					  FALSE);
   1820 }
   1821 
   1822 
   1823 /**
   1824  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
   1825  * @wpa_s: %wpa_supplicant network interface data
   1826  * @fail: WPS failure information
   1827  *
   1828  * Sends Event dbus signal with name "fail" and dictionary containing
   1829  * "msg" field with fail message number (int32) as arguments
   1830  */
   1831 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
   1832 				     struct wps_event_fail *fail)
   1833 {
   1834 
   1835 	DBusMessage *msg;
   1836 	DBusMessageIter iter, dict_iter;
   1837 	struct wpas_dbus_priv *iface;
   1838 	char *key = "fail";
   1839 
   1840 	iface = wpa_s->global->dbus;
   1841 
   1842 	/* Do nothing if the control interface is not turned on */
   1843 	if (iface == NULL)
   1844 		return;
   1845 
   1846 	if (wpa_s->p2p_mgmt)
   1847 		wpa_s = wpa_s->parent;
   1848 
   1849 	if (!wpa_s->dbus_new_path)
   1850 		return;
   1851 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1852 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1853 				      "WpsFailed");
   1854 	if (msg == NULL)
   1855 		return;
   1856 
   1857 	dbus_message_iter_init_append(msg, &iter);
   1858 
   1859 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
   1860 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1861 	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
   1862 	    !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
   1863 					fail->config_error) ||
   1864 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   1865 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1866 	else
   1867 		dbus_connection_send(iface->con, msg, NULL);
   1868 
   1869 	dbus_message_unref(msg);
   1870 }
   1871 
   1872 
   1873 /**
   1874  * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event
   1875  * @wpa_s: %wpa_supplicant network interface data
   1876  * @reason: indicates the reason code for group formation failure
   1877  *
   1878  * Sends Event dbus signal and string reason code when available.
   1879  */
   1880 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
   1881 						  const char *reason)
   1882 {
   1883 	DBusMessage *msg;
   1884 	struct wpas_dbus_priv *iface;
   1885 
   1886 	iface = wpa_s->global->dbus;
   1887 
   1888 	/* Do nothing if the control interface is not turned on */
   1889 	if (iface == NULL)
   1890 		return;
   1891 
   1892 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1893 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1894 				      "GroupFormationFailure");
   1895 	if (msg == NULL)
   1896 		return;
   1897 
   1898 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
   1899 				     DBUS_TYPE_INVALID))
   1900 		dbus_connection_send(iface->con, msg, NULL);
   1901 	else
   1902 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1903 
   1904 	dbus_message_unref(msg);
   1905 }
   1906 
   1907 
   1908 /**
   1909  * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal
   1910  * @wpa_s: %wpa_supplicant network interface data
   1911  * @sa: Source address of the Invitation Request
   1912  * @dev_add: GO Device Address
   1913  * @bssid: P2P Group BSSID or %NULL if not received
   1914  * @id: Persistent group id or %0 if not persistent group
   1915  * @op_freq: Operating frequency for the group
   1916  */
   1917 
   1918 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
   1919 					      const u8 *sa, const u8 *dev_addr,
   1920 					      const u8 *bssid, int id,
   1921 					      int op_freq)
   1922 {
   1923 	DBusMessage *msg;
   1924 	DBusMessageIter iter, dict_iter;
   1925 	struct wpas_dbus_priv *iface;
   1926 
   1927 	iface = wpa_s->global->dbus;
   1928 
   1929 	/* Do nothing if the control interface is not turned on */
   1930 	if (iface == NULL)
   1931 		return;
   1932 
   1933 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1934 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1935 				      "InvitationReceived");
   1936 	if (msg == NULL)
   1937 		return;
   1938 
   1939 	dbus_message_iter_init_append(msg, &iter);
   1940 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1941 	    (sa &&
   1942 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "sa",
   1943 					      (const char *) sa, ETH_ALEN)) ||
   1944 	    (dev_addr &&
   1945 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr",
   1946 					      (const char *) dev_addr,
   1947 					      ETH_ALEN)) ||
   1948 	    (bssid &&
   1949 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
   1950 					      (const char *) bssid,
   1951 					      ETH_ALEN)) ||
   1952 	    (id &&
   1953 	     !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) ||
   1954 	    !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) ||
   1955 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
   1956 		dbus_message_unref(msg);
   1957 		return;
   1958 	}
   1959 
   1960 	dbus_connection_send(iface->con, msg, NULL);
   1961 	dbus_message_unref(msg);
   1962 }
   1963 
   1964 
   1965 #endif /* CONFIG_P2P */
   1966 
   1967 
   1968 /**
   1969  * wpas_dbus_signal_prop_changed - Signals change of property
   1970  * @wpa_s: %wpa_supplicant network interface data
   1971  * @property: indicates which property has changed
   1972  *
   1973  * Sends PropertyChanged signals with path, interface and arguments
   1974  * depending on which property has changed.
   1975  */
   1976 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
   1977 				   enum wpas_dbus_prop property)
   1978 {
   1979 	char *prop;
   1980 	dbus_bool_t flush;
   1981 
   1982 	if (wpa_s->dbus_new_path == NULL)
   1983 		return; /* Skip signal since D-Bus setup is not yet ready */
   1984 
   1985 	flush = FALSE;
   1986 	switch (property) {
   1987 	case WPAS_DBUS_PROP_AP_SCAN:
   1988 		prop = "ApScan";
   1989 		break;
   1990 #ifdef CONFIG_IEEE80211W
   1991 	case WPAS_DBUS_PROP_PMF:
   1992 		prop = "Pmf";
   1993 		break;
   1994 #endif /* CONFIG_IEEE80211W */
   1995 	case WPAS_DBUS_PROP_SCANNING:
   1996 		prop = "Scanning";
   1997 		break;
   1998 	case WPAS_DBUS_PROP_STATE:
   1999 		prop = "State";
   2000 		break;
   2001 	case WPAS_DBUS_PROP_CURRENT_BSS:
   2002 		prop = "CurrentBSS";
   2003 		break;
   2004 	case WPAS_DBUS_PROP_CURRENT_NETWORK:
   2005 		prop = "CurrentNetwork";
   2006 		break;
   2007 	case WPAS_DBUS_PROP_BSSS:
   2008 		prop = "BSSs";
   2009 		break;
   2010 	case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
   2011 		prop = "CurrentAuthMode";
   2012 		break;
   2013 	case WPAS_DBUS_PROP_DISCONNECT_REASON:
   2014 		prop = "DisconnectReason";
   2015 		flush = TRUE;
   2016 		break;
   2017 	case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
   2018 		prop = "AssocStatusCode";
   2019 		flush = TRUE;
   2020 		break;
   2021 	default:
   2022 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
   2023 			   __func__, property);
   2024 		return;
   2025 	}
   2026 
   2027 	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
   2028 				       wpa_s->dbus_new_path,
   2029 				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
   2030 	if (flush) {
   2031 		wpa_dbus_flush_object_changed_properties(
   2032 			wpa_s->global->dbus->con, wpa_s->dbus_new_path);
   2033 	}
   2034 }
   2035 
   2036 
   2037 /**
   2038  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
   2039  * @wpa_s: %wpa_supplicant network interface data
   2040  * @property: indicates which property has changed
   2041  * @id: unique BSS identifier
   2042  *
   2043  * Sends PropertyChanged signals with path, interface, and arguments depending
   2044  * on which property has changed.
   2045  */
   2046 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
   2047 				       enum wpas_dbus_bss_prop property,
   2048 				       unsigned int id)
   2049 {
   2050 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
   2051 	char *prop;
   2052 
   2053 	if (!wpa_s->dbus_new_path)
   2054 		return;
   2055 
   2056 	switch (property) {
   2057 	case WPAS_DBUS_BSS_PROP_SIGNAL:
   2058 		prop = "Signal";
   2059 		break;
   2060 	case WPAS_DBUS_BSS_PROP_FREQ:
   2061 		prop = "Frequency";
   2062 		break;
   2063 	case WPAS_DBUS_BSS_PROP_MODE:
   2064 		prop = "Mode";
   2065 		break;
   2066 	case WPAS_DBUS_BSS_PROP_PRIVACY:
   2067 		prop = "Privacy";
   2068 		break;
   2069 	case WPAS_DBUS_BSS_PROP_RATES:
   2070 		prop = "Rates";
   2071 		break;
   2072 	case WPAS_DBUS_BSS_PROP_WPA:
   2073 		prop = "WPA";
   2074 		break;
   2075 	case WPAS_DBUS_BSS_PROP_RSN:
   2076 		prop = "RSN";
   2077 		break;
   2078 	case WPAS_DBUS_BSS_PROP_WPS:
   2079 		prop = "WPS";
   2080 		break;
   2081 	case WPAS_DBUS_BSS_PROP_IES:
   2082 		prop = "IEs";
   2083 		break;
   2084 	case WPAS_DBUS_BSS_PROP_AGE:
   2085 		prop = "Age";
   2086 		break;
   2087 	default:
   2088 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
   2089 			   __func__, property);
   2090 		return;
   2091 	}
   2092 
   2093 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
   2094 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
   2095 		    wpa_s->dbus_new_path, id);
   2096 
   2097 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
   2098 				       WPAS_DBUS_NEW_IFACE_BSS, prop);
   2099 }
   2100 
   2101 
   2102 /**
   2103  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
   2104  * @global: wpa_global structure
   2105  *
   2106  * Sends PropertyChanged signals informing that debug level has changed.
   2107  */
   2108 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
   2109 {
   2110 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
   2111 				       WPAS_DBUS_NEW_INTERFACE,
   2112 				       "DebugLevel");
   2113 }
   2114 
   2115 
   2116 /**
   2117  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
   2118  * @global: wpa_global structure
   2119  *
   2120  * Sends PropertyChanged signals informing that debug timestamp has changed.
   2121  */
   2122 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
   2123 {
   2124 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
   2125 				       WPAS_DBUS_NEW_INTERFACE,
   2126 				       "DebugTimestamp");
   2127 }
   2128 
   2129 
   2130 /**
   2131  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
   2132  * @global: wpa_global structure
   2133  *
   2134  * Sends PropertyChanged signals informing that debug show_keys has changed.
   2135  */
   2136 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
   2137 {
   2138 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
   2139 				       WPAS_DBUS_NEW_INTERFACE,
   2140 				       "DebugShowKeys");
   2141 }
   2142 
   2143 
   2144 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
   2145 			       void *priv,
   2146 			       WPADBusArgumentFreeFunction priv_free,
   2147 			       const struct wpa_dbus_method_desc *methods,
   2148 			       const struct wpa_dbus_property_desc *properties,
   2149 			       const struct wpa_dbus_signal_desc *signals)
   2150 {
   2151 	int n;
   2152 
   2153 	obj_desc->user_data = priv;
   2154 	obj_desc->user_data_free_func = priv_free;
   2155 	obj_desc->methods = methods;
   2156 	obj_desc->properties = properties;
   2157 	obj_desc->signals = signals;
   2158 
   2159 	for (n = 0; properties && properties->dbus_property; properties++)
   2160 		n++;
   2161 
   2162 	obj_desc->prop_changed_flags = os_zalloc(n);
   2163 	if (!obj_desc->prop_changed_flags)
   2164 		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
   2165 			   __func__);
   2166 }
   2167 
   2168 
   2169 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
   2170 	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
   2171 	  (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
   2172 	  {
   2173 		  { "args", "a{sv}", ARG_IN },
   2174 		  { "path", "o", ARG_OUT },
   2175 		  END_ARGS
   2176 	  }
   2177 	},
   2178 	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
   2179 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
   2180 	  {
   2181 		  { "path", "o", ARG_IN },
   2182 		  END_ARGS
   2183 	  }
   2184 	},
   2185 	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
   2186 	  (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
   2187 	  {
   2188 		  { "ifname", "s", ARG_IN },
   2189 		  { "path", "o", ARG_OUT },
   2190 		  END_ARGS
   2191 	  }
   2192 	},
   2193 	{ "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
   2194 	  (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
   2195 	  {
   2196 		END_ARGS
   2197 	  }
   2198 	},
   2199 	{ NULL, NULL, NULL, { END_ARGS } }
   2200 };
   2201 
   2202 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
   2203 	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
   2204 	  wpas_dbus_getter_debug_level,
   2205 	  wpas_dbus_setter_debug_level,
   2206 	  NULL
   2207 	},
   2208 	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
   2209 	  wpas_dbus_getter_debug_timestamp,
   2210 	  wpas_dbus_setter_debug_timestamp,
   2211 	  NULL
   2212 	},
   2213 	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
   2214 	  wpas_dbus_getter_debug_show_keys,
   2215 	  wpas_dbus_setter_debug_show_keys,
   2216 	  NULL
   2217 	},
   2218 	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
   2219 	  wpas_dbus_getter_interfaces,
   2220 	  NULL,
   2221 	  NULL
   2222 	},
   2223 	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
   2224 	  wpas_dbus_getter_eap_methods,
   2225 	  NULL,
   2226 	  NULL
   2227 	},
   2228 	{ "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
   2229 	  wpas_dbus_getter_global_capabilities,
   2230 	  NULL,
   2231 	  NULL
   2232 	},
   2233 #ifdef CONFIG_WIFI_DISPLAY
   2234 	{ "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
   2235 	  wpas_dbus_getter_global_wfd_ies,
   2236 	  wpas_dbus_setter_global_wfd_ies,
   2237 	  NULL
   2238 	},
   2239 #endif /* CONFIG_WIFI_DISPLAY */
   2240 	{ NULL, NULL, NULL, NULL, NULL, NULL }
   2241 };
   2242 
   2243 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
   2244 	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
   2245 	  {
   2246 		  { "path", "o", ARG_OUT },
   2247 		  { "properties", "a{sv}", ARG_OUT },
   2248 		  END_ARGS
   2249 	  }
   2250 	},
   2251 	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
   2252 	  {
   2253 		  { "path", "o", ARG_OUT },
   2254 		  END_ARGS
   2255 	  }
   2256 	},
   2257 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   2258 	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
   2259 	  {
   2260 		  { "properties", "a{sv}", ARG_OUT },
   2261 		  END_ARGS
   2262 	  }
   2263 	},
   2264 	{ NULL, NULL, { END_ARGS } }
   2265 };
   2266 
   2267 
   2268 static char * uscore_to_dbus(const char *uscore)
   2269 {
   2270 	const char *p = uscore;
   2271 	char *str, *s;
   2272 	dbus_bool_t last_was_uscore = TRUE;
   2273 
   2274 	s = str = os_zalloc(os_strlen(uscore) + 1);
   2275 	if (!str)
   2276 		return NULL;
   2277 	while (p && *p) {
   2278 		if (*p == '_') {
   2279 			last_was_uscore = TRUE;
   2280 		} else {
   2281 			*s++ = last_was_uscore ? toupper(*p) : *p;
   2282 			last_was_uscore = FALSE;
   2283 		}
   2284 		p++;
   2285 	}
   2286 
   2287 	return str;
   2288 }
   2289 
   2290 
   2291 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
   2292 
   2293 
   2294 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
   2295 {
   2296 	int idx = priv->globals_start;
   2297 
   2298 	/* Free all allocated property values */
   2299 	while (priv->all_interface_properties[idx].dbus_property)
   2300 		os_free((char *)
   2301 			priv->all_interface_properties[idx++].dbus_property);
   2302 	os_free((char *) priv->all_interface_properties);
   2303 }
   2304 
   2305 
   2306 /**
   2307  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
   2308  * @global: Pointer to global data from wpa_supplicant_init()
   2309  * Returns: 0 on success or -1 on failure
   2310  *
   2311  * Initialize the dbus control interface for wpa_supplicant and start
   2312  * receiving commands from external programs over the bus.
   2313  */
   2314 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
   2315 {
   2316 	struct wpa_dbus_object_desc *obj_desc;
   2317 	int ret;
   2318 
   2319 	ret = wpa_dbus_ctrl_iface_props_init(priv);
   2320 	if (ret < 0) {
   2321 		wpa_printf(MSG_ERROR,
   2322 			   "dbus: Not enough memory to init interface properties");
   2323 		return -1;
   2324 	}
   2325 
   2326 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   2327 	if (!obj_desc) {
   2328 		wpa_printf(MSG_ERROR,
   2329 			   "Not enough memory to create object description");
   2330 		goto error;
   2331 	}
   2332 
   2333 	wpas_dbus_register(obj_desc, priv->global, NULL,
   2334 			   wpas_dbus_global_methods,
   2335 			   wpas_dbus_global_properties,
   2336 			   wpas_dbus_global_signals);
   2337 
   2338 	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
   2339 		   WPAS_DBUS_NEW_PATH);
   2340 	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
   2341 				       WPAS_DBUS_NEW_SERVICE,
   2342 				       obj_desc);
   2343 	if (ret < 0) {
   2344 		free_dbus_object_desc(obj_desc);
   2345 		goto error;
   2346 	}
   2347 
   2348 	priv->dbus_new_initialized = 1;
   2349 	return 0;
   2350 
   2351 error:
   2352 	wpa_dbus_ctrl_iface_props_deinit(priv);
   2353 	return -1;
   2354 }
   2355 
   2356 
   2357 /**
   2358  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
   2359  * wpa_supplicant
   2360  * @priv: Pointer to dbus private data from wpas_dbus_init()
   2361  *
   2362  * Deinitialize the dbus control interface that was initialized with
   2363  * wpas_dbus_ctrl_iface_init().
   2364  */
   2365 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
   2366 {
   2367 	if (!priv->dbus_new_initialized)
   2368 		return;
   2369 	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
   2370 		   WPAS_DBUS_NEW_PATH);
   2371 	dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
   2372 	wpa_dbus_ctrl_iface_props_deinit(priv);
   2373 }
   2374 
   2375 
   2376 static void wpa_dbus_free(void *ptr)
   2377 {
   2378 	os_free(ptr);
   2379 }
   2380 
   2381 
   2382 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
   2383 	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
   2384 	  wpas_dbus_getter_network_properties,
   2385 	  wpas_dbus_setter_network_properties,
   2386 	  NULL
   2387 	},
   2388 	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
   2389 	  wpas_dbus_getter_enabled,
   2390 	  wpas_dbus_setter_enabled,
   2391 	  NULL
   2392 	},
   2393 	{ NULL, NULL, NULL, NULL, NULL, NULL }
   2394 };
   2395 
   2396 
   2397 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
   2398 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   2399 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
   2400 	  {
   2401 		  { "properties", "a{sv}", ARG_OUT },
   2402 		  END_ARGS
   2403 	  }
   2404 	},
   2405 	{ NULL, NULL, { END_ARGS } }
   2406 };
   2407 
   2408 
   2409 /**
   2410  * wpas_dbus_register_network - Register a configured network with dbus
   2411  * @wpa_s: wpa_supplicant interface structure
   2412  * @ssid: network configuration data
   2413  * Returns: 0 on success, -1 on failure
   2414  *
   2415  * Registers network representing object with dbus
   2416  */
   2417 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
   2418 			       struct wpa_ssid *ssid)
   2419 {
   2420 	struct wpas_dbus_priv *ctrl_iface;
   2421 	struct wpa_dbus_object_desc *obj_desc;
   2422 	struct network_handler_args *arg;
   2423 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   2424 
   2425 #ifdef CONFIG_P2P
   2426 	/*
   2427 	 * If it is a persistent group register it as such.
   2428 	 * This is to handle cases where an interface is being initialized
   2429 	 * with a list of networks read from config.
   2430 	 */
   2431 	if (network_is_persistent_group(ssid))
   2432 		return wpas_dbus_register_persistent_group(wpa_s, ssid);
   2433 #endif /* CONFIG_P2P */
   2434 
   2435 	/* Do nothing if the control interface is not turned on */
   2436 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
   2437 		return 0;
   2438 	ctrl_iface = wpa_s->global->dbus;
   2439 	if (ctrl_iface == NULL)
   2440 		return 0;
   2441 
   2442 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   2443 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
   2444 		    wpa_s->dbus_new_path, ssid->id);
   2445 
   2446 	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
   2447 		   net_obj_path);
   2448 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   2449 	if (!obj_desc) {
   2450 		wpa_printf(MSG_ERROR,
   2451 			   "Not enough memory to create object description");
   2452 		goto err;
   2453 	}
   2454 
   2455 	/* allocate memory for handlers arguments */
   2456 	arg = os_zalloc(sizeof(struct network_handler_args));
   2457 	if (!arg) {
   2458 		wpa_printf(MSG_ERROR,
   2459 			   "Not enough memory to create arguments for method");
   2460 		goto err;
   2461 	}
   2462 
   2463 	arg->wpa_s = wpa_s;
   2464 	arg->ssid = ssid;
   2465 
   2466 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
   2467 			   wpas_dbus_network_properties,
   2468 			   wpas_dbus_network_signals);
   2469 
   2470 	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
   2471 					       wpa_s->ifname, obj_desc))
   2472 		goto err;
   2473 
   2474 	wpas_dbus_signal_network_added(wpa_s, ssid->id);
   2475 
   2476 	return 0;
   2477 
   2478 err:
   2479 	free_dbus_object_desc(obj_desc);
   2480 	return -1;
   2481 }
   2482 
   2483 
   2484 /**
   2485  * wpas_dbus_unregister_network - Unregister a configured network from dbus
   2486  * @wpa_s: wpa_supplicant interface structure
   2487  * @nid: network id
   2488  * Returns: 0 on success, -1 on failure
   2489  *
   2490  * Unregisters network representing object from dbus
   2491  */
   2492 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
   2493 {
   2494 	struct wpas_dbus_priv *ctrl_iface;
   2495 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   2496 	int ret;
   2497 #ifdef CONFIG_P2P
   2498 	struct wpa_ssid *ssid;
   2499 
   2500 	ssid = wpa_config_get_network(wpa_s->conf, nid);
   2501 
   2502 	/* If it is a persistent group unregister it as such */
   2503 	if (ssid && network_is_persistent_group(ssid))
   2504 		return wpas_dbus_unregister_persistent_group(wpa_s, nid);
   2505 #endif /* CONFIG_P2P */
   2506 
   2507 	/* Do nothing if the control interface is not turned on */
   2508 	if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
   2509 		return 0;
   2510 	ctrl_iface = wpa_s->global->dbus;
   2511 	if (ctrl_iface == NULL)
   2512 		return 0;
   2513 
   2514 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   2515 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
   2516 		    wpa_s->dbus_new_path, nid);
   2517 
   2518 	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
   2519 		   net_obj_path);
   2520 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
   2521 
   2522 	if (!ret)
   2523 		wpas_dbus_signal_network_removed(wpa_s, nid);
   2524 
   2525 	return ret;
   2526 }
   2527 
   2528 
   2529 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
   2530 	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
   2531 	  wpas_dbus_getter_bss_ssid,
   2532 	  NULL,
   2533 	  NULL
   2534 	},
   2535 	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
   2536 	  wpas_dbus_getter_bss_bssid,
   2537 	  NULL,
   2538 	  NULL
   2539 	},
   2540 	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
   2541 	  wpas_dbus_getter_bss_privacy,
   2542 	  NULL,
   2543 	  NULL
   2544 	},
   2545 	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
   2546 	  wpas_dbus_getter_bss_mode,
   2547 	  NULL,
   2548 	  NULL
   2549 	},
   2550 	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
   2551 	  wpas_dbus_getter_bss_signal,
   2552 	  NULL,
   2553 	  NULL
   2554 	},
   2555 	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
   2556 	  wpas_dbus_getter_bss_frequency,
   2557 	  NULL,
   2558 	  NULL
   2559 	},
   2560 	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
   2561 	  wpas_dbus_getter_bss_rates,
   2562 	  NULL,
   2563 	  NULL
   2564 	},
   2565 	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
   2566 	  wpas_dbus_getter_bss_wpa,
   2567 	  NULL,
   2568 	  NULL
   2569 	},
   2570 	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
   2571 	  wpas_dbus_getter_bss_rsn,
   2572 	  NULL,
   2573 	  NULL
   2574 	},
   2575 	{ "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
   2576 	  wpas_dbus_getter_bss_wps,
   2577 	  NULL,
   2578 	  NULL
   2579 	},
   2580 	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
   2581 	  wpas_dbus_getter_bss_ies,
   2582 	  NULL,
   2583 	  NULL
   2584 	},
   2585 	{ "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
   2586 	  wpas_dbus_getter_bss_age,
   2587 	  NULL,
   2588 	  NULL
   2589 	},
   2590 	{ NULL, NULL, NULL, NULL, NULL, NULL }
   2591 };
   2592 
   2593 
   2594 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
   2595 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   2596 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
   2597 	  {
   2598 		  { "properties", "a{sv}", ARG_OUT },
   2599 		  END_ARGS
   2600 	  }
   2601 	},
   2602 	{ NULL, NULL, { END_ARGS } }
   2603 };
   2604 
   2605 
   2606 /**
   2607  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
   2608  * @wpa_s: wpa_supplicant interface structure
   2609  * @bssid: scanned network bssid
   2610  * @id: unique BSS identifier
   2611  * Returns: 0 on success, -1 on failure
   2612  *
   2613  * Unregisters BSS representing object from dbus
   2614  */
   2615 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
   2616 			     u8 bssid[ETH_ALEN], unsigned int id)
   2617 {
   2618 	struct wpas_dbus_priv *ctrl_iface;
   2619 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   2620 
   2621 	/* Do nothing if the control interface is not turned on */
   2622 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
   2623 		return 0;
   2624 	ctrl_iface = wpa_s->global->dbus;
   2625 	if (ctrl_iface == NULL)
   2626 		return 0;
   2627 
   2628 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   2629 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
   2630 		    wpa_s->dbus_new_path, id);
   2631 
   2632 	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
   2633 		   bss_obj_path);
   2634 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
   2635 		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
   2636 			   bss_obj_path);
   2637 		return -1;
   2638 	}
   2639 
   2640 	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
   2641 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
   2642 
   2643 	return 0;
   2644 }
   2645 
   2646 
   2647 /**
   2648  * wpas_dbus_register_bss - Register a scanned BSS with dbus
   2649  * @wpa_s: wpa_supplicant interface structure
   2650  * @bssid: scanned network bssid
   2651  * @id: unique BSS identifier
   2652  * Returns: 0 on success, -1 on failure
   2653  *
   2654  * Registers BSS representing object with dbus
   2655  */
   2656 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
   2657 			   u8 bssid[ETH_ALEN], unsigned int id)
   2658 {
   2659 	struct wpas_dbus_priv *ctrl_iface;
   2660 	struct wpa_dbus_object_desc *obj_desc;
   2661 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   2662 	struct bss_handler_args *arg;
   2663 
   2664 	/* Do nothing if the control interface is not turned on */
   2665 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
   2666 		return 0;
   2667 	ctrl_iface = wpa_s->global->dbus;
   2668 	if (ctrl_iface == NULL)
   2669 		return 0;
   2670 
   2671 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   2672 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
   2673 		    wpa_s->dbus_new_path, id);
   2674 
   2675 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   2676 	if (!obj_desc) {
   2677 		wpa_printf(MSG_ERROR,
   2678 			   "Not enough memory to create object description");
   2679 		goto err;
   2680 	}
   2681 
   2682 	arg = os_zalloc(sizeof(struct bss_handler_args));
   2683 	if (!arg) {
   2684 		wpa_printf(MSG_ERROR,
   2685 			   "Not enough memory to create arguments for handler");
   2686 		goto err;
   2687 	}
   2688 	arg->wpa_s = wpa_s;
   2689 	arg->id = id;
   2690 
   2691 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
   2692 			   wpas_dbus_bss_properties,
   2693 			   wpas_dbus_bss_signals);
   2694 
   2695 	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
   2696 		   bss_obj_path);
   2697 	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
   2698 					       wpa_s->ifname, obj_desc)) {
   2699 		wpa_printf(MSG_ERROR,
   2700 			   "Cannot register BSSID dbus object %s.",
   2701 			   bss_obj_path);
   2702 		goto err;
   2703 	}
   2704 
   2705 	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
   2706 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
   2707 
   2708 	return 0;
   2709 
   2710 err:
   2711 	free_dbus_object_desc(obj_desc);
   2712 	return -1;
   2713 }
   2714 
   2715 
   2716 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
   2717 	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2718 	  (WPADBusMethodHandler) wpas_dbus_handler_scan,
   2719 	  {
   2720 		  { "args", "a{sv}", ARG_IN },
   2721 		  END_ARGS
   2722 	  }
   2723 	},
   2724 	{ "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2725 	  (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
   2726 	  {
   2727 		  { "args", "a{sv}", ARG_OUT },
   2728 		  END_ARGS
   2729 	  }
   2730 	},
   2731 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2732 	  (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
   2733 	  {
   2734 		  END_ARGS
   2735 	  }
   2736 	},
   2737 	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2738 	  (WPADBusMethodHandler) wpas_dbus_handler_add_network,
   2739 	  {
   2740 		  { "args", "a{sv}", ARG_IN },
   2741 		  { "path", "o", ARG_OUT },
   2742 		  END_ARGS
   2743 	  }
   2744 	},
   2745 	{ "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2746 	  (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
   2747 	  {
   2748 		  END_ARGS
   2749 	  }
   2750 	},
   2751 	{ "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2752 	  (WPADBusMethodHandler) wpas_dbus_handler_reattach,
   2753 	  {
   2754 		  END_ARGS
   2755 	  }
   2756 	},
   2757 	{ "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2758 	  (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
   2759 	  {
   2760 		  END_ARGS
   2761 	  }
   2762 	},
   2763 	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2764 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
   2765 	  {
   2766 		  { "path", "o", ARG_IN },
   2767 		  END_ARGS
   2768 	  }
   2769 	},
   2770 	{ "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2771 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
   2772 	  {
   2773 		  END_ARGS
   2774 	  }
   2775 	},
   2776 	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2777 	  (WPADBusMethodHandler) wpas_dbus_handler_select_network,
   2778 	  {
   2779 		  { "path", "o", ARG_IN },
   2780 		  END_ARGS
   2781 	  }
   2782 	},
   2783 	{ "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2784 	  (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
   2785 	  {
   2786 		  { "path", "o", ARG_IN },
   2787 		  { "field", "s", ARG_IN },
   2788 		  { "value", "s", ARG_IN },
   2789 		  END_ARGS
   2790 	  }
   2791 	},
   2792 #ifndef CONFIG_NO_CONFIG_BLOBS
   2793 	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2794 	  (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
   2795 	  {
   2796 		  { "name", "s", ARG_IN },
   2797 		  { "data", "ay", ARG_IN },
   2798 		  END_ARGS
   2799 	  }
   2800 	},
   2801 	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2802 	  (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
   2803 	  {
   2804 		  { "name", "s", ARG_IN },
   2805 		  { "data", "ay", ARG_OUT },
   2806 		  END_ARGS
   2807 	  }
   2808 	},
   2809 	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2810 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
   2811 	  {
   2812 		  { "name", "s", ARG_IN },
   2813 		  END_ARGS
   2814 	  }
   2815 	},
   2816 #endif /* CONFIG_NO_CONFIG_BLOBS */
   2817 	{ "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2818 	  (WPADBusMethodHandler)
   2819 	  wpas_dbus_handler_set_pkcs11_engine_and_module_path,
   2820 	  {
   2821 		  { "pkcs11_engine_path", "s", ARG_IN },
   2822 		  { "pkcs11_module_path", "s", ARG_IN },
   2823 		  END_ARGS
   2824 	  }
   2825 	},
   2826 #ifdef CONFIG_WPS
   2827 	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
   2828 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
   2829 	  {
   2830 		  { "args", "a{sv}", ARG_IN },
   2831 		  { "output", "a{sv}", ARG_OUT },
   2832 		  END_ARGS
   2833 	  }
   2834 	},
   2835 	{ "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
   2836 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
   2837 	  {
   2838 		  END_ARGS
   2839 	  }
   2840 	},
   2841 #endif /* CONFIG_WPS */
   2842 #ifdef CONFIG_P2P
   2843 	{ "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2844 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
   2845 	  {
   2846 		  { "args", "a{sv}", ARG_IN },
   2847 		  END_ARGS
   2848 	  }
   2849 	},
   2850 	{ "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2851 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
   2852 	  {
   2853 		  END_ARGS
   2854 	  }
   2855 	},
   2856 	{ "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2857 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
   2858 	  {
   2859 		  { "timeout", "i", ARG_IN },
   2860 		  END_ARGS
   2861 	  }
   2862 	},
   2863 	{ "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2864 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
   2865 	  {
   2866 		  { "args", "a{sv}", ARG_IN },
   2867 		  END_ARGS
   2868 	  }
   2869 	},
   2870 	{ "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2871 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
   2872 	  {
   2873 		  { "args", "a{sv}", ARG_IN },
   2874 		  END_ARGS
   2875 	  }
   2876 	},
   2877 	{ "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2878 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
   2879 	  {
   2880 		  { "peer", "o", ARG_IN },
   2881 		  { "config_method", "s", ARG_IN },
   2882 		  END_ARGS
   2883 	  }
   2884 	},
   2885 	{ "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2886 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
   2887 	  {
   2888 		  { "args", "a{sv}", ARG_IN },
   2889 		  { "generated_pin", "s", ARG_OUT },
   2890 		  END_ARGS
   2891 	  }
   2892 	},
   2893 	{ "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2894 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
   2895 	  {
   2896 		  { "args", "a{sv}", ARG_IN },
   2897 		  END_ARGS
   2898 	  }
   2899 	},
   2900 	{ "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2901 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
   2902 	  {
   2903 		  END_ARGS
   2904 	  }
   2905 	},
   2906 	{ "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2907 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
   2908 	  {
   2909 		  { "args", "a{sv}", ARG_IN },
   2910 		  END_ARGS
   2911 	  }
   2912 	},
   2913 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2914 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
   2915 	  {
   2916 		  END_ARGS
   2917 	  }
   2918 	},
   2919 	{ "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2920 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
   2921 	  {
   2922 		  { "peer", "o", ARG_IN },
   2923 		  END_ARGS
   2924 	  }
   2925 	},
   2926 	{ "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2927 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
   2928 	  {
   2929 		  { "args", "a{sv}", ARG_IN },
   2930 		  END_ARGS
   2931 	  }
   2932 	},
   2933 	{ "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2934 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
   2935 	  {
   2936 		  END_ARGS
   2937 	  }
   2938 	},
   2939 	{ "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2940 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
   2941 	  {
   2942 		  { "args", "a{sv}", ARG_IN },
   2943 		  END_ARGS
   2944 	  }
   2945 	},
   2946 	{ "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2947 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
   2948 	  {
   2949 		  { "args", "a{sv}", ARG_IN },
   2950 		  END_ARGS
   2951 	  }
   2952 	},
   2953 	{ "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2954 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
   2955 	  {
   2956 		  END_ARGS
   2957 	  }
   2958 	},
   2959 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2960 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
   2961 	  {
   2962 		  { "args", "a{sv}", ARG_IN },
   2963 		  { "ref", "t", ARG_OUT },
   2964 		  END_ARGS
   2965 	  }
   2966 	},
   2967 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2968 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
   2969 	  {
   2970 		  { "args", "a{sv}", ARG_IN },
   2971 		  END_ARGS
   2972 	  }
   2973 	},
   2974 	{ "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2975 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
   2976 	  {
   2977 		  { "args", "t", ARG_IN },
   2978 		  END_ARGS
   2979 	  }
   2980 	},
   2981 	{ "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2982 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
   2983 	  {
   2984 		  END_ARGS
   2985 	  }
   2986 	},
   2987 	{ "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2988 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
   2989 	  {
   2990 		  { "arg", "i", ARG_IN },
   2991 		  END_ARGS
   2992 	  }
   2993 	},
   2994 	{ "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2995 	  (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
   2996 	  {
   2997 		  { "args", "a{sv}", ARG_IN },
   2998 		  { "path", "o", ARG_OUT },
   2999 		  END_ARGS
   3000 	  }
   3001 	},
   3002 	{ "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3003 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
   3004 	  {
   3005 		  { "path", "o", ARG_IN },
   3006 		  END_ARGS
   3007 	  }
   3008 	},
   3009 	{ "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3010 	  (WPADBusMethodHandler)
   3011 	  wpas_dbus_handler_remove_all_persistent_groups,
   3012 	  {
   3013 		  END_ARGS
   3014 	  }
   3015 	},
   3016 #endif /* CONFIG_P2P */
   3017 	{ "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3018 	  (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
   3019 	  {
   3020 		  { "age", "u", ARG_IN },
   3021 		  END_ARGS
   3022 	  }
   3023 	},
   3024 #ifdef CONFIG_AP
   3025 	{ "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3026 	  (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
   3027 	  {
   3028 		  END_ARGS
   3029 	  }
   3030 	},
   3031 	{ "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3032 	  (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
   3033 	  {
   3034 		  END_ARGS
   3035 	  }
   3036 	},
   3037 #endif /* CONFIG_AP */
   3038 	{ "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3039 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
   3040 	  {
   3041 		  END_ARGS
   3042 	  }
   3043 	},
   3044 	{ "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3045 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
   3046 	  {
   3047 		  END_ARGS
   3048 	  }
   3049 	},
   3050 #ifdef CONFIG_AUTOSCAN
   3051 	{ "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3052 	  (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
   3053 	  {
   3054 		  { "arg", "s", ARG_IN },
   3055 		  END_ARGS
   3056 	  }
   3057 	},
   3058 #endif /* CONFIG_AUTOSCAN */
   3059 #ifdef CONFIG_TDLS
   3060 	{ "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3061 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
   3062 	  {
   3063 		  { "peer_address", "s", ARG_IN },
   3064 		  END_ARGS
   3065 	  }
   3066 	},
   3067 	{ "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3068 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
   3069 	  {
   3070 		  { "peer_address", "s", ARG_IN },
   3071 		  END_ARGS
   3072 	  }
   3073 	},
   3074 	{ "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3075 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
   3076 	  {
   3077 		  { "peer_address", "s", ARG_IN },
   3078 		  { "status", "s", ARG_OUT },
   3079 		  END_ARGS
   3080 	  }
   3081 	},
   3082 	{ "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3083 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
   3084 	  {
   3085 		  { "peer_address", "s", ARG_IN },
   3086 		  END_ARGS
   3087 	  }
   3088 	},
   3089 #endif /* CONFIG_TDLS */
   3090 	{ "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3091 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
   3092 	  {
   3093 		  { "frame_id", "i", ARG_IN },
   3094 		  { "ielems", "ay", ARG_IN },
   3095 		  END_ARGS
   3096 	  }
   3097 	},
   3098 	{ "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3099 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
   3100 	  {
   3101 		  { "frame_id", "i", ARG_IN },
   3102 		  { "ielems", "ay", ARG_OUT },
   3103 		  END_ARGS
   3104 	  }
   3105 	},
   3106 	{ "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3107 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
   3108 	  {
   3109 		  { "frame_id", "i", ARG_IN },
   3110 		  { "ielems", "ay", ARG_IN },
   3111 		  END_ARGS
   3112 	  }
   3113 	},
   3114 #ifndef CONFIG_NO_CONFIG_WRITE
   3115 	{ "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3116 	  (WPADBusMethodHandler) wpas_dbus_handler_save_config,
   3117 	  {
   3118 		  END_ARGS
   3119 	  }
   3120 	},
   3121 #endif /* CONFIG_NO_CONFIG_WRITE */
   3122 	{ NULL, NULL, NULL, { END_ARGS } }
   3123 };
   3124 
   3125 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
   3126 	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
   3127 	  wpas_dbus_getter_capabilities,
   3128 	  NULL,
   3129 	  NULL
   3130 	},
   3131 	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3132 	  wpas_dbus_getter_state,
   3133 	  NULL,
   3134 	  NULL
   3135 	},
   3136 	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
   3137 	  wpas_dbus_getter_scanning,
   3138 	  NULL,
   3139 	  NULL
   3140 	},
   3141 	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
   3142 	  wpas_dbus_getter_ap_scan,
   3143 	  wpas_dbus_setter_ap_scan,
   3144 	  NULL
   3145 	},
   3146 #ifdef CONFIG_IEEE80211W
   3147 	{ "Pmf", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
   3148 	  wpas_dbus_getter_pmf,
   3149 	  wpas_dbus_setter_pmf,
   3150 	  NULL
   3151 	},
   3152 #endif /* CONFIG_IEEE80211W */
   3153 	{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
   3154 	  wpas_dbus_getter_bss_expire_age,
   3155 	  wpas_dbus_setter_bss_expire_age,
   3156 	  NULL
   3157 	},
   3158 	{ "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
   3159 	  wpas_dbus_getter_bss_expire_count,
   3160 	  wpas_dbus_setter_bss_expire_count,
   3161 	  NULL
   3162 	},
   3163 	{ "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3164 	  wpas_dbus_getter_country,
   3165 	  wpas_dbus_setter_country,
   3166 	  NULL
   3167 	},
   3168 	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3169 	  wpas_dbus_getter_ifname,
   3170 	  NULL,
   3171 	  NULL
   3172 	},
   3173 	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3174 	  wpas_dbus_getter_driver,
   3175 	  NULL,
   3176 	  NULL
   3177 	},
   3178 	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3179 	  wpas_dbus_getter_bridge_ifname,
   3180 	  NULL,
   3181 	  NULL
   3182 	},
   3183 	{ "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3184 	  wpas_dbus_getter_config_file,
   3185 	  NULL,
   3186 	  NULL
   3187 	},
   3188 	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
   3189 	  wpas_dbus_getter_current_bss,
   3190 	  NULL,
   3191 	  NULL
   3192 	},
   3193 	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
   3194 	  wpas_dbus_getter_current_network,
   3195 	  NULL,
   3196 	  NULL
   3197 	},
   3198 	{ "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3199 	  wpas_dbus_getter_current_auth_mode,
   3200 	  NULL,
   3201 	  NULL
   3202 	},
   3203 	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
   3204 	  wpas_dbus_getter_blobs,
   3205 	  NULL,
   3206 	  NULL
   3207 	},
   3208 	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
   3209 	  wpas_dbus_getter_bsss,
   3210 	  NULL,
   3211 	  NULL
   3212 	},
   3213 	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
   3214 	  wpas_dbus_getter_networks,
   3215 	  NULL,
   3216 	  NULL
   3217 	},
   3218 	{ "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
   3219 	  wpas_dbus_getter_fast_reauth,
   3220 	  wpas_dbus_setter_fast_reauth,
   3221 	  NULL
   3222 	},
   3223 	{ "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
   3224 	  wpas_dbus_getter_scan_interval,
   3225 	  wpas_dbus_setter_scan_interval,
   3226 	  NULL
   3227 	},
   3228 	{ "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3229 	  wpas_dbus_getter_pkcs11_engine_path,
   3230 	  NULL,
   3231 	  NULL
   3232 	},
   3233 	{ "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   3234 	  wpas_dbus_getter_pkcs11_module_path,
   3235 	  NULL,
   3236 	  NULL
   3237 	},
   3238 #ifdef CONFIG_WPS
   3239 	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
   3240 	  wpas_dbus_getter_process_credentials,
   3241 	  wpas_dbus_setter_process_credentials,
   3242 	  NULL
   3243 	},
   3244 	{ "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
   3245 	  wpas_dbus_getter_config_methods,
   3246 	  wpas_dbus_setter_config_methods,
   3247 	  NULL
   3248 	},
   3249 	{
   3250 	  "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
   3251 	  wpas_dbus_getter_wps_device_name,
   3252 	  wpas_dbus_setter_wps_device_name,
   3253 	  NULL
   3254 	},
   3255 	{
   3256 	  "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
   3257 	  wpas_dbus_getter_wps_manufacturer,
   3258 	  wpas_dbus_setter_wps_manufacturer,
   3259 	  NULL
   3260 	},
   3261 	{
   3262 	  "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
   3263 	  wpas_dbus_getter_wps_device_model_name,
   3264 	  wpas_dbus_setter_wps_device_model_name,
   3265 	  NULL
   3266 	},
   3267 	{
   3268 	  "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
   3269 	  wpas_dbus_getter_wps_device_model_number,
   3270 	  wpas_dbus_setter_wps_device_model_number,
   3271 	  NULL
   3272 	},
   3273 	{
   3274 	  "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
   3275 	  wpas_dbus_getter_wps_device_serial_number,
   3276 	  wpas_dbus_setter_wps_device_serial_number,
   3277 	  NULL
   3278 	},
   3279 	{
   3280 	  "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
   3281 	  wpas_dbus_getter_wps_device_device_type,
   3282 	  wpas_dbus_setter_wps_device_device_type,
   3283 	  NULL
   3284 	},
   3285 #endif /* CONFIG_WPS */
   3286 #ifdef CONFIG_P2P
   3287 	{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
   3288 	  wpas_dbus_getter_p2p_device_config,
   3289 	  wpas_dbus_setter_p2p_device_config,
   3290 	  NULL
   3291 	},
   3292 	{ "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
   3293 	  wpas_dbus_getter_p2p_peers,
   3294 	  NULL,
   3295 	  NULL
   3296 	},
   3297 	{ "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
   3298 	  wpas_dbus_getter_p2p_role,
   3299 	  NULL,
   3300 	  NULL
   3301 	},
   3302 	{ "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
   3303 	  wpas_dbus_getter_p2p_group,
   3304 	  NULL,
   3305 	  NULL
   3306 	},
   3307 	{ "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
   3308 	  wpas_dbus_getter_p2p_peergo,
   3309 	  NULL,
   3310 	  NULL
   3311 	},
   3312 	{ "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
   3313 	  wpas_dbus_getter_persistent_groups,
   3314 	  NULL,
   3315 	  NULL
   3316 	},
   3317 #endif /* CONFIG_P2P */
   3318 	{ "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
   3319 	  wpas_dbus_getter_disconnect_reason,
   3320 	  NULL,
   3321 	  NULL
   3322 	},
   3323 	{ "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
   3324 	  wpas_dbus_getter_assoc_status_code,
   3325 	  NULL,
   3326 	  NULL
   3327 	},
   3328 	{ NULL, NULL, NULL, NULL, NULL, NULL }
   3329 };
   3330 
   3331 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
   3332 	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3333 	  {
   3334 		  { "success", "b", ARG_OUT },
   3335 		  END_ARGS
   3336 	  }
   3337 	},
   3338 	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3339 	  {
   3340 		  { "path", "o", ARG_OUT },
   3341 		  { "properties", "a{sv}", ARG_OUT },
   3342 		  END_ARGS
   3343 	  }
   3344 	},
   3345 	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3346 	  {
   3347 		  { "path", "o", ARG_OUT },
   3348 		  END_ARGS
   3349 	  }
   3350 	},
   3351 	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3352 	  {
   3353 		  { "name", "s", ARG_OUT },
   3354 		  END_ARGS
   3355 	  }
   3356 	},
   3357 	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3358 	  {
   3359 		  { "name", "s", ARG_OUT },
   3360 		  END_ARGS
   3361 	  }
   3362 	},
   3363 	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3364 	  {
   3365 		  { "path", "o", ARG_OUT },
   3366 		  { "properties", "a{sv}", ARG_OUT },
   3367 		  END_ARGS
   3368 	  }
   3369 	},
   3370 	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3371 	  {
   3372 		  { "path", "o", ARG_OUT },
   3373 		  END_ARGS
   3374 	  }
   3375 	},
   3376 	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3377 	  {
   3378 		  { "path", "o", ARG_OUT },
   3379 		  END_ARGS
   3380 	  }
   3381 	},
   3382 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   3383 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3384 	  {
   3385 		  { "properties", "a{sv}", ARG_OUT },
   3386 		  END_ARGS
   3387 	  }
   3388 	},
   3389 #ifdef CONFIG_WPS
   3390 	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
   3391 	  {
   3392 		  { "name", "s", ARG_OUT },
   3393 		  { "args", "a{sv}", ARG_OUT },
   3394 		  END_ARGS
   3395 	  }
   3396 	},
   3397 	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
   3398 	  {
   3399 		  { "credentials", "a{sv}", ARG_OUT },
   3400 		  END_ARGS
   3401 	  }
   3402 	},
   3403 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   3404 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
   3405 	  {
   3406 		  { "properties", "a{sv}", ARG_OUT },
   3407 		  END_ARGS
   3408 	  }
   3409 	},
   3410 #endif /* CONFIG_WPS */
   3411 #ifdef CONFIG_P2P
   3412 	{ "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3413 	  {
   3414 		  { "path", "o", ARG_OUT },
   3415 		  END_ARGS
   3416 	  }
   3417 	},
   3418 	{ "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3419 	  {
   3420 		  { "path", "o", ARG_OUT },
   3421 		  { "properties", "a{sv}", ARG_OUT },
   3422 		  END_ARGS
   3423 	  }
   3424 	},
   3425 	{ "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3426 	  {
   3427 		  { "path", "o", ARG_OUT },
   3428 		  END_ARGS
   3429 	  }
   3430 	},
   3431 	{ "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3432 	  {
   3433 		  END_ARGS
   3434 	  }
   3435 	},
   3436 	{ "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3437 	  {
   3438 		  { "peer_object", "o", ARG_OUT },
   3439 		  { "pin", "s", ARG_OUT },
   3440 		  END_ARGS
   3441 	  }
   3442 	},
   3443 	{ "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3444 	  {
   3445 		  { "peer_object", "o", ARG_OUT },
   3446 		  { "pin", "s", ARG_OUT },
   3447 		  END_ARGS
   3448 	  }
   3449 	},
   3450 	{ "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3451 	  {
   3452 		  { "peer_object", "o", ARG_OUT },
   3453 		  END_ARGS
   3454 	  }
   3455 	},
   3456 	{ "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3457 	  {
   3458 		  { "peer_object", "o", ARG_OUT },
   3459 		  END_ARGS
   3460 	  }
   3461 	},
   3462 	{ "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3463 	  {
   3464 		  { "peer_object", "o", ARG_OUT },
   3465 		  END_ARGS
   3466 	  }
   3467 	},
   3468 	{ "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3469 	  {
   3470 		  { "peer_object", "o", ARG_OUT },
   3471 		  END_ARGS
   3472 	  }
   3473 	},
   3474 	{ "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3475 	  {
   3476 		  { "peer_object", "o", ARG_OUT },
   3477 		  { "status", "i", ARG_OUT },
   3478 		  END_ARGS
   3479 	  }
   3480 	},
   3481 	{ "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3482 	  {
   3483 		  { "properties", "a{sv}", ARG_OUT },
   3484 		  END_ARGS
   3485 	  }
   3486 	},
   3487 	{ "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3488 	  {
   3489 		  { "reason", "s", ARG_OUT },
   3490 		  END_ARGS
   3491 	  }
   3492 	},
   3493 	{ "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3494 	  {
   3495 		  { "properties", "a{sv}", ARG_OUT },
   3496 		  END_ARGS
   3497 	  }
   3498 	},
   3499 	{ "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3500 	  {
   3501 		  { "properties", "a{sv}", ARG_OUT },
   3502 		  END_ARGS
   3503 	  }
   3504 	},
   3505 	{ "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3506 	  {
   3507 		  { "path", "o", ARG_OUT },
   3508 		  { "dev_passwd_id", "q", ARG_OUT },
   3509 		  { "device_go_intent", "y", ARG_OUT },
   3510 		  END_ARGS
   3511 	  }
   3512 	},
   3513 	{ "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3514 	  {
   3515 		  { "invite_result", "a{sv}", ARG_OUT },
   3516 		  END_ARGS
   3517 	  }
   3518 	},
   3519 	{ "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3520 	  {
   3521 		  { "properties", "a{sv}", ARG_OUT },
   3522 		  END_ARGS
   3523 	  }
   3524 	},
   3525 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3526 	  {
   3527 		  { "sd_request", "a{sv}", ARG_OUT },
   3528 		  END_ARGS
   3529 	  }
   3530 	},
   3531 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3532 	  {
   3533 		  { "sd_response", "a{sv}", ARG_OUT },
   3534 		  END_ARGS
   3535 	  }
   3536 	},
   3537 	{ "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3538 	  {
   3539 		  { "path", "o", ARG_OUT },
   3540 		  { "properties", "a{sv}", ARG_OUT },
   3541 		  END_ARGS
   3542 	  }
   3543 	},
   3544 	{ "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3545 	  {
   3546 		  { "path", "o", ARG_OUT },
   3547 		  END_ARGS
   3548 	  }
   3549 	},
   3550 	{ "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3551 	  {
   3552 		  { "name", "s", ARG_OUT },
   3553 		  { "args", "a{sv}", ARG_OUT },
   3554 		  END_ARGS
   3555 	  }
   3556 	},
   3557 	{ "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3558 	  {
   3559 		  { "properties", "a{sv}", ARG_OUT },
   3560 		  END_ARGS
   3561 	  }
   3562 	},
   3563 #endif /* CONFIG_P2P */
   3564 #ifdef CONFIG_AP
   3565 	{ "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3566 	  {
   3567 		  { "args", "a{sv}", ARG_OUT },
   3568 		  END_ARGS
   3569 	  }
   3570 	},
   3571 #endif /* CONFIG_AP */
   3572 	{ "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3573 	  {
   3574 		  { "certification", "a{sv}", ARG_OUT },
   3575 		  END_ARGS
   3576 	  }
   3577 	},
   3578 	{ "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3579 	  {
   3580 		  { "status", "s", ARG_OUT },
   3581 		  { "parameter", "s", ARG_OUT },
   3582 		  END_ARGS
   3583 	  }
   3584 	},
   3585 	{ "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3586 	  {
   3587 		  { "name", "s", ARG_OUT },
   3588 		  END_ARGS
   3589 	  }
   3590 	},
   3591 	{ "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3592 	  {
   3593 		  { "name", "s", ARG_OUT },
   3594 		  END_ARGS
   3595 	  }
   3596 	},
   3597 	{ "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3598 	  {
   3599 		  { "path", "o", ARG_OUT },
   3600 		  { "field", "s", ARG_OUT },
   3601 		  { "text", "s", ARG_OUT },
   3602 		  END_ARGS
   3603 	  }
   3604 	},
   3605 	{ NULL, NULL, { END_ARGS } }
   3606 };
   3607 
   3608 
   3609 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
   3610 {
   3611 	size_t all_size;
   3612 	unsigned int i, j, count, num_const, num_globals;
   3613 	const char *global_name;
   3614 	static const char * const ignored_globals[] = {
   3615 		"bss_expiration_age", "bss_expiration_scan_count",
   3616 		"ap_scan", "country", "fast_reauth",
   3617 		"pkcs11_engine_path", "pkcs11_module_path"
   3618 	};
   3619 
   3620 	/* wpas_dbus_interface_properties terminates with a NULL element */
   3621 	num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
   3622 
   3623 	num_globals = wpa_config_get_num_global_field_names();
   3624 	priv->globals_start = num_const;
   3625 
   3626 	/* allocate enough for all properties + terminating NULL element */
   3627 	all_size = (num_globals + num_const + 1) *
   3628 		sizeof(wpas_dbus_interface_properties[0]);
   3629 	priv->all_interface_properties = os_zalloc(all_size);
   3630 	if (!priv->all_interface_properties) {
   3631 		wpa_printf(MSG_ERROR,
   3632 			   "dbus: Not enough memory for interface properties");
   3633 		return -1;
   3634 	}
   3635 
   3636 	/* Copy constant interface properties to the start of the array */
   3637 	os_memcpy(priv->all_interface_properties,
   3638 		  wpas_dbus_interface_properties,
   3639 		  sizeof(wpas_dbus_interface_properties));
   3640 
   3641 	/* Dynamically construct interface global properties */
   3642 	for (i = 0, count = num_const; i < num_globals; i++) {
   3643 		struct wpa_dbus_property_desc *desc;
   3644 		int no_var = 0;
   3645 
   3646 		/* ignore globals that are actually just methods */
   3647 		global_name = wpa_config_get_global_field_name(i, &no_var);
   3648 		if (no_var)
   3649 			continue;
   3650 		/* Ignore fields already explicitly exposed */
   3651 		for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
   3652 			if (os_strcmp(global_name, ignored_globals[j]) == 0)
   3653 				break;
   3654 		}
   3655 		if (j < ARRAY_SIZE(ignored_globals))
   3656 			continue;
   3657 
   3658 		desc = &priv->all_interface_properties[count++];
   3659 		desc->dbus_property = uscore_to_dbus(global_name);
   3660 		if (!desc->dbus_property) {
   3661 			wpa_printf(MSG_ERROR,
   3662 				   "dbus: Not enough memory for D-Bus property name");
   3663 			goto error;
   3664 		}
   3665 		desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
   3666 		desc->type = "s";
   3667 		desc->getter = wpas_dbus_getter_iface_global;
   3668 		desc->setter = wpas_dbus_setter_iface_global;
   3669 		desc->data = global_name;
   3670 	}
   3671 
   3672 	return 0;
   3673 
   3674 error:
   3675 	wpa_dbus_ctrl_iface_props_deinit(priv);
   3676 	return -1;
   3677 }
   3678 
   3679 
   3680 /**
   3681  * wpas_dbus_register_interface - Register an interface with D-Bus
   3682  * @wpa_s: wpa_supplicant interface structure
   3683  * Returns: 0 on success, -1 on failure
   3684  */
   3685 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
   3686 {
   3687 	struct wpa_dbus_object_desc *obj_desc = NULL;
   3688 	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
   3689 	int next;
   3690 
   3691 	/* Do nothing if the control interface is not turned on */
   3692 	if (ctrl_iface == NULL)
   3693 		return 0;
   3694 
   3695 	/* Create and set the interface's object path */
   3696 	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
   3697 	if (wpa_s->dbus_new_path == NULL)
   3698 		return -1;
   3699 	next = ctrl_iface->next_objid++;
   3700 	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3701 		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
   3702 		    next);
   3703 
   3704 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   3705 	if (!obj_desc) {
   3706 		wpa_printf(MSG_ERROR,
   3707 			   "Not enough memory to create object description");
   3708 		goto err;
   3709 	}
   3710 
   3711 	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
   3712 			   ctrl_iface->all_interface_properties,
   3713 			   wpas_dbus_interface_signals);
   3714 
   3715 	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
   3716 		   wpa_s->dbus_new_path);
   3717 	if (wpa_dbus_register_object_per_iface(ctrl_iface,
   3718 					       wpa_s->dbus_new_path,
   3719 					       wpa_s->ifname, obj_desc))
   3720 		goto err;
   3721 
   3722 	wpas_dbus_signal_interface_added(wpa_s);
   3723 
   3724 	return 0;
   3725 
   3726 err:
   3727 	os_free(wpa_s->dbus_new_path);
   3728 	wpa_s->dbus_new_path = NULL;
   3729 	free_dbus_object_desc(obj_desc);
   3730 	return -1;
   3731 }
   3732 
   3733 
   3734 /**
   3735  * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
   3736  * @wpa_s: wpa_supplicant interface structure
   3737  * Returns: 0 on success, -1 on failure
   3738  */
   3739 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
   3740 {
   3741 	struct wpas_dbus_priv *ctrl_iface;
   3742 
   3743 	/* Do nothing if the control interface is not turned on */
   3744 	if (wpa_s == NULL || wpa_s->global == NULL)
   3745 		return 0;
   3746 	ctrl_iface = wpa_s->global->dbus;
   3747 	if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
   3748 		return 0;
   3749 
   3750 	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
   3751 		   wpa_s->dbus_new_path);
   3752 
   3753 #ifdef CONFIG_AP
   3754 	if (wpa_s->preq_notify_peer) {
   3755 		wpas_dbus_unsubscribe_noc(ctrl_iface);
   3756 		os_free(wpa_s->preq_notify_peer);
   3757 		wpa_s->preq_notify_peer = NULL;
   3758 	}
   3759 #endif /* CONFIG_AP */
   3760 
   3761 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
   3762 						 wpa_s->dbus_new_path))
   3763 		return -1;
   3764 
   3765 	wpas_dbus_signal_interface_removed(wpa_s);
   3766 
   3767 	os_free(wpa_s->dbus_new_path);
   3768 	wpa_s->dbus_new_path = NULL;
   3769 
   3770 	return 0;
   3771 }
   3772 
   3773 #ifdef CONFIG_P2P
   3774 
   3775 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
   3776 	{ "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3777 	  wpas_dbus_getter_p2p_peer_device_name,
   3778 	  NULL,
   3779 	  NULL
   3780 	},
   3781 	{ "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3782 	  wpas_dbus_getter_p2p_peer_manufacturer,
   3783 	  NULL,
   3784 	  NULL
   3785 	},
   3786 	{ "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3787 	  wpas_dbus_getter_p2p_peer_modelname,
   3788 	  NULL,
   3789 	  NULL
   3790 	},
   3791 	{ "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3792 	  wpas_dbus_getter_p2p_peer_modelnumber,
   3793 	  NULL,
   3794 	  NULL
   3795 	},
   3796 	{ "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3797 	  wpas_dbus_getter_p2p_peer_serialnumber,
   3798 	  NULL,
   3799 	  NULL
   3800 	},
   3801 	{ "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
   3802 	  wpas_dbus_getter_p2p_peer_primary_device_type,
   3803 	  NULL,
   3804 	  NULL
   3805 	},
   3806 	{ "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
   3807 	  wpas_dbus_getter_p2p_peer_config_method,
   3808 	  NULL,
   3809 	  NULL
   3810 	},
   3811 	{ "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
   3812 	  wpas_dbus_getter_p2p_peer_level,
   3813 	  NULL,
   3814 	  NULL
   3815 	},
   3816 	{ "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
   3817 	  wpas_dbus_getter_p2p_peer_device_capability,
   3818 	  NULL,
   3819 	  NULL
   3820 	},
   3821 	{ "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
   3822 	  wpas_dbus_getter_p2p_peer_group_capability,
   3823 	  NULL,
   3824 	  NULL
   3825 	},
   3826 	{ "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
   3827 	  wpas_dbus_getter_p2p_peer_secondary_device_types,
   3828 	  NULL,
   3829 	  NULL
   3830 	},
   3831 	{ "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
   3832 	  wpas_dbus_getter_p2p_peer_vendor_extension,
   3833 	  NULL,
   3834 	  NULL
   3835 	},
   3836 	{ "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
   3837 	  wpas_dbus_getter_p2p_peer_ies,
   3838 	  NULL,
   3839 	  NULL
   3840 	},
   3841 	{ "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
   3842 	  wpas_dbus_getter_p2p_peer_device_address,
   3843 	  NULL,
   3844 	  NULL
   3845 	},
   3846 	{ "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
   3847 	  wpas_dbus_getter_p2p_peer_groups,
   3848 	  NULL,
   3849 	  NULL
   3850 	},
   3851 	{ NULL, NULL, NULL, NULL, NULL, NULL }
   3852 };
   3853 
   3854 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
   3855 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   3856 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
   3857 	  {
   3858 		  { "properties", "a{sv}", ARG_OUT },
   3859 		  END_ARGS
   3860 	  }
   3861 	},
   3862 	{ NULL, NULL, { END_ARGS } }
   3863 };
   3864 
   3865 /**
   3866  * wpas_dbus_signal_peer - Send a peer related event signal
   3867  * @wpa_s: %wpa_supplicant network interface data
   3868  * @dev: peer device object
   3869  * @interface: name of the interface emitting this signal.
   3870  *	In case of peer objects, it would be emitted by either
   3871  *	the "interface object" or by "peer objects"
   3872  * @sig_name: signal name - DeviceFound
   3873  * @properties: Whether to add a second argument with object properties
   3874  *
   3875  * Notify listeners about event related with p2p peer device
   3876  */
   3877 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
   3878 				  const u8 *dev_addr, const char *interface,
   3879 				  const char *sig_name, int properties)
   3880 {
   3881 	struct wpas_dbus_priv *iface;
   3882 	DBusMessage *msg;
   3883 	DBusMessageIter iter;
   3884 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   3885 
   3886 	if (wpa_s->p2p_mgmt)
   3887 		wpa_s = wpa_s->parent;
   3888 
   3889 	iface = wpa_s->global->dbus;
   3890 
   3891 	/* Do nothing if the control interface is not turned on */
   3892 	if (iface == NULL || !wpa_s->dbus_new_path)
   3893 		return;
   3894 
   3895 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3896 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   3897 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
   3898 
   3899 	msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
   3900 				      sig_name);
   3901 	if (msg == NULL)
   3902 		return;
   3903 
   3904 	dbus_message_iter_init_append(msg, &iter);
   3905 	path = peer_obj_path;
   3906 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   3907 					    &path) ||
   3908 	    (properties && !wpa_dbus_get_object_properties(
   3909 		    iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
   3910 		    &iter)))
   3911 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   3912 	else
   3913 		dbus_connection_send(iface->con, msg, NULL);
   3914 
   3915 	dbus_message_unref(msg);
   3916 }
   3917 
   3918 
   3919 /**
   3920  * wpas_dbus_signal_peer_found - Send a peer found signal
   3921  * @wpa_s: %wpa_supplicant network interface data
   3922  * @dev_addr: Peer P2P Device Address
   3923  *
   3924  * Notify listeners about find a p2p peer device found
   3925  */
   3926 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
   3927 					const u8 *dev_addr)
   3928 {
   3929 	wpas_dbus_signal_peer(wpa_s, dev_addr,
   3930 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3931 			      "DeviceFound", FALSE);
   3932 
   3933 	wpas_dbus_signal_peer(wpa_s, dev_addr,
   3934 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3935 			      "DeviceFoundProperties", TRUE);
   3936 }
   3937 
   3938 /**
   3939  * wpas_dbus_signal_peer_lost - Send a peer lost signal
   3940  * @wpa_s: %wpa_supplicant network interface data
   3941  * @dev_addr: Peer P2P Device Address
   3942  *
   3943  * Notify listeners about lost a p2p peer device
   3944  */
   3945 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
   3946 				       const u8 *dev_addr)
   3947 {
   3948 	wpas_dbus_signal_peer(wpa_s, dev_addr,
   3949 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3950 			      "DeviceLost", FALSE);
   3951 }
   3952 
   3953 /**
   3954  * wpas_dbus_register_peer - Register a discovered peer object with dbus
   3955  * @wpa_s: wpa_supplicant interface structure
   3956  * @dev_addr: P2P Device Address of the peer
   3957  * Returns: 0 on success, -1 on failure
   3958  *
   3959  * Registers network representing object with dbus
   3960  */
   3961 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
   3962 {
   3963 	struct wpas_dbus_priv *ctrl_iface;
   3964 	struct wpa_dbus_object_desc *obj_desc;
   3965 	struct peer_handler_args *arg;
   3966 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   3967 
   3968 	/* Do nothing if the control interface is not turned on */
   3969 	if (wpa_s == NULL || wpa_s->global == NULL)
   3970 		return 0;
   3971 
   3972 	ctrl_iface = wpa_s->global->dbus;
   3973 	if (ctrl_iface == NULL)
   3974 		return 0;
   3975 
   3976 	wpa_s = wpa_s->parent->parent;
   3977 	if (!wpa_s->dbus_new_path)
   3978 		return 0;
   3979 
   3980 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3981 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   3982 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
   3983 
   3984 	wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
   3985 		   peer_obj_path);
   3986 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   3987 	if (!obj_desc) {
   3988 		wpa_printf(MSG_ERROR,
   3989 			   "Not enough memory to create object description");
   3990 		goto err;
   3991 	}
   3992 
   3993 	/* allocate memory for handlers arguments */
   3994 	arg = os_zalloc(sizeof(struct peer_handler_args));
   3995 	if (!arg) {
   3996 		wpa_printf(MSG_ERROR,
   3997 			   "Not enough memory to create arguments for method");
   3998 		goto err;
   3999 	}
   4000 
   4001 	arg->wpa_s = wpa_s;
   4002 	os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
   4003 
   4004 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
   4005 			   NULL,
   4006 			   wpas_dbus_p2p_peer_properties,
   4007 			   wpas_dbus_p2p_peer_signals);
   4008 
   4009 	if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
   4010 					       wpa_s->ifname, obj_desc))
   4011 		goto err;
   4012 
   4013 	return 0;
   4014 
   4015 err:
   4016 	free_dbus_object_desc(obj_desc);
   4017 	return -1;
   4018 }
   4019 
   4020 /**
   4021  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
   4022  * @wpa_s: wpa_supplicant interface structure
   4023  * @dev_addr: p2p device addr
   4024  * Returns: 0 on success, -1 on failure
   4025  *
   4026  * Registers network representing object with dbus
   4027  */
   4028 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
   4029 				  const u8 *dev_addr)
   4030 {
   4031 	struct wpas_dbus_priv *ctrl_iface;
   4032 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   4033 	int ret;
   4034 
   4035 	/* Do nothing if the control interface is not turned on */
   4036 	if (wpa_s == NULL || wpa_s->global == NULL)
   4037 		return 0;
   4038 
   4039 	wpa_s = wpa_s->parent->parent;
   4040 	if (!wpa_s->dbus_new_path)
   4041 		return 0;
   4042 
   4043 	ctrl_iface = wpa_s->global->dbus;
   4044 	if (ctrl_iface == NULL)
   4045 		return 0;
   4046 
   4047 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   4048 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   4049 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
   4050 
   4051 	wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
   4052 		   peer_obj_path);
   4053 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
   4054 
   4055 	return ret;
   4056 }
   4057 
   4058 
   4059 /**
   4060  * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
   4061  * @wpa_s: %wpa_supplicant network interface data
   4062  *
   4063  * Notify listeners about P2P Find stopped
   4064  */
   4065 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
   4066 {
   4067 	struct wpas_dbus_priv *iface;
   4068 	DBusMessage *msg;
   4069 
   4070 	iface = wpa_s->global->dbus;
   4071 
   4072 	/* Do nothing if the control interface is not turned on */
   4073 	if (iface == NULL || !wpa_s->dbus_new_path)
   4074 		return;
   4075 
   4076 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   4077 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   4078 				      "FindStopped");
   4079 	if (msg == NULL)
   4080 		return;
   4081 
   4082 	dbus_connection_send(iface->con, msg, NULL);
   4083 
   4084 	dbus_message_unref(msg);
   4085 }
   4086 
   4087 
   4088 /**
   4089  * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
   4090  * @wpa_s: %wpa_supplicant network interface data
   4091  * @dev_addr: P2P Device Address
   4092  *
   4093  * Notify listeners about peer Groups property changes.
   4094  */
   4095 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
   4096 					  const u8 *dev_addr)
   4097 {
   4098 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   4099 
   4100 	if (wpa_s->p2p_mgmt)
   4101 		wpa_s = wpa_s->parent;
   4102 
   4103 	if (!wpa_s->dbus_new_path)
   4104 		return;
   4105 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   4106 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   4107 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
   4108 
   4109 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
   4110 				       WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
   4111 }
   4112 
   4113 
   4114 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
   4115 	{ "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
   4116 	  wpas_dbus_getter_p2p_group_members,
   4117 	  NULL,
   4118 	  NULL
   4119 	},
   4120 	{ "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
   4121 	  wpas_dbus_getter_p2p_group,
   4122 	  NULL,
   4123 	  NULL
   4124 	},
   4125 	{ "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
   4126 	  wpas_dbus_getter_p2p_role,
   4127 	  NULL,
   4128 	  NULL
   4129 	},
   4130 	{ "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
   4131 	  wpas_dbus_getter_p2p_group_ssid,
   4132 	  NULL,
   4133 	  NULL
   4134 	},
   4135 	{ "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
   4136 	  wpas_dbus_getter_p2p_group_bssid,
   4137 	  NULL,
   4138 	  NULL
   4139 	},
   4140 	{ "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
   4141 	  wpas_dbus_getter_p2p_group_frequency,
   4142 	  NULL,
   4143 	  NULL
   4144 	},
   4145 	{ "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
   4146 	  wpas_dbus_getter_p2p_group_passphrase,
   4147 	  NULL,
   4148 	  NULL
   4149 	},
   4150 	{ "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
   4151 	  wpas_dbus_getter_p2p_group_psk,
   4152 	  NULL,
   4153 	  NULL
   4154 	},
   4155 	{ "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
   4156 	  wpas_dbus_getter_p2p_group_vendor_ext,
   4157 	  wpas_dbus_setter_p2p_group_vendor_ext,
   4158 	  NULL
   4159 	},
   4160 	{ NULL, NULL, NULL, NULL, NULL, NULL }
   4161 };
   4162 
   4163 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
   4164 	{ "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
   4165 	  {
   4166 		  { "peer", "o", ARG_OUT },
   4167 		  END_ARGS
   4168 	  }
   4169 	},
   4170 	{ "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
   4171 	  {
   4172 		  { "peer", "o", ARG_OUT },
   4173 		  END_ARGS
   4174 	  }
   4175 	},
   4176 	{ NULL, NULL, { END_ARGS } }
   4177 };
   4178 
   4179 /**
   4180  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
   4181  * @wpa_s: wpa_supplicant interface structure
   4182  * @ssid: SSID struct
   4183  * Returns: 0 on success, -1 on failure
   4184  *
   4185  * Registers p2p group representing object with dbus
   4186  */
   4187 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
   4188 				  struct wpa_ssid *ssid)
   4189 {
   4190 	struct wpas_dbus_priv *ctrl_iface;
   4191 	struct wpa_dbus_object_desc *obj_desc;
   4192 	char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   4193 
   4194 	/* Do nothing if the control interface is not turned on */
   4195 	if (wpa_s == NULL || wpa_s->global == NULL)
   4196 		return;
   4197 
   4198 	ctrl_iface = wpa_s->global->dbus;
   4199 	if (ctrl_iface == NULL)
   4200 		return;
   4201 
   4202 	if (wpa_s->dbus_groupobj_path) {
   4203 		wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
   4204 			   __func__, wpa_s->dbus_groupobj_path);
   4205 		return;
   4206 	}
   4207 
   4208 	if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
   4209 		return;
   4210 
   4211 	wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
   4212 	if (wpa_s->dbus_groupobj_path == NULL)
   4213 		return;
   4214 
   4215 	wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
   4216 		   group_obj_path);
   4217 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   4218 	if (!obj_desc) {
   4219 		wpa_printf(MSG_ERROR,
   4220 			   "Not enough memory to create object description");
   4221 		goto err;
   4222 	}
   4223 
   4224 	wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
   4225 			   wpas_dbus_p2p_group_properties,
   4226 			   wpas_dbus_p2p_group_signals);
   4227 
   4228 	if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
   4229 					       wpa_s->ifname, obj_desc))
   4230 		goto err;
   4231 
   4232 	return;
   4233 
   4234 err:
   4235 	if (wpa_s->dbus_groupobj_path) {
   4236 		os_free(wpa_s->dbus_groupobj_path);
   4237 		wpa_s->dbus_groupobj_path = NULL;
   4238 	}
   4239 
   4240 	free_dbus_object_desc(obj_desc);
   4241 }
   4242 
   4243 /**
   4244  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
   4245  * @wpa_s: wpa_supplicant interface structure
   4246  * @ssid: network name of the p2p group started
   4247  */
   4248 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
   4249 				    const struct wpa_ssid *ssid)
   4250 {
   4251 	struct wpas_dbus_priv *ctrl_iface;
   4252 
   4253 	/* Do nothing if the control interface is not turned on */
   4254 	if (wpa_s == NULL || wpa_s->global == NULL)
   4255 		return;
   4256 
   4257 	if (wpa_s->p2p_mgmt)
   4258 		wpa_s = wpa_s->parent;
   4259 
   4260 	ctrl_iface = wpa_s->global->dbus;
   4261 	if (ctrl_iface == NULL)
   4262 		return;
   4263 
   4264 	if (!wpa_s->dbus_groupobj_path) {
   4265 		wpa_printf(MSG_DEBUG,
   4266 			   "%s: Group object '%s' already unregistered",
   4267 			   __func__, wpa_s->dbus_groupobj_path);
   4268 		return;
   4269 	}
   4270 
   4271 	peer_groups_changed(wpa_s);
   4272 
   4273 	wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
   4274 		   wpa_s->dbus_groupobj_path);
   4275 
   4276 	wpa_dbus_unregister_object_per_iface(ctrl_iface,
   4277 					     wpa_s->dbus_groupobj_path);
   4278 
   4279 	os_free(wpa_s->dbus_groupobj_path);
   4280 	wpa_s->dbus_groupobj_path = NULL;
   4281 }
   4282 
   4283 static const struct wpa_dbus_property_desc
   4284 	wpas_dbus_persistent_group_properties[] = {
   4285 	{ "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
   4286 	  wpas_dbus_getter_persistent_group_properties,
   4287 	  wpas_dbus_setter_persistent_group_properties,
   4288 	  NULL
   4289 	},
   4290 	{ NULL, NULL, NULL, NULL, NULL, NULL }
   4291 };
   4292 
   4293 /* No signals intended for persistent group objects */
   4294 
   4295 /**
   4296  * wpas_dbus_register_persistent_group - Register a configured(saved)
   4297  *	persistent group with dbus
   4298  * @wpa_s: wpa_supplicant interface structure
   4299  * @ssid: persistent group (still represented as a network within wpa)
   4300  *	  configuration data
   4301  * Returns: 0 on success, -1 on failure
   4302  *
   4303  * Registers a persistent group representing object with dbus.
   4304  */
   4305 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
   4306 					struct wpa_ssid *ssid)
   4307 {
   4308 	struct wpas_dbus_priv *ctrl_iface;
   4309 	struct wpa_dbus_object_desc *obj_desc;
   4310 	struct network_handler_args *arg;
   4311 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   4312 
   4313 	/* Do nothing if the control interface is not turned on */
   4314 	if (wpa_s == NULL || wpa_s->global == NULL)
   4315 		return 0;
   4316 	wpa_s = wpa_s->parent->parent;
   4317 	if (!wpa_s->dbus_new_path)
   4318 		return 0;
   4319 
   4320 	/* Make sure ssid is a persistent group */
   4321 	if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
   4322 		return -1; /* should we return w/o complaining? */
   4323 
   4324 	if (wpa_s->p2p_mgmt)
   4325 		wpa_s = wpa_s->parent;
   4326 
   4327 	ctrl_iface = wpa_s->global->dbus;
   4328 	if (ctrl_iface == NULL)
   4329 		return 0;
   4330 
   4331 	/*
   4332 	 * Intentionally not coming up with different numbering scheme
   4333 	 * for persistent groups.
   4334 	 */
   4335 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   4336 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
   4337 		    wpa_s->dbus_new_path, ssid->id);
   4338 
   4339 	wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
   4340 		   pgrp_obj_path);
   4341 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   4342 	if (!obj_desc) {
   4343 		wpa_printf(MSG_ERROR,
   4344 			   "dbus: Not enough memory to create object description");
   4345 		goto err;
   4346 	}
   4347 
   4348 	/*
   4349 	 * Reusing the same context structure as that for networks
   4350 	 * since these are represented using same data structure.
   4351 	 */
   4352 	/* allocate memory for handlers arguments */
   4353 	arg = os_zalloc(sizeof(struct network_handler_args));
   4354 	if (!arg) {
   4355 		wpa_printf(MSG_ERROR,
   4356 			   "dbus: Not enough memory to create arguments for method");
   4357 		goto err;
   4358 	}
   4359 
   4360 	arg->wpa_s = wpa_s;
   4361 	arg->ssid = ssid;
   4362 
   4363 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
   4364 			   wpas_dbus_persistent_group_properties,
   4365 			   NULL);
   4366 
   4367 	if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
   4368 					       wpa_s->ifname, obj_desc))
   4369 		goto err;
   4370 
   4371 	wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
   4372 
   4373 	return 0;
   4374 
   4375 err:
   4376 	free_dbus_object_desc(obj_desc);
   4377 	return -1;
   4378 }
   4379 
   4380 
   4381 /**
   4382  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
   4383  *	from dbus
   4384  * @wpa_s: wpa_supplicant interface structure
   4385  * @nid: network id
   4386  * Returns: 0 on success, -1 on failure
   4387  *
   4388  * Unregisters persistent group representing object from dbus
   4389  *
   4390  * NOTE: There is a slight issue with the semantics here. While the
   4391  * implementation simply means the persistent group is unloaded from memory,
   4392  * it should not get interpreted as the group is actually being erased/removed
   4393  * from persistent storage as well.
   4394  */
   4395 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
   4396 					  int nid)
   4397 {
   4398 	struct wpas_dbus_priv *ctrl_iface;
   4399 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   4400 	int ret;
   4401 
   4402 	/* Do nothing if the control interface is not turned on */
   4403 	if (wpa_s == NULL || wpa_s->global == NULL)
   4404 		return 0;
   4405 
   4406 	wpa_s = wpa_s->parent->parent;
   4407 
   4408 	ctrl_iface = wpa_s->global->dbus;
   4409 	if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
   4410 		return 0;
   4411 
   4412 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   4413 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
   4414 		    wpa_s->dbus_new_path, nid);
   4415 
   4416 	wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
   4417 		   pgrp_obj_path);
   4418 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
   4419 
   4420 	if (!ret)
   4421 		wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
   4422 
   4423 	return ret;
   4424 }
   4425 
   4426 #endif /* CONFIG_P2P */
   4427