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_close_write(&iter, &dict_iter))
    637 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    638 	else
    639 		dbus_connection_send(iface->con, msg, NULL);
    640 
    641 	dbus_message_unref(msg);
    642 }
    643 
    644 
    645 /**
    646  * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
    647  * @wpa_s: %wpa_supplicant network interface data
    648  * @m2d: M2D event data information
    649  *
    650  * Sends Event dbus signal with name "m2d" and dictionary containing
    651  * fields of wps_event_m2d structure.
    652  */
    653 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
    654 				    struct wps_event_m2d *m2d)
    655 {
    656 
    657 	DBusMessage *msg;
    658 	DBusMessageIter iter, dict_iter;
    659 	struct wpas_dbus_priv *iface;
    660 	char *key = "m2d";
    661 
    662 	iface = wpa_s->global->dbus;
    663 
    664 	/* Do nothing if the control interface is not turned on */
    665 	if (iface == NULL || !wpa_s->dbus_new_path)
    666 		return;
    667 
    668 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    669 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
    670 	if (msg == NULL)
    671 		return;
    672 
    673 	dbus_message_iter_init_append(msg, &iter);
    674 
    675 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
    676 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    677 	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
    678 					 m2d->config_methods) ||
    679 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
    680 					     (const char *) m2d->manufacturer,
    681 					     m2d->manufacturer_len) ||
    682 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
    683 					     (const char *) m2d->model_name,
    684 					     m2d->model_name_len) ||
    685 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
    686 					     (const char *) m2d->model_number,
    687 					     m2d->model_number_len) ||
    688 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
    689 					     (const char *)
    690 					     m2d->serial_number,
    691 					     m2d->serial_number_len) ||
    692 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
    693 					     (const char *) m2d->dev_name,
    694 					     m2d->dev_name_len) ||
    695 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
    696 					     (const char *)
    697 					     m2d->primary_dev_type, 8) ||
    698 	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
    699 					 m2d->config_error) ||
    700 	    !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
    701 					 m2d->dev_password_id) ||
    702 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    703 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    704 	else
    705 		dbus_connection_send(iface->con, msg, NULL);
    706 
    707 	dbus_message_unref(msg);
    708 }
    709 
    710 
    711 /**
    712  * wpas_dbus_signal_wps_cred - Signals new credentials
    713  * @wpa_s: %wpa_supplicant network interface data
    714  * @cred: WPS Credential information
    715  *
    716  * Sends signal with credentials in directory argument
    717  */
    718 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
    719 			       const struct wps_credential *cred)
    720 {
    721 	DBusMessage *msg;
    722 	DBusMessageIter iter, dict_iter;
    723 	struct wpas_dbus_priv *iface;
    724 	char *auth_type[5]; /* we have five possible authentication types */
    725 	int at_num = 0;
    726 	char *encr_type[3]; /* we have three possible encryption types */
    727 	int et_num = 0;
    728 
    729 	iface = wpa_s->global->dbus;
    730 
    731 	/* Do nothing if the control interface is not turned on */
    732 	if (iface == NULL || !wpa_s->dbus_new_path)
    733 		return;
    734 
    735 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    736 				      WPAS_DBUS_NEW_IFACE_WPS,
    737 				      "Credentials");
    738 	if (msg == NULL)
    739 		return;
    740 
    741 	dbus_message_iter_init_append(msg, &iter);
    742 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
    743 		goto nomem;
    744 
    745 	if (cred->auth_type & WPS_AUTH_OPEN)
    746 		auth_type[at_num++] = "open";
    747 	if (cred->auth_type & WPS_AUTH_WPAPSK)
    748 		auth_type[at_num++] = "wpa-psk";
    749 	if (cred->auth_type & WPS_AUTH_WPA)
    750 		auth_type[at_num++] = "wpa-eap";
    751 	if (cred->auth_type & WPS_AUTH_WPA2)
    752 		auth_type[at_num++] = "wpa2-eap";
    753 	if (cred->auth_type & WPS_AUTH_WPA2PSK)
    754 		auth_type[at_num++] = "wpa2-psk";
    755 
    756 	if (cred->encr_type & WPS_ENCR_NONE)
    757 		encr_type[et_num++] = "none";
    758 	if (cred->encr_type & WPS_ENCR_TKIP)
    759 		encr_type[et_num++] = "tkip";
    760 	if (cred->encr_type & WPS_ENCR_AES)
    761 		encr_type[et_num++] = "aes";
    762 
    763 	if ((wpa_s->current_ssid &&
    764 	     !wpa_dbus_dict_append_byte_array(
    765 		     &dict_iter, "BSSID",
    766 		     (const char *) wpa_s->current_ssid->bssid, ETH_ALEN)) ||
    767 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
    768 					     (const char *) cred->ssid,
    769 					     cred->ssid_len) ||
    770 	    !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
    771 					       (const char **) auth_type,
    772 					       at_num) ||
    773 	    !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
    774 					       (const char **) encr_type,
    775 					       et_num) ||
    776 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
    777 					     (const char *) cred->key,
    778 					     cred->key_len) ||
    779 	    !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
    780 					 cred->key_idx) ||
    781 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    782 		goto nomem;
    783 
    784 	dbus_connection_send(iface->con, msg, NULL);
    785 
    786 nomem:
    787 	dbus_message_unref(msg);
    788 }
    789 
    790 #endif /* CONFIG_WPS */
    791 
    792 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
    793 				    int depth, const char *subject,
    794 				    const char *altsubject[],
    795 				    int num_altsubject,
    796 				    const char *cert_hash,
    797 				    const struct wpabuf *cert)
    798 {
    799 	struct wpas_dbus_priv *iface;
    800 	DBusMessage *msg;
    801 	DBusMessageIter iter, dict_iter;
    802 
    803 	iface = wpa_s->global->dbus;
    804 
    805 	/* Do nothing if the control interface is not turned on */
    806 	if (iface == NULL || !wpa_s->dbus_new_path)
    807 		return;
    808 
    809 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    810 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    811 				      "Certification");
    812 	if (msg == NULL)
    813 		return;
    814 
    815 	dbus_message_iter_init_append(msg, &iter);
    816 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    817 	    !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
    818 	    !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) ||
    819 	    (altsubject && num_altsubject &&
    820 	     !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject",
    821 						altsubject, num_altsubject)) ||
    822 	    (cert_hash &&
    823 	     !wpa_dbus_dict_append_string(&dict_iter, "cert_hash",
    824 					  cert_hash)) ||
    825 	    (cert &&
    826 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
    827 					      wpabuf_head(cert),
    828 					      wpabuf_len(cert))) ||
    829 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    830 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    831 	else
    832 		dbus_connection_send(iface->con, msg, NULL);
    833 	dbus_message_unref(msg);
    834 }
    835 
    836 
    837 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
    838 				 const char *status, const char *parameter)
    839 {
    840 	struct wpas_dbus_priv *iface;
    841 	DBusMessage *msg;
    842 	DBusMessageIter iter;
    843 
    844 	iface = wpa_s->global->dbus;
    845 
    846 	/* Do nothing if the control interface is not turned on */
    847 	if (iface == NULL || !wpa_s->dbus_new_path)
    848 		return;
    849 
    850 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    851 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
    852 				      "EAP");
    853 	if (msg == NULL)
    854 		return;
    855 
    856 	dbus_message_iter_init_append(msg, &iter);
    857 
    858 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) ||
    859 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
    860 					    &parameter))
    861 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    862 	else
    863 		dbus_connection_send(iface->con, msg, NULL);
    864 	dbus_message_unref(msg);
    865 }
    866 
    867 
    868 /**
    869  * wpas_dbus_signal_sta - Send a station related event signal
    870  * @wpa_s: %wpa_supplicant network interface data
    871  * @sta: station mac address
    872  * @sig_name: signal name - StaAuthorized or StaDeauthorized
    873  *
    874  * Notify listeners about event related with station
    875  */
    876 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s,
    877 				 const u8 *sta, const char *sig_name)
    878 {
    879 	struct wpas_dbus_priv *iface;
    880 	DBusMessage *msg;
    881 	char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX];
    882 	char *dev_mac;
    883 
    884 	os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta));
    885 	dev_mac = sta_mac;
    886 
    887 	iface = wpa_s->global->dbus;
    888 
    889 	/* Do nothing if the control interface is not turned on */
    890 	if (iface == NULL || !wpa_s->dbus_new_path)
    891 		return;
    892 
    893 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
    894 				      WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
    895 	if (msg == NULL)
    896 		return;
    897 
    898 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac,
    899 				     DBUS_TYPE_INVALID))
    900 		dbus_connection_send(iface->con, msg, NULL);
    901 	else
    902 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    903 	dbus_message_unref(msg);
    904 
    905 	wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'",
    906 		   sta_mac, sig_name);
    907 }
    908 
    909 
    910 /**
    911  * wpas_dbus_signal_sta_authorized - Send a STA authorized signal
    912  * @wpa_s: %wpa_supplicant network interface data
    913  * @sta: station mac address
    914  *
    915  * Notify listeners a new station has been authorized
    916  */
    917 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
    918 				     const u8 *sta)
    919 {
    920 	wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized");
    921 }
    922 
    923 
    924 /**
    925  * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal
    926  * @wpa_s: %wpa_supplicant network interface data
    927  * @sta: station mac address
    928  *
    929  * Notify listeners a station has been deauthorized
    930  */
    931 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
    932 				       const u8 *sta)
    933 {
    934 	wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized");
    935 }
    936 
    937 
    938 #ifdef CONFIG_P2P
    939 
    940 /**
    941  * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
    942  * @wpa_s: %wpa_supplicant network interface data
    943  * @role: role of this device (client or GO)
    944  * Sends signal with i/f name and role as string arguments
    945  */
    946 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
    947 					const char *role)
    948 {
    949 	DBusMessage *msg;
    950 	DBusMessageIter iter, dict_iter;
    951 	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
    952 	struct wpa_supplicant *parent;
    953 
    954 	/* Do nothing if the control interface is not turned on */
    955 	if (iface == NULL)
    956 		return;
    957 
    958 	parent = wpa_s->parent;
    959 	if (parent->p2p_mgmt)
    960 		parent = parent->parent;
    961 
    962 	if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path ||
    963 	    !parent->dbus_new_path)
    964 		return;
    965 
    966 	msg = dbus_message_new_signal(parent->dbus_new_path,
    967 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
    968 				      "GroupFinished");
    969 	if (msg == NULL)
    970 		return;
    971 
    972 	dbus_message_iter_init_append(msg, &iter);
    973 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
    974 	    !wpa_dbus_dict_append_object_path(&dict_iter,
    975 					      "interface_object",
    976 					      wpa_s->dbus_new_path) ||
    977 	    !wpa_dbus_dict_append_string(&dict_iter, "role", role) ||
    978 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
    979 					      wpa_s->dbus_groupobj_path) ||
    980 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
    981 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
    982 	else
    983 		dbus_connection_send(iface->con, msg, NULL);
    984 	dbus_message_unref(msg);
    985 }
    986 
    987 
    988 /**
    989  * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
    990  *
    991  * @dev_addr - who sent the request or responded to our request.
    992  * @request - Will be 1 if request, 0 for response.
    993  * @status - valid only in case of response
    994  * @config_methods - wps config methods
    995  * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
    996  *
    997  * Sends following provision discovery related events:
    998  *	ProvisionDiscoveryRequestDisplayPin
    999  *	ProvisionDiscoveryResponseDisplayPin
   1000  *	ProvisionDiscoveryRequestEnterPin
   1001  *	ProvisionDiscoveryResponseEnterPin
   1002  *	ProvisionDiscoveryPBCRequest
   1003  *	ProvisionDiscoveryPBCResponse
   1004  *
   1005  *	TODO::
   1006  *	ProvisionDiscoveryFailure (timeout case)
   1007  */
   1008 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
   1009 					      const u8 *dev_addr, int request,
   1010 					      enum p2p_prov_disc_status status,
   1011 					      u16 config_methods,
   1012 					      unsigned int generated_pin)
   1013 {
   1014 	DBusMessage *msg;
   1015 	DBusMessageIter iter;
   1016 	struct wpas_dbus_priv *iface;
   1017 	char *_signal;
   1018 	int add_pin = 0;
   1019 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1020 	int error_ret = 1;
   1021 	char pin[9], *p_pin = NULL;
   1022 
   1023 	iface = wpa_s->global->dbus;
   1024 
   1025 	/* Do nothing if the control interface is not turned on */
   1026 	if (iface == NULL)
   1027 		return;
   1028 
   1029 	if (wpa_s->p2p_mgmt)
   1030 		wpa_s = wpa_s->parent;
   1031 	if (!wpa_s->dbus_new_path)
   1032 		return;
   1033 
   1034 	if (request || !status) {
   1035 		if (config_methods & WPS_CONFIG_DISPLAY)
   1036 			_signal = request ?
   1037 				 "ProvisionDiscoveryRequestDisplayPin" :
   1038 				 "ProvisionDiscoveryResponseEnterPin";
   1039 		else if (config_methods & WPS_CONFIG_KEYPAD)
   1040 			_signal = request ?
   1041 				 "ProvisionDiscoveryRequestEnterPin" :
   1042 				 "ProvisionDiscoveryResponseDisplayPin";
   1043 		else if (config_methods & WPS_CONFIG_PUSHBUTTON)
   1044 			_signal = request ? "ProvisionDiscoveryPBCRequest" :
   1045 				   "ProvisionDiscoveryPBCResponse";
   1046 		else
   1047 			return; /* Unknown or un-supported method */
   1048 	} else {
   1049 		/* Explicit check for failure response */
   1050 		_signal = "ProvisionDiscoveryFailure";
   1051 	}
   1052 
   1053 	add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
   1054 		   (!request && !status &&
   1055 			(config_methods & WPS_CONFIG_KEYPAD)));
   1056 
   1057 	if (add_pin) {
   1058 		os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
   1059 		p_pin = pin;
   1060 	}
   1061 
   1062 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1063 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
   1064 	if (msg == NULL)
   1065 		return;
   1066 
   1067 	/* Check if this is a known peer */
   1068 	if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
   1069 		goto error;
   1070 
   1071 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1072 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1073 			COMPACT_MACSTR,
   1074 			wpa_s->dbus_new_path, MAC2STR(dev_addr));
   1075 
   1076 	path = peer_obj_path;
   1077 
   1078 	dbus_message_iter_init_append(msg, &iter);
   1079 
   1080 	if (!dbus_message_iter_append_basic(&iter,
   1081 					    DBUS_TYPE_OBJECT_PATH,
   1082 					    &path))
   1083 			goto error;
   1084 
   1085 	if (!request && status)
   1086 		/* Attach status to ProvisionDiscoveryFailure */
   1087 		error_ret = !dbus_message_iter_append_basic(&iter,
   1088 						    DBUS_TYPE_INT32,
   1089 						    &status);
   1090 	else
   1091 		error_ret = (add_pin &&
   1092 				 !dbus_message_iter_append_basic(&iter,
   1093 							DBUS_TYPE_STRING,
   1094 							&p_pin));
   1095 
   1096 error:
   1097 	if (!error_ret)
   1098 		dbus_connection_send(iface->con, msg, NULL);
   1099 	else
   1100 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1101 
   1102 	dbus_message_unref(msg);
   1103 }
   1104 
   1105 
   1106 /**
   1107  * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX
   1108  * @wpa_s: %wpa_supplicant network interface data
   1109  * @src: Source address of the message triggering this notification
   1110  * @dev_passwd_id: WPS Device Password Id
   1111  * @go_intent: Peer's GO Intent value
   1112  *
   1113  * Sends signal to notify that a peer P2P Device is requesting group owner
   1114  * negotiation with us.
   1115  */
   1116 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
   1117 				     const u8 *src, u16 dev_passwd_id,
   1118 				     u8 go_intent)
   1119 {
   1120 	DBusMessage *msg;
   1121 	DBusMessageIter iter;
   1122 	struct wpas_dbus_priv *iface;
   1123 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1124 
   1125 	iface = wpa_s->global->dbus;
   1126 
   1127 	/* Do nothing if the control interface is not turned on */
   1128 	if (iface == NULL)
   1129 		return;
   1130 
   1131 	if (wpa_s->p2p_mgmt)
   1132 		wpa_s = wpa_s->parent;
   1133 	if (!wpa_s->dbus_new_path)
   1134 		return;
   1135 
   1136 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1137 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   1138 		    wpa_s->dbus_new_path, MAC2STR(src));
   1139 	path = peer_obj_path;
   1140 
   1141 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1142 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1143 				      "GONegotiationRequest");
   1144 	if (msg == NULL)
   1145 		return;
   1146 
   1147 	dbus_message_iter_init_append(msg, &iter);
   1148 
   1149 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   1150 					    &path) ||
   1151 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
   1152 					    &dev_passwd_id) ||
   1153 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
   1154 					    &go_intent))
   1155 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1156 	else
   1157 		dbus_connection_send(iface->con, msg, NULL);
   1158 
   1159 	dbus_message_unref(msg);
   1160 }
   1161 
   1162 
   1163 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
   1164 					const struct wpa_ssid *ssid,
   1165 					char *group_obj_path)
   1166 {
   1167 	char group_name[3];
   1168 
   1169 	if (!wpa_s->dbus_new_path ||
   1170 	    os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
   1171 		return -1;
   1172 
   1173 	os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
   1174 	group_name[2] = '\0';
   1175 
   1176 	os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1177 		    "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
   1178 		    wpa_s->dbus_new_path, group_name);
   1179 
   1180 	return 0;
   1181 }
   1182 
   1183 
   1184 struct group_changed_data {
   1185 	struct wpa_supplicant *wpa_s;
   1186 	struct p2p_peer_info *info;
   1187 };
   1188 
   1189 
   1190 static int match_group_where_peer_is_client(struct p2p_group *group,
   1191 					    void *user_data)
   1192 {
   1193 	struct group_changed_data *data = user_data;
   1194 	const struct p2p_group_config *cfg;
   1195 	struct wpa_supplicant *wpa_s_go;
   1196 
   1197 	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
   1198 		return 1;
   1199 
   1200 	cfg = p2p_group_get_config(group);
   1201 
   1202 	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
   1203 					 cfg->ssid_len);
   1204 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
   1205 		wpas_dbus_signal_peer_groups_changed(
   1206 			data->wpa_s->parent, data->info->p2p_device_addr);
   1207 		return 0;
   1208 	}
   1209 
   1210 	return 1;
   1211 }
   1212 
   1213 
   1214 static void signal_peer_groups_changed(struct p2p_peer_info *info,
   1215 				       void *user_data)
   1216 {
   1217 	struct group_changed_data *data = user_data;
   1218 	struct wpa_supplicant *wpa_s_go;
   1219 
   1220 	wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
   1221 					     info->p2p_device_addr);
   1222 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
   1223 		wpas_dbus_signal_peer_groups_changed(data->wpa_s->parent,
   1224 						     info->p2p_device_addr);
   1225 		return;
   1226 	}
   1227 
   1228 	data->info = info;
   1229 	p2p_loop_on_all_groups(data->wpa_s->global->p2p,
   1230 			       match_group_where_peer_is_client, data);
   1231 	data->info = NULL;
   1232 }
   1233 
   1234 
   1235 static void peer_groups_changed(struct wpa_supplicant *wpa_s)
   1236 {
   1237 	struct group_changed_data data;
   1238 
   1239 	os_memset(&data, 0, sizeof(data));
   1240 	data.wpa_s = wpa_s;
   1241 
   1242 	p2p_loop_on_known_peers(wpa_s->global->p2p,
   1243 				signal_peer_groups_changed, &data);
   1244 }
   1245 
   1246 
   1247 /**
   1248  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
   1249  * started. Emitted when a group is successfully started
   1250  * irrespective of the role (client/GO) of the current device
   1251  *
   1252  * @wpa_s: %wpa_supplicant network interface data
   1253  * @ssid: SSID object
   1254  * @client: this device is P2P client
   1255  * @network_id: network id of the group started, use instead of ssid->id
   1256  *	to account for persistent groups
   1257  */
   1258 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
   1259 					const struct wpa_ssid *ssid,
   1260 					int client, int network_id)
   1261 {
   1262 	DBusMessage *msg;
   1263 	DBusMessageIter iter, dict_iter;
   1264 	struct wpas_dbus_priv *iface;
   1265 	struct wpa_supplicant *parent;
   1266 
   1267 	parent = wpa_s->parent;
   1268 	if (parent->p2p_mgmt)
   1269 		parent = parent->parent;
   1270 
   1271 	iface = parent->global->dbus;
   1272 
   1273 	/* Do nothing if the control interface is not turned on */
   1274 	if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path)
   1275 		return;
   1276 
   1277 	if (wpa_s->dbus_groupobj_path == NULL)
   1278 		return;
   1279 
   1280 	/* New interface has been created for this group */
   1281 	msg = dbus_message_new_signal(parent->dbus_new_path,
   1282 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1283 				      "GroupStarted");
   1284 	if (msg == NULL)
   1285 		return;
   1286 
   1287 	dbus_message_iter_init_append(msg, &iter);
   1288 	/*
   1289 	 * In case the device supports creating a separate interface the
   1290 	 * DBus client will need to know the object path for the interface
   1291 	 * object this group was created on, so include it here.
   1292 	 */
   1293 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1294 	    !wpa_dbus_dict_append_object_path(&dict_iter,
   1295 					      "interface_object",
   1296 					      wpa_s->dbus_new_path) ||
   1297 	    !wpa_dbus_dict_append_string(&dict_iter, "role",
   1298 					 client ? "client" : "GO") ||
   1299 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
   1300 					      wpa_s->dbus_groupobj_path) ||
   1301 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
   1302 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1303 	} else {
   1304 		dbus_connection_send(iface->con, msg, NULL);
   1305 		if (client)
   1306 			peer_groups_changed(wpa_s);
   1307 	}
   1308 	dbus_message_unref(msg);
   1309 }
   1310 
   1311 
   1312 /**
   1313  * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal
   1314  * @wpa_s: %wpa_supplicant network interface data
   1315  * @res: Result of the GO Neg Request
   1316  */
   1317 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
   1318 				      struct p2p_go_neg_results *res)
   1319 {
   1320 	DBusMessage *msg;
   1321 	DBusMessageIter iter, dict_iter;
   1322 	DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
   1323 	struct wpas_dbus_priv *iface;
   1324 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1325 	dbus_int32_t freqs[P2P_MAX_CHANNELS];
   1326 	dbus_int32_t *f_array = freqs;
   1327 
   1328 
   1329 	iface = wpa_s->global->dbus;
   1330 
   1331 	if (wpa_s->p2p_mgmt)
   1332 		wpa_s = wpa_s->parent;
   1333 
   1334 	os_memset(freqs, 0, sizeof(freqs));
   1335 	/* Do nothing if the control interface is not turned on */
   1336 	if (iface == NULL || !wpa_s->dbus_new_path)
   1337 		return;
   1338 
   1339 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1340 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   1341 		    wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
   1342 	path = peer_obj_path;
   1343 
   1344 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1345 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1346 				      res->status ? "GONegotiationFailure" :
   1347 						    "GONegotiationSuccess");
   1348 	if (msg == NULL)
   1349 		return;
   1350 
   1351 	dbus_message_iter_init_append(msg, &iter);
   1352 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1353 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
   1354 					      path) ||
   1355 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
   1356 		goto err;
   1357 
   1358 	if (!res->status) {
   1359 		int i = 0;
   1360 		int freq_list_num = 0;
   1361 
   1362 		if ((res->role_go &&
   1363 		     !wpa_dbus_dict_append_string(&dict_iter, "passphrase",
   1364 						  res->passphrase)) ||
   1365 		    !wpa_dbus_dict_append_string(&dict_iter, "role_go",
   1366 						 res->role_go ? "GO" :
   1367 						 "client") ||
   1368 		    !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
   1369 						res->freq) ||
   1370 		    !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
   1371 						     (const char *) res->ssid,
   1372 						     res->ssid_len) ||
   1373 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
   1374 						     "peer_device_addr",
   1375 						     (const char *)
   1376 						     res->peer_device_addr,
   1377 						     ETH_ALEN) ||
   1378 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
   1379 						     "peer_interface_addr",
   1380 						     (const char *)
   1381 						     res->peer_interface_addr,
   1382 						     ETH_ALEN) ||
   1383 		    !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
   1384 						 p2p_wps_method_text(
   1385 							 res->wps_method)))
   1386 			goto err;
   1387 
   1388 		for (i = 0; i < P2P_MAX_CHANNELS; i++) {
   1389 			if (res->freq_list[i]) {
   1390 				freqs[i] = res->freq_list[i];
   1391 				freq_list_num++;
   1392 			}
   1393 		}
   1394 
   1395 		if (!wpa_dbus_dict_begin_array(&dict_iter,
   1396 					       "frequency_list",
   1397 					       DBUS_TYPE_INT32_AS_STRING,
   1398 					       &iter_dict_entry,
   1399 					       &iter_dict_val,
   1400 					       &iter_dict_array) ||
   1401 		    !dbus_message_iter_append_fixed_array(&iter_dict_array,
   1402 							  DBUS_TYPE_INT32,
   1403 							  &f_array,
   1404 							  freq_list_num) ||
   1405 		    !wpa_dbus_dict_end_array(&dict_iter,
   1406 					     &iter_dict_entry,
   1407 					     &iter_dict_val,
   1408 					     &iter_dict_array) ||
   1409 		    !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
   1410 						res->persistent_group) ||
   1411 		    !wpa_dbus_dict_append_uint32(&dict_iter,
   1412 						 "peer_config_timeout",
   1413 						 res->peer_config_timeout))
   1414 			goto err;
   1415 	}
   1416 
   1417 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
   1418 		goto err;
   1419 
   1420 	dbus_connection_send(iface->con, msg, NULL);
   1421 err:
   1422 	dbus_message_unref(msg);
   1423 }
   1424 
   1425 
   1426 /**
   1427  * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
   1428  * @wpa_s: %wpa_supplicant network interface data
   1429  * @status: Status of invitation process
   1430  * @bssid: Basic Service Set Identifier
   1431  */
   1432 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
   1433 					    int status, const u8 *bssid)
   1434 {
   1435 	DBusMessage *msg;
   1436 	DBusMessageIter iter, dict_iter;
   1437 	struct wpas_dbus_priv *iface;
   1438 
   1439 	wpa_printf(MSG_DEBUG, "%s", __func__);
   1440 
   1441 	iface = wpa_s->global->dbus;
   1442 	/* Do nothing if the control interface is not turned on */
   1443 	if (iface == NULL)
   1444 		return;
   1445 
   1446 	if (wpa_s->p2p_mgmt)
   1447 		wpa_s = wpa_s->parent;
   1448 	if (!wpa_s->dbus_new_path)
   1449 		return;
   1450 
   1451 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1452 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1453 				      "InvitationResult");
   1454 
   1455 	if (msg == NULL)
   1456 		return;
   1457 
   1458 	dbus_message_iter_init_append(msg, &iter);
   1459 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1460 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", status) ||
   1461 	    (bssid &&
   1462 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
   1463 					      (const char *) bssid,
   1464 					      ETH_ALEN)) ||
   1465 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   1466 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1467 	else
   1468 		dbus_connection_send(iface->con, msg, NULL);
   1469 	dbus_message_unref(msg);
   1470 }
   1471 
   1472 
   1473 /**
   1474  *
   1475  * Method to emit a signal for a peer joining the group.
   1476  * The signal will carry path to the group member object
   1477  * constructed using p2p i/f addr used for connecting.
   1478  *
   1479  * @wpa_s: %wpa_supplicant network interface data
   1480  * @peer_addr: P2P Device Address of the peer joining the group
   1481  */
   1482 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
   1483 				      const u8 *peer_addr)
   1484 {
   1485 	struct wpas_dbus_priv *iface;
   1486 	DBusMessage *msg;
   1487 	DBusMessageIter iter;
   1488 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1489 	struct wpa_supplicant *parent;
   1490 
   1491 	iface = wpa_s->global->dbus;
   1492 
   1493 	/* Do nothing if the control interface is not turned on */
   1494 	if (iface == NULL)
   1495 		return;
   1496 
   1497 	if (!wpa_s->dbus_groupobj_path)
   1498 		return;
   1499 
   1500 	parent = wpa_s->parent;
   1501 	if (parent->p2p_mgmt)
   1502 		parent = parent->parent;
   1503 	if (!parent->dbus_new_path)
   1504 		return;
   1505 
   1506 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1507 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1508 			COMPACT_MACSTR,
   1509 			parent->dbus_new_path, MAC2STR(peer_addr));
   1510 
   1511 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
   1512 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
   1513 				      "PeerJoined");
   1514 	if (msg == NULL)
   1515 		return;
   1516 
   1517 	dbus_message_iter_init_append(msg, &iter);
   1518 	path = peer_obj_path;
   1519 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   1520 					    &path)) {
   1521 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1522 	} else {
   1523 		dbus_connection_send(iface->con, msg, NULL);
   1524 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
   1525 	}
   1526 	dbus_message_unref(msg);
   1527 }
   1528 
   1529 
   1530 /**
   1531  *
   1532  * Method to emit a signal for a peer disconnecting the group.
   1533  * The signal will carry path to the group member object
   1534  * constructed using the P2P Device Address of the peer.
   1535  *
   1536  * @wpa_s: %wpa_supplicant network interface data
   1537  * @peer_addr: P2P Device Address of the peer joining the group
   1538  */
   1539 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
   1540 					    const u8 *peer_addr)
   1541 {
   1542 	struct wpas_dbus_priv *iface;
   1543 	DBusMessage *msg;
   1544 	DBusMessageIter iter;
   1545 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1546 	struct wpa_supplicant *parent;
   1547 
   1548 	iface = wpa_s->global->dbus;
   1549 
   1550 	/* Do nothing if the control interface is not turned on */
   1551 	if (iface == NULL)
   1552 		return;
   1553 
   1554 	if (!wpa_s->dbus_groupobj_path)
   1555 		return;
   1556 
   1557 	parent = wpa_s->parent;
   1558 	if (parent->p2p_mgmt)
   1559 		parent = parent->parent;
   1560 	if (!parent->dbus_new_path)
   1561 		return;
   1562 
   1563 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1564 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1565 			COMPACT_MACSTR,
   1566 			parent->dbus_new_path, MAC2STR(peer_addr));
   1567 
   1568 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
   1569 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
   1570 				      "PeerDisconnected");
   1571 	if (msg == NULL)
   1572 		return;
   1573 
   1574 	dbus_message_iter_init_append(msg, &iter);
   1575 	path = peer_obj_path;
   1576 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   1577 					    &path)) {
   1578 		wpa_printf(MSG_ERROR,
   1579 			   "dbus: Failed to construct PeerDisconnected signal");
   1580 	} else {
   1581 		dbus_connection_send(iface->con, msg, NULL);
   1582 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
   1583 	}
   1584 	dbus_message_unref(msg);
   1585 }
   1586 
   1587 
   1588 /**
   1589  *
   1590  * Method to emit a signal for a service discovery request.
   1591  * The signal will carry station address, frequency, dialog token,
   1592  * update indicator and it tlvs
   1593  *
   1594  * @wpa_s: %wpa_supplicant network interface data
   1595  * @sa: station addr (p2p i/f) of the peer
   1596  * @dialog_token: service discovery request dialog token
   1597  * @update_indic: service discovery request update indicator
   1598  * @tlvs: service discovery request genrated byte array of tlvs
   1599  * @tlvs_len: service discovery request tlvs length
   1600  */
   1601 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
   1602 				     int freq, const u8 *sa, u8 dialog_token,
   1603 				     u16 update_indic, const u8 *tlvs,
   1604 				     size_t tlvs_len)
   1605 {
   1606 	DBusMessage *msg;
   1607 	DBusMessageIter iter, dict_iter;
   1608 	struct wpas_dbus_priv *iface;
   1609 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1610 
   1611 	iface = wpa_s->global->dbus;
   1612 
   1613 	/* Do nothing if the control interface is not turned on */
   1614 	if (iface == NULL)
   1615 		return;
   1616 
   1617 	if (wpa_s->p2p_mgmt)
   1618 		wpa_s = wpa_s->parent;
   1619 	if (!wpa_s->dbus_new_path)
   1620 		return;
   1621 
   1622 	/* Check if this is a known peer */
   1623 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
   1624 		return;
   1625 
   1626 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1627 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1628 				      "ServiceDiscoveryRequest");
   1629 	if (msg == NULL)
   1630 		return;
   1631 
   1632 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1633 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1634 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
   1635 
   1636 	path = peer_obj_path;
   1637 
   1638 	dbus_message_iter_init_append(msg, &iter);
   1639 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1640 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
   1641 					      path) ||
   1642 	    !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
   1643 	    !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
   1644 					dialog_token) ||
   1645 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
   1646 					 update_indic) ||
   1647 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
   1648 					     (const char *) tlvs,
   1649 					     tlvs_len) ||
   1650 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   1651 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1652 	else
   1653 		dbus_connection_send(iface->con, msg, NULL);
   1654 	dbus_message_unref(msg);
   1655 }
   1656 
   1657 
   1658 /**
   1659  *
   1660  * Method to emit a signal for a service discovery response.
   1661  * The signal will carry station address, update indicator and it
   1662  * tlvs
   1663  *
   1664  * @wpa_s: %wpa_supplicant network interface data
   1665  * @sa: station addr (p2p i/f) of the peer
   1666  * @update_indic: service discovery request update indicator
   1667  * @tlvs: service discovery request genrated byte array of tlvs
   1668  * @tlvs_len: service discovery request tlvs length
   1669  */
   1670 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
   1671 				      const u8 *sa, u16 update_indic,
   1672 				      const u8 *tlvs, size_t tlvs_len)
   1673 {
   1674 	DBusMessage *msg;
   1675 	DBusMessageIter iter, dict_iter;
   1676 	struct wpas_dbus_priv *iface;
   1677 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1678 
   1679 	iface = wpa_s->global->dbus;
   1680 
   1681 	/* Do nothing if the control interface is not turned on */
   1682 	if (iface == NULL)
   1683 		return;
   1684 
   1685 	if (wpa_s->p2p_mgmt)
   1686 		wpa_s = wpa_s->parent;
   1687 	if (!wpa_s->dbus_new_path)
   1688 		return;
   1689 
   1690 	/* Check if this is a known peer */
   1691 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
   1692 		return;
   1693 
   1694 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1695 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1696 				      "ServiceDiscoveryResponse");
   1697 	if (msg == NULL)
   1698 		return;
   1699 
   1700 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1701 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
   1702 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
   1703 
   1704 	path = peer_obj_path;
   1705 
   1706 	dbus_message_iter_init_append(msg, &iter);
   1707 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1708 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
   1709 					      path) ||
   1710 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
   1711 					 update_indic) ||
   1712 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
   1713 					     (const char *) tlvs,
   1714 					     tlvs_len) ||
   1715 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   1716 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1717 	else
   1718 		dbus_connection_send(iface->con, msg, NULL);
   1719 	dbus_message_unref(msg);
   1720 }
   1721 
   1722 
   1723 /**
   1724  * wpas_dbus_signal_persistent_group - Send a persistent group related
   1725  *	event signal
   1726  * @wpa_s: %wpa_supplicant network interface data
   1727  * @id: new persistent group id
   1728  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
   1729  * @properties: determines if add second argument with object properties
   1730  *
   1731  * Notify listeners about an event related to persistent groups.
   1732  */
   1733 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
   1734 					      int id, const char *sig_name,
   1735 					      int properties)
   1736 {
   1737 	struct wpas_dbus_priv *iface;
   1738 	DBusMessage *msg;
   1739 	DBusMessageIter iter;
   1740 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   1741 
   1742 	iface = wpa_s->global->dbus;
   1743 
   1744 	/* Do nothing if the control interface is not turned on */
   1745 	if (iface == NULL)
   1746 		return;
   1747 
   1748 	if (wpa_s->p2p_mgmt)
   1749 		wpa_s = wpa_s->parent;
   1750 	if (!wpa_s->dbus_new_path)
   1751 		return;
   1752 
   1753 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   1754 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
   1755 		    wpa_s->dbus_new_path, id);
   1756 
   1757 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1758 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1759 				      sig_name);
   1760 	if (msg == NULL)
   1761 		return;
   1762 
   1763 	dbus_message_iter_init_append(msg, &iter);
   1764 	path = pgrp_obj_path;
   1765 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   1766 					    &path) ||
   1767 	    (properties &&
   1768 	     !wpa_dbus_get_object_properties(
   1769 		     iface, pgrp_obj_path,
   1770 		     WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
   1771 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1772 	else
   1773 		dbus_connection_send(iface->con, msg, NULL);
   1774 
   1775 	dbus_message_unref(msg);
   1776 }
   1777 
   1778 
   1779 /**
   1780  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
   1781  *	added signal
   1782  * @wpa_s: %wpa_supplicant network interface data
   1783  * @id: new persistent group id
   1784  *
   1785  * Notify listeners about addition of a new persistent group.
   1786  */
   1787 static void wpas_dbus_signal_persistent_group_added(
   1788 	struct wpa_supplicant *wpa_s, int id)
   1789 {
   1790 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
   1791 					  TRUE);
   1792 }
   1793 
   1794 
   1795 /**
   1796  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
   1797  *	removed signal
   1798  * @wpa_s: %wpa_supplicant network interface data
   1799  * @id: persistent group id
   1800  *
   1801  * Notify listeners about removal of a persistent group.
   1802  */
   1803 static void wpas_dbus_signal_persistent_group_removed(
   1804 	struct wpa_supplicant *wpa_s, int id)
   1805 {
   1806 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
   1807 					  FALSE);
   1808 }
   1809 
   1810 
   1811 /**
   1812  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
   1813  * @wpa_s: %wpa_supplicant network interface data
   1814  * @fail: WPS failure information
   1815  *
   1816  * Sends Event dbus signal with name "fail" and dictionary containing
   1817  * "msg" field with fail message number (int32) as arguments
   1818  */
   1819 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
   1820 				     struct wps_event_fail *fail)
   1821 {
   1822 
   1823 	DBusMessage *msg;
   1824 	DBusMessageIter iter, dict_iter;
   1825 	struct wpas_dbus_priv *iface;
   1826 	char *key = "fail";
   1827 
   1828 	iface = wpa_s->global->dbus;
   1829 
   1830 	/* Do nothing if the control interface is not turned on */
   1831 	if (iface == NULL)
   1832 		return;
   1833 
   1834 	if (wpa_s->p2p_mgmt)
   1835 		wpa_s = wpa_s->parent;
   1836 
   1837 	if (!wpa_s->dbus_new_path)
   1838 		return;
   1839 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   1840 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   1841 				      "WpsFailed");
   1842 	if (msg == NULL)
   1843 		return;
   1844 
   1845 	dbus_message_iter_init_append(msg, &iter);
   1846 
   1847 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
   1848 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
   1849 	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
   1850 	    !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
   1851 					fail->config_error) ||
   1852 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
   1853 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   1854 	else
   1855 		dbus_connection_send(iface->con, msg, NULL);
   1856 
   1857 	dbus_message_unref(msg);
   1858 }
   1859 
   1860 #endif /* CONFIG_P2P */
   1861 
   1862 
   1863 /**
   1864  * wpas_dbus_signal_prop_changed - Signals change of property
   1865  * @wpa_s: %wpa_supplicant network interface data
   1866  * @property: indicates which property has changed
   1867  *
   1868  * Sends PropertyChanged signals with path, interface and arguments
   1869  * depending on which property has changed.
   1870  */
   1871 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
   1872 				   enum wpas_dbus_prop property)
   1873 {
   1874 	char *prop;
   1875 	dbus_bool_t flush;
   1876 
   1877 	if (wpa_s->dbus_new_path == NULL)
   1878 		return; /* Skip signal since D-Bus setup is not yet ready */
   1879 
   1880 	flush = FALSE;
   1881 	switch (property) {
   1882 	case WPAS_DBUS_PROP_AP_SCAN:
   1883 		prop = "ApScan";
   1884 		break;
   1885 	case WPAS_DBUS_PROP_SCANNING:
   1886 		prop = "Scanning";
   1887 		break;
   1888 	case WPAS_DBUS_PROP_STATE:
   1889 		prop = "State";
   1890 		break;
   1891 	case WPAS_DBUS_PROP_CURRENT_BSS:
   1892 		prop = "CurrentBSS";
   1893 		break;
   1894 	case WPAS_DBUS_PROP_CURRENT_NETWORK:
   1895 		prop = "CurrentNetwork";
   1896 		break;
   1897 	case WPAS_DBUS_PROP_BSSS:
   1898 		prop = "BSSs";
   1899 		break;
   1900 	case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
   1901 		prop = "CurrentAuthMode";
   1902 		break;
   1903 	case WPAS_DBUS_PROP_DISCONNECT_REASON:
   1904 		prop = "DisconnectReason";
   1905 		flush = TRUE;
   1906 		break;
   1907 	default:
   1908 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
   1909 			   __func__, property);
   1910 		return;
   1911 	}
   1912 
   1913 	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
   1914 				       wpa_s->dbus_new_path,
   1915 				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
   1916 	if (flush) {
   1917 		wpa_dbus_flush_object_changed_properties(
   1918 			wpa_s->global->dbus->con, wpa_s->dbus_new_path);
   1919 	}
   1920 }
   1921 
   1922 
   1923 /**
   1924  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
   1925  * @wpa_s: %wpa_supplicant network interface data
   1926  * @property: indicates which property has changed
   1927  * @id: unique BSS identifier
   1928  *
   1929  * Sends PropertyChanged signals with path, interface, and arguments depending
   1930  * on which property has changed.
   1931  */
   1932 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
   1933 				       enum wpas_dbus_bss_prop property,
   1934 				       unsigned int id)
   1935 {
   1936 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
   1937 	char *prop;
   1938 
   1939 	if (!wpa_s->dbus_new_path)
   1940 		return;
   1941 
   1942 	switch (property) {
   1943 	case WPAS_DBUS_BSS_PROP_SIGNAL:
   1944 		prop = "Signal";
   1945 		break;
   1946 	case WPAS_DBUS_BSS_PROP_FREQ:
   1947 		prop = "Frequency";
   1948 		break;
   1949 	case WPAS_DBUS_BSS_PROP_MODE:
   1950 		prop = "Mode";
   1951 		break;
   1952 	case WPAS_DBUS_BSS_PROP_PRIVACY:
   1953 		prop = "Privacy";
   1954 		break;
   1955 	case WPAS_DBUS_BSS_PROP_RATES:
   1956 		prop = "Rates";
   1957 		break;
   1958 	case WPAS_DBUS_BSS_PROP_WPA:
   1959 		prop = "WPA";
   1960 		break;
   1961 	case WPAS_DBUS_BSS_PROP_RSN:
   1962 		prop = "RSN";
   1963 		break;
   1964 	case WPAS_DBUS_BSS_PROP_WPS:
   1965 		prop = "WPS";
   1966 		break;
   1967 	case WPAS_DBUS_BSS_PROP_IES:
   1968 		prop = "IEs";
   1969 		break;
   1970 	case WPAS_DBUS_BSS_PROP_AGE:
   1971 		prop = "Age";
   1972 		break;
   1973 	default:
   1974 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
   1975 			   __func__, property);
   1976 		return;
   1977 	}
   1978 
   1979 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
   1980 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
   1981 		    wpa_s->dbus_new_path, id);
   1982 
   1983 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
   1984 				       WPAS_DBUS_NEW_IFACE_BSS, prop);
   1985 }
   1986 
   1987 
   1988 /**
   1989  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
   1990  * @global: wpa_global structure
   1991  *
   1992  * Sends PropertyChanged signals informing that debug level has changed.
   1993  */
   1994 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
   1995 {
   1996 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
   1997 				       WPAS_DBUS_NEW_INTERFACE,
   1998 				       "DebugLevel");
   1999 }
   2000 
   2001 
   2002 /**
   2003  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
   2004  * @global: wpa_global structure
   2005  *
   2006  * Sends PropertyChanged signals informing that debug timestamp has changed.
   2007  */
   2008 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
   2009 {
   2010 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
   2011 				       WPAS_DBUS_NEW_INTERFACE,
   2012 				       "DebugTimestamp");
   2013 }
   2014 
   2015 
   2016 /**
   2017  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
   2018  * @global: wpa_global structure
   2019  *
   2020  * Sends PropertyChanged signals informing that debug show_keys has changed.
   2021  */
   2022 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
   2023 {
   2024 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
   2025 				       WPAS_DBUS_NEW_INTERFACE,
   2026 				       "DebugShowKeys");
   2027 }
   2028 
   2029 
   2030 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
   2031 			       void *priv,
   2032 			       WPADBusArgumentFreeFunction priv_free,
   2033 			       const struct wpa_dbus_method_desc *methods,
   2034 			       const struct wpa_dbus_property_desc *properties,
   2035 			       const struct wpa_dbus_signal_desc *signals)
   2036 {
   2037 	int n;
   2038 
   2039 	obj_desc->user_data = priv;
   2040 	obj_desc->user_data_free_func = priv_free;
   2041 	obj_desc->methods = methods;
   2042 	obj_desc->properties = properties;
   2043 	obj_desc->signals = signals;
   2044 
   2045 	for (n = 0; properties && properties->dbus_property; properties++)
   2046 		n++;
   2047 
   2048 	obj_desc->prop_changed_flags = os_zalloc(n);
   2049 	if (!obj_desc->prop_changed_flags)
   2050 		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
   2051 			   __func__);
   2052 }
   2053 
   2054 
   2055 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
   2056 	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
   2057 	  (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
   2058 	  {
   2059 		  { "args", "a{sv}", ARG_IN },
   2060 		  { "path", "o", ARG_OUT },
   2061 		  END_ARGS
   2062 	  }
   2063 	},
   2064 	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
   2065 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
   2066 	  {
   2067 		  { "path", "o", ARG_IN },
   2068 		  END_ARGS
   2069 	  }
   2070 	},
   2071 	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
   2072 	  (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
   2073 	  {
   2074 		  { "ifname", "s", ARG_IN },
   2075 		  { "path", "o", ARG_OUT },
   2076 		  END_ARGS
   2077 	  }
   2078 	},
   2079 	{ NULL, NULL, NULL, { END_ARGS } }
   2080 };
   2081 
   2082 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
   2083 	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
   2084 	  wpas_dbus_getter_debug_level,
   2085 	  wpas_dbus_setter_debug_level
   2086 	},
   2087 	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
   2088 	  wpas_dbus_getter_debug_timestamp,
   2089 	  wpas_dbus_setter_debug_timestamp
   2090 	},
   2091 	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
   2092 	  wpas_dbus_getter_debug_show_keys,
   2093 	  wpas_dbus_setter_debug_show_keys
   2094 	},
   2095 	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
   2096 	  wpas_dbus_getter_interfaces,
   2097 	  NULL
   2098 	},
   2099 	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
   2100 	  wpas_dbus_getter_eap_methods,
   2101 	  NULL
   2102 	},
   2103 	{ "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
   2104 	  wpas_dbus_getter_global_capabilities,
   2105 	  NULL
   2106 	},
   2107 #ifdef CONFIG_WIFI_DISPLAY
   2108 	{ "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
   2109 	  wpas_dbus_getter_global_wfd_ies,
   2110 	  wpas_dbus_setter_global_wfd_ies
   2111 	},
   2112 #endif /* CONFIG_WIFI_DISPLAY */
   2113 	{ NULL, NULL, NULL, NULL, NULL }
   2114 };
   2115 
   2116 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
   2117 	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
   2118 	  {
   2119 		  { "path", "o", ARG_OUT },
   2120 		  { "properties", "a{sv}", ARG_OUT },
   2121 		  END_ARGS
   2122 	  }
   2123 	},
   2124 	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
   2125 	  {
   2126 		  { "path", "o", ARG_OUT },
   2127 		  END_ARGS
   2128 	  }
   2129 	},
   2130 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   2131 	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
   2132 	  {
   2133 		  { "properties", "a{sv}", ARG_OUT },
   2134 		  END_ARGS
   2135 	  }
   2136 	},
   2137 	{ NULL, NULL, { END_ARGS } }
   2138 };
   2139 
   2140 
   2141 /**
   2142  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
   2143  * @global: Pointer to global data from wpa_supplicant_init()
   2144  * Returns: 0 on success or -1 on failure
   2145  *
   2146  * Initialize the dbus control interface for wpa_supplicantand and start
   2147  * receiving commands from external programs over the bus.
   2148  */
   2149 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
   2150 {
   2151 	struct wpa_dbus_object_desc *obj_desc;
   2152 	int ret;
   2153 
   2154 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   2155 	if (!obj_desc) {
   2156 		wpa_printf(MSG_ERROR,
   2157 			   "Not enough memory to create object description");
   2158 		return -1;
   2159 	}
   2160 
   2161 	wpas_dbus_register(obj_desc, priv->global, NULL,
   2162 			   wpas_dbus_global_methods,
   2163 			   wpas_dbus_global_properties,
   2164 			   wpas_dbus_global_signals);
   2165 
   2166 	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
   2167 		   WPAS_DBUS_NEW_PATH);
   2168 	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
   2169 				       WPAS_DBUS_NEW_SERVICE,
   2170 				       obj_desc);
   2171 	if (ret < 0)
   2172 		free_dbus_object_desc(obj_desc);
   2173 	else
   2174 		priv->dbus_new_initialized = 1;
   2175 
   2176 	return ret;
   2177 }
   2178 
   2179 
   2180 /**
   2181  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
   2182  * wpa_supplicant
   2183  * @iface: Pointer to dbus private data from wpas_dbus_init()
   2184  *
   2185  * Deinitialize the dbus control interface that was initialized with
   2186  * wpas_dbus_ctrl_iface_init().
   2187  */
   2188 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
   2189 {
   2190 	if (!iface->dbus_new_initialized)
   2191 		return;
   2192 	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
   2193 		   WPAS_DBUS_NEW_PATH);
   2194 	dbus_connection_unregister_object_path(iface->con,
   2195 					       WPAS_DBUS_NEW_PATH);
   2196 }
   2197 
   2198 
   2199 static void wpa_dbus_free(void *ptr)
   2200 {
   2201 	os_free(ptr);
   2202 }
   2203 
   2204 
   2205 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
   2206 	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
   2207 	  wpas_dbus_getter_network_properties,
   2208 	  wpas_dbus_setter_network_properties
   2209 	},
   2210 	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
   2211 	  wpas_dbus_getter_enabled,
   2212 	  wpas_dbus_setter_enabled
   2213 	},
   2214 	{ NULL, NULL, NULL, NULL, NULL }
   2215 };
   2216 
   2217 
   2218 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
   2219 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   2220 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
   2221 	  {
   2222 		  { "properties", "a{sv}", ARG_OUT },
   2223 		  END_ARGS
   2224 	  }
   2225 	},
   2226 	{ NULL, NULL, { END_ARGS } }
   2227 };
   2228 
   2229 
   2230 /**
   2231  * wpas_dbus_register_network - Register a configured network with dbus
   2232  * @wpa_s: wpa_supplicant interface structure
   2233  * @ssid: network configuration data
   2234  * Returns: 0 on success, -1 on failure
   2235  *
   2236  * Registers network representing object with dbus
   2237  */
   2238 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
   2239 			       struct wpa_ssid *ssid)
   2240 {
   2241 	struct wpas_dbus_priv *ctrl_iface;
   2242 	struct wpa_dbus_object_desc *obj_desc;
   2243 	struct network_handler_args *arg;
   2244 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   2245 
   2246 #ifdef CONFIG_P2P
   2247 	/*
   2248 	 * If it is a persistent group register it as such.
   2249 	 * This is to handle cases where an interface is being initialized
   2250 	 * with a list of networks read from config.
   2251 	 */
   2252 	if (network_is_persistent_group(ssid))
   2253 		return wpas_dbus_register_persistent_group(wpa_s, ssid);
   2254 #endif /* CONFIG_P2P */
   2255 
   2256 	/* Do nothing if the control interface is not turned on */
   2257 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
   2258 		return 0;
   2259 	ctrl_iface = wpa_s->global->dbus;
   2260 	if (ctrl_iface == NULL)
   2261 		return 0;
   2262 
   2263 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   2264 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
   2265 		    wpa_s->dbus_new_path, ssid->id);
   2266 
   2267 	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
   2268 		   net_obj_path);
   2269 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   2270 	if (!obj_desc) {
   2271 		wpa_printf(MSG_ERROR,
   2272 			   "Not enough memory to create object description");
   2273 		goto err;
   2274 	}
   2275 
   2276 	/* allocate memory for handlers arguments */
   2277 	arg = os_zalloc(sizeof(struct network_handler_args));
   2278 	if (!arg) {
   2279 		wpa_printf(MSG_ERROR,
   2280 			   "Not enough memory to create arguments for method");
   2281 		goto err;
   2282 	}
   2283 
   2284 	arg->wpa_s = wpa_s;
   2285 	arg->ssid = ssid;
   2286 
   2287 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
   2288 			   wpas_dbus_network_properties,
   2289 			   wpas_dbus_network_signals);
   2290 
   2291 	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
   2292 					       wpa_s->ifname, obj_desc))
   2293 		goto err;
   2294 
   2295 	wpas_dbus_signal_network_added(wpa_s, ssid->id);
   2296 
   2297 	return 0;
   2298 
   2299 err:
   2300 	free_dbus_object_desc(obj_desc);
   2301 	return -1;
   2302 }
   2303 
   2304 
   2305 /**
   2306  * wpas_dbus_unregister_network - Unregister a configured network from dbus
   2307  * @wpa_s: wpa_supplicant interface structure
   2308  * @nid: network id
   2309  * Returns: 0 on success, -1 on failure
   2310  *
   2311  * Unregisters network representing object from dbus
   2312  */
   2313 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
   2314 {
   2315 	struct wpas_dbus_priv *ctrl_iface;
   2316 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   2317 	int ret;
   2318 #ifdef CONFIG_P2P
   2319 	struct wpa_ssid *ssid;
   2320 
   2321 	ssid = wpa_config_get_network(wpa_s->conf, nid);
   2322 
   2323 	/* If it is a persistent group unregister it as such */
   2324 	if (ssid && network_is_persistent_group(ssid))
   2325 		return wpas_dbus_unregister_persistent_group(wpa_s, nid);
   2326 #endif /* CONFIG_P2P */
   2327 
   2328 	/* Do nothing if the control interface is not turned on */
   2329 	if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
   2330 		return 0;
   2331 	ctrl_iface = wpa_s->global->dbus;
   2332 	if (ctrl_iface == NULL)
   2333 		return 0;
   2334 
   2335 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   2336 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
   2337 		    wpa_s->dbus_new_path, nid);
   2338 
   2339 	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
   2340 		   net_obj_path);
   2341 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
   2342 
   2343 	if (!ret)
   2344 		wpas_dbus_signal_network_removed(wpa_s, nid);
   2345 
   2346 	return ret;
   2347 }
   2348 
   2349 
   2350 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
   2351 	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
   2352 	  wpas_dbus_getter_bss_ssid,
   2353 	  NULL
   2354 	},
   2355 	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
   2356 	  wpas_dbus_getter_bss_bssid,
   2357 	  NULL
   2358 	},
   2359 	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
   2360 	  wpas_dbus_getter_bss_privacy,
   2361 	  NULL
   2362 	},
   2363 	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
   2364 	  wpas_dbus_getter_bss_mode,
   2365 	  NULL
   2366 	},
   2367 	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
   2368 	  wpas_dbus_getter_bss_signal,
   2369 	  NULL
   2370 	},
   2371 	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
   2372 	  wpas_dbus_getter_bss_frequency,
   2373 	  NULL
   2374 	},
   2375 	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
   2376 	  wpas_dbus_getter_bss_rates,
   2377 	  NULL
   2378 	},
   2379 	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
   2380 	  wpas_dbus_getter_bss_wpa,
   2381 	  NULL
   2382 	},
   2383 	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
   2384 	  wpas_dbus_getter_bss_rsn,
   2385 	  NULL
   2386 	},
   2387 	{ "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
   2388 	  wpas_dbus_getter_bss_wps,
   2389 	  NULL
   2390 	},
   2391 	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
   2392 	  wpas_dbus_getter_bss_ies,
   2393 	  NULL
   2394 	},
   2395 	{ "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
   2396 	  wpas_dbus_getter_bss_age,
   2397 	  NULL
   2398 	},
   2399 	{ NULL, NULL, NULL, NULL, NULL }
   2400 };
   2401 
   2402 
   2403 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
   2404 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   2405 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
   2406 	  {
   2407 		  { "properties", "a{sv}", ARG_OUT },
   2408 		  END_ARGS
   2409 	  }
   2410 	},
   2411 	{ NULL, NULL, { END_ARGS } }
   2412 };
   2413 
   2414 
   2415 /**
   2416  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
   2417  * @wpa_s: wpa_supplicant interface structure
   2418  * @bssid: scanned network bssid
   2419  * @id: unique BSS identifier
   2420  * Returns: 0 on success, -1 on failure
   2421  *
   2422  * Unregisters BSS representing object from dbus
   2423  */
   2424 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
   2425 			     u8 bssid[ETH_ALEN], unsigned int id)
   2426 {
   2427 	struct wpas_dbus_priv *ctrl_iface;
   2428 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   2429 
   2430 	/* Do nothing if the control interface is not turned on */
   2431 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
   2432 		return 0;
   2433 	ctrl_iface = wpa_s->global->dbus;
   2434 	if (ctrl_iface == NULL)
   2435 		return 0;
   2436 
   2437 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   2438 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
   2439 		    wpa_s->dbus_new_path, id);
   2440 
   2441 	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
   2442 		   bss_obj_path);
   2443 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
   2444 		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
   2445 			   bss_obj_path);
   2446 		return -1;
   2447 	}
   2448 
   2449 	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
   2450 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
   2451 
   2452 	return 0;
   2453 }
   2454 
   2455 
   2456 /**
   2457  * wpas_dbus_register_bss - Register a scanned BSS with dbus
   2458  * @wpa_s: wpa_supplicant interface structure
   2459  * @bssid: scanned network bssid
   2460  * @id: unique BSS identifier
   2461  * Returns: 0 on success, -1 on failure
   2462  *
   2463  * Registers BSS representing object with dbus
   2464  */
   2465 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
   2466 			   u8 bssid[ETH_ALEN], unsigned int id)
   2467 {
   2468 	struct wpas_dbus_priv *ctrl_iface;
   2469 	struct wpa_dbus_object_desc *obj_desc;
   2470 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   2471 	struct bss_handler_args *arg;
   2472 
   2473 	/* Do nothing if the control interface is not turned on */
   2474 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
   2475 		return 0;
   2476 	ctrl_iface = wpa_s->global->dbus;
   2477 	if (ctrl_iface == NULL)
   2478 		return 0;
   2479 
   2480 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   2481 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
   2482 		    wpa_s->dbus_new_path, id);
   2483 
   2484 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   2485 	if (!obj_desc) {
   2486 		wpa_printf(MSG_ERROR,
   2487 			   "Not enough memory to create object description");
   2488 		goto err;
   2489 	}
   2490 
   2491 	arg = os_zalloc(sizeof(struct bss_handler_args));
   2492 	if (!arg) {
   2493 		wpa_printf(MSG_ERROR,
   2494 			   "Not enough memory to create arguments for handler");
   2495 		goto err;
   2496 	}
   2497 	arg->wpa_s = wpa_s;
   2498 	arg->id = id;
   2499 
   2500 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
   2501 			   wpas_dbus_bss_properties,
   2502 			   wpas_dbus_bss_signals);
   2503 
   2504 	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
   2505 		   bss_obj_path);
   2506 	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
   2507 					       wpa_s->ifname, obj_desc)) {
   2508 		wpa_printf(MSG_ERROR,
   2509 			   "Cannot register BSSID dbus object %s.",
   2510 			   bss_obj_path);
   2511 		goto err;
   2512 	}
   2513 
   2514 	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
   2515 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
   2516 
   2517 	return 0;
   2518 
   2519 err:
   2520 	free_dbus_object_desc(obj_desc);
   2521 	return -1;
   2522 }
   2523 
   2524 
   2525 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
   2526 	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2527 	  (WPADBusMethodHandler) wpas_dbus_handler_scan,
   2528 	  {
   2529 		  { "args", "a{sv}", ARG_IN },
   2530 		  END_ARGS
   2531 	  }
   2532 	},
   2533 	{ "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2534 	  (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
   2535 	  {
   2536 		  { "args", "a{sv}", ARG_OUT },
   2537 		  END_ARGS
   2538 	  }
   2539 	},
   2540 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2541 	  (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
   2542 	  {
   2543 		  END_ARGS
   2544 	  }
   2545 	},
   2546 	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2547 	  (WPADBusMethodHandler) wpas_dbus_handler_add_network,
   2548 	  {
   2549 		  { "args", "a{sv}", ARG_IN },
   2550 		  { "path", "o", ARG_OUT },
   2551 		  END_ARGS
   2552 	  }
   2553 	},
   2554 	{ "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2555 	  (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
   2556 	  {
   2557 		  END_ARGS
   2558 	  }
   2559 	},
   2560 	{ "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2561 	  (WPADBusMethodHandler) wpas_dbus_handler_reattach,
   2562 	  {
   2563 		  END_ARGS
   2564 	  }
   2565 	},
   2566 	{ "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2567 	  (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
   2568 	  {
   2569 		  END_ARGS
   2570 	  }
   2571 	},
   2572 	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2573 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
   2574 	  {
   2575 		  { "path", "o", ARG_IN },
   2576 		  END_ARGS
   2577 	  }
   2578 	},
   2579 	{ "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2580 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
   2581 	  {
   2582 		  END_ARGS
   2583 	  }
   2584 	},
   2585 	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2586 	  (WPADBusMethodHandler) wpas_dbus_handler_select_network,
   2587 	  {
   2588 		  { "path", "o", ARG_IN },
   2589 		  END_ARGS
   2590 	  }
   2591 	},
   2592 	{ "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2593 	  (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
   2594 	  {
   2595 		  { "path", "o", ARG_IN },
   2596 		  { "field", "s", ARG_IN },
   2597 		  { "value", "s", ARG_IN },
   2598 		  END_ARGS
   2599 	  }
   2600 	},
   2601 #ifndef CONFIG_NO_CONFIG_BLOBS
   2602 	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2603 	  (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
   2604 	  {
   2605 		  { "name", "s", ARG_IN },
   2606 		  { "data", "ay", ARG_IN },
   2607 		  END_ARGS
   2608 	  }
   2609 	},
   2610 	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2611 	  (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
   2612 	  {
   2613 		  { "name", "s", ARG_IN },
   2614 		  { "data", "ay", ARG_OUT },
   2615 		  END_ARGS
   2616 	  }
   2617 	},
   2618 	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2619 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
   2620 	  {
   2621 		  { "name", "s", ARG_IN },
   2622 		  END_ARGS
   2623 	  }
   2624 	},
   2625 #endif /* CONFIG_NO_CONFIG_BLOBS */
   2626 	{ "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2627 	  (WPADBusMethodHandler)
   2628 	  wpas_dbus_handler_set_pkcs11_engine_and_module_path,
   2629 	  {
   2630 		  { "pkcs11_engine_path", "s", ARG_IN },
   2631 		  { "pkcs11_module_path", "s", ARG_IN },
   2632 		  END_ARGS
   2633 	  }
   2634 	},
   2635 #ifdef CONFIG_WPS
   2636 	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
   2637 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
   2638 	  {
   2639 		  { "args", "a{sv}", ARG_IN },
   2640 		  { "output", "a{sv}", ARG_OUT },
   2641 		  END_ARGS
   2642 	  }
   2643 	},
   2644 	{ "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
   2645 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
   2646 	  {
   2647 		  END_ARGS
   2648 	  }
   2649 	},
   2650 #endif /* CONFIG_WPS */
   2651 #ifdef CONFIG_P2P
   2652 	{ "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2653 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
   2654 	  {
   2655 		  { "args", "a{sv}", ARG_IN },
   2656 		  END_ARGS
   2657 	  }
   2658 	},
   2659 	{ "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2660 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
   2661 	  {
   2662 		  END_ARGS
   2663 	  }
   2664 	},
   2665 	{ "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2666 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
   2667 	  {
   2668 		  { "timeout", "i", ARG_IN },
   2669 		  END_ARGS
   2670 	  }
   2671 	},
   2672 	{ "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2673 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
   2674 	  {
   2675 		  { "args", "a{sv}", ARG_IN },
   2676 		  END_ARGS
   2677 	  }
   2678 	},
   2679 	{ "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2680 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
   2681 	  {
   2682 		  { "args", "a{sv}", ARG_IN },
   2683 		  END_ARGS
   2684 	  }
   2685 	},
   2686 	{ "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2687 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
   2688 	  {
   2689 		  { "peer", "o", ARG_IN },
   2690 		  { "config_method", "s", ARG_IN },
   2691 		  END_ARGS
   2692 	  }
   2693 	},
   2694 	{ "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2695 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
   2696 	  {
   2697 		  { "args", "a{sv}", ARG_IN },
   2698 		  { "generated_pin", "s", ARG_OUT },
   2699 		  END_ARGS
   2700 	  }
   2701 	},
   2702 	{ "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2703 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
   2704 	  {
   2705 		  { "args", "a{sv}", ARG_IN },
   2706 		  END_ARGS
   2707 	  }
   2708 	},
   2709 	{ "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2710 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
   2711 	  {
   2712 		  END_ARGS
   2713 	  }
   2714 	},
   2715 	{ "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2716 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
   2717 	  {
   2718 		  { "args", "a{sv}", ARG_IN },
   2719 		  END_ARGS
   2720 	  }
   2721 	},
   2722 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2723 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
   2724 	  {
   2725 		  END_ARGS
   2726 	  }
   2727 	},
   2728 	{ "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2729 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
   2730 	  {
   2731 		  { "peer", "o", ARG_IN },
   2732 		  END_ARGS
   2733 	  }
   2734 	},
   2735 	{ "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2736 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
   2737 	  {
   2738 		  { "args", "a{sv}", ARG_IN },
   2739 		  END_ARGS
   2740 	  }
   2741 	},
   2742 	{ "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2743 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
   2744 	  {
   2745 		  END_ARGS
   2746 	  }
   2747 	},
   2748 	{ "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2749 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
   2750 	  {
   2751 		  { "args", "a{sv}", ARG_IN },
   2752 		  END_ARGS
   2753 	  }
   2754 	},
   2755 	{ "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2756 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
   2757 	  {
   2758 		  { "args", "a{sv}", ARG_IN },
   2759 		  END_ARGS
   2760 	  }
   2761 	},
   2762 	{ "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2763 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
   2764 	  {
   2765 		  END_ARGS
   2766 	  }
   2767 	},
   2768 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2769 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
   2770 	  {
   2771 		  { "args", "a{sv}", ARG_IN },
   2772 		  { "ref", "t", ARG_OUT },
   2773 		  END_ARGS
   2774 	  }
   2775 	},
   2776 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2777 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
   2778 	  {
   2779 		  { "args", "a{sv}", ARG_IN },
   2780 		  END_ARGS
   2781 	  }
   2782 	},
   2783 	{ "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2784 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
   2785 	  {
   2786 		  { "args", "t", ARG_IN },
   2787 		  END_ARGS
   2788 	  }
   2789 	},
   2790 	{ "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2791 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
   2792 	  {
   2793 		  END_ARGS
   2794 	  }
   2795 	},
   2796 	{ "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2797 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
   2798 	  {
   2799 		  { "arg", "i", ARG_IN },
   2800 		  END_ARGS
   2801 	  }
   2802 	},
   2803 	{ "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2804 	  (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
   2805 	  {
   2806 		  { "args", "a{sv}", ARG_IN },
   2807 		  { "path", "o", ARG_OUT },
   2808 		  END_ARGS
   2809 	  }
   2810 	},
   2811 	{ "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2812 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
   2813 	  {
   2814 		  { "path", "o", ARG_IN },
   2815 		  END_ARGS
   2816 	  }
   2817 	},
   2818 	{ "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   2819 	  (WPADBusMethodHandler)
   2820 	  wpas_dbus_handler_remove_all_persistent_groups,
   2821 	  {
   2822 		  END_ARGS
   2823 	  }
   2824 	},
   2825 #endif /* CONFIG_P2P */
   2826 	{ "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2827 	  (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
   2828 	  {
   2829 		  { "age", "u", ARG_IN },
   2830 		  END_ARGS
   2831 	  }
   2832 	},
   2833 #ifdef CONFIG_AP
   2834 	{ "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2835 	  (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
   2836 	  {
   2837 		  END_ARGS
   2838 	  }
   2839 	},
   2840 	{ "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2841 	  (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
   2842 	  {
   2843 		  END_ARGS
   2844 	  }
   2845 	},
   2846 #endif /* CONFIG_AP */
   2847 	{ "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2848 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
   2849 	  {
   2850 		  END_ARGS
   2851 	  }
   2852 	},
   2853 	{ "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2854 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
   2855 	  {
   2856 		  END_ARGS
   2857 	  }
   2858 	},
   2859 #ifdef CONFIG_AUTOSCAN
   2860 	{ "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2861 	  (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
   2862 	  {
   2863 		  { "arg", "s", ARG_IN },
   2864 		  END_ARGS
   2865 	  }
   2866 	},
   2867 #endif /* CONFIG_AUTOSCAN */
   2868 #ifdef CONFIG_TDLS
   2869 	{ "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2870 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
   2871 	  {
   2872 		  { "peer_address", "s", ARG_IN },
   2873 		  END_ARGS
   2874 	  }
   2875 	},
   2876 	{ "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2877 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
   2878 	  {
   2879 		  { "peer_address", "s", ARG_IN },
   2880 		  END_ARGS
   2881 	  }
   2882 	},
   2883 	{ "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2884 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
   2885 	  {
   2886 		  { "peer_address", "s", ARG_IN },
   2887 		  { "status", "s", ARG_OUT },
   2888 		  END_ARGS
   2889 	  }
   2890 	},
   2891 	{ "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
   2892 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
   2893 	  {
   2894 		  { "peer_address", "s", ARG_IN },
   2895 		  END_ARGS
   2896 	  }
   2897 	},
   2898 #endif /* CONFIG_TDLS */
   2899 	{ NULL, NULL, NULL, { END_ARGS } }
   2900 };
   2901 
   2902 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
   2903 	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
   2904 	  wpas_dbus_getter_capabilities,
   2905 	  NULL
   2906 	},
   2907 	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   2908 	  wpas_dbus_getter_state,
   2909 	  NULL
   2910 	},
   2911 	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
   2912 	  wpas_dbus_getter_scanning,
   2913 	  NULL
   2914 	},
   2915 	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
   2916 	  wpas_dbus_getter_ap_scan,
   2917 	  wpas_dbus_setter_ap_scan
   2918 	},
   2919 	{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
   2920 	  wpas_dbus_getter_bss_expire_age,
   2921 	  wpas_dbus_setter_bss_expire_age
   2922 	},
   2923 	{ "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
   2924 	  wpas_dbus_getter_bss_expire_count,
   2925 	  wpas_dbus_setter_bss_expire_count
   2926 	},
   2927 	{ "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   2928 	  wpas_dbus_getter_country,
   2929 	  wpas_dbus_setter_country
   2930 	},
   2931 	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   2932 	  wpas_dbus_getter_ifname,
   2933 	  NULL
   2934 	},
   2935 	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   2936 	  wpas_dbus_getter_driver,
   2937 	  NULL
   2938 	},
   2939 	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   2940 	  wpas_dbus_getter_bridge_ifname,
   2941 	  NULL
   2942 	},
   2943 	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
   2944 	  wpas_dbus_getter_current_bss,
   2945 	  NULL
   2946 	},
   2947 	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
   2948 	  wpas_dbus_getter_current_network,
   2949 	  NULL
   2950 	},
   2951 	{ "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   2952 	  wpas_dbus_getter_current_auth_mode,
   2953 	  NULL
   2954 	},
   2955 	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
   2956 	  wpas_dbus_getter_blobs,
   2957 	  NULL
   2958 	},
   2959 	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
   2960 	  wpas_dbus_getter_bsss,
   2961 	  NULL
   2962 	},
   2963 	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
   2964 	  wpas_dbus_getter_networks,
   2965 	  NULL
   2966 	},
   2967 	{ "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
   2968 	  wpas_dbus_getter_fast_reauth,
   2969 	  wpas_dbus_setter_fast_reauth
   2970 	},
   2971 	{ "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
   2972 	  wpas_dbus_getter_scan_interval,
   2973 	  wpas_dbus_setter_scan_interval
   2974 	},
   2975 	{ "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   2976 	  wpas_dbus_getter_pkcs11_engine_path,
   2977 	  NULL
   2978 	},
   2979 	{ "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
   2980 	  wpas_dbus_getter_pkcs11_module_path,
   2981 	  NULL
   2982 	},
   2983 #ifdef CONFIG_WPS
   2984 	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
   2985 	  wpas_dbus_getter_process_credentials,
   2986 	  wpas_dbus_setter_process_credentials
   2987 	},
   2988 	{ "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
   2989 	  wpas_dbus_getter_config_methods,
   2990 	  wpas_dbus_setter_config_methods
   2991 	},
   2992 #endif /* CONFIG_WPS */
   2993 #ifdef CONFIG_P2P
   2994 	{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
   2995 	  wpas_dbus_getter_p2p_device_config,
   2996 	  wpas_dbus_setter_p2p_device_config
   2997 	},
   2998 	{ "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
   2999 	  wpas_dbus_getter_p2p_peers,
   3000 	  NULL
   3001 	},
   3002 	{ "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
   3003 	  wpas_dbus_getter_p2p_role,
   3004 	  NULL
   3005 	},
   3006 	{ "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
   3007 	  wpas_dbus_getter_p2p_group,
   3008 	  NULL
   3009 	},
   3010 	{ "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
   3011 	  wpas_dbus_getter_p2p_peergo,
   3012 	  NULL
   3013 	},
   3014 	{ "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
   3015 	  wpas_dbus_getter_persistent_groups,
   3016 	  NULL
   3017 	},
   3018 #endif /* CONFIG_P2P */
   3019 	{ "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
   3020 	  wpas_dbus_getter_disconnect_reason,
   3021 	  NULL
   3022 	},
   3023 	{ NULL, NULL, NULL, NULL, NULL }
   3024 };
   3025 
   3026 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
   3027 	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3028 	  {
   3029 		  { "success", "b", ARG_OUT },
   3030 		  END_ARGS
   3031 	  }
   3032 	},
   3033 	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3034 	  {
   3035 		  { "path", "o", ARG_OUT },
   3036 		  { "properties", "a{sv}", ARG_OUT },
   3037 		  END_ARGS
   3038 	  }
   3039 	},
   3040 	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3041 	  {
   3042 		  { "path", "o", ARG_OUT },
   3043 		  END_ARGS
   3044 	  }
   3045 	},
   3046 	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3047 	  {
   3048 		  { "name", "s", ARG_OUT },
   3049 		  END_ARGS
   3050 	  }
   3051 	},
   3052 	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3053 	  {
   3054 		  { "name", "s", ARG_OUT },
   3055 		  END_ARGS
   3056 	  }
   3057 	},
   3058 	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3059 	  {
   3060 		  { "path", "o", ARG_OUT },
   3061 		  { "properties", "a{sv}", ARG_OUT },
   3062 		  END_ARGS
   3063 	  }
   3064 	},
   3065 	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3066 	  {
   3067 		  { "path", "o", ARG_OUT },
   3068 		  END_ARGS
   3069 	  }
   3070 	},
   3071 	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3072 	  {
   3073 		  { "path", "o", ARG_OUT },
   3074 		  END_ARGS
   3075 	  }
   3076 	},
   3077 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   3078 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3079 	  {
   3080 		  { "properties", "a{sv}", ARG_OUT },
   3081 		  END_ARGS
   3082 	  }
   3083 	},
   3084 #ifdef CONFIG_WPS
   3085 	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
   3086 	  {
   3087 		  { "name", "s", ARG_OUT },
   3088 		  { "args", "a{sv}", ARG_OUT },
   3089 		  END_ARGS
   3090 	  }
   3091 	},
   3092 	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
   3093 	  {
   3094 		  { "credentials", "a{sv}", ARG_OUT },
   3095 		  END_ARGS
   3096 	  }
   3097 	},
   3098 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   3099 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
   3100 	  {
   3101 		  { "properties", "a{sv}", ARG_OUT },
   3102 		  END_ARGS
   3103 	  }
   3104 	},
   3105 #endif /* CONFIG_WPS */
   3106 #ifdef CONFIG_P2P
   3107 	{ "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3108 	  {
   3109 		  { "path", "o", ARG_OUT },
   3110 		  END_ARGS
   3111 	  }
   3112 	},
   3113 	{ "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3114 	  {
   3115 		  { "path", "o", ARG_OUT },
   3116 		  END_ARGS
   3117 	  }
   3118 	},
   3119 	{ "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3120 	  {
   3121 		  END_ARGS
   3122 	  }
   3123 	},
   3124 	{ "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3125 	  {
   3126 		  { "peer_object", "o", ARG_OUT },
   3127 		  { "pin", "s", ARG_OUT },
   3128 		  END_ARGS
   3129 	  }
   3130 	},
   3131 	{ "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3132 	  {
   3133 		  { "peer_object", "o", ARG_OUT },
   3134 		  { "pin", "s", ARG_OUT },
   3135 		  END_ARGS
   3136 	  }
   3137 	},
   3138 	{ "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3139 	  {
   3140 		  { "peer_object", "o", ARG_OUT },
   3141 		  END_ARGS
   3142 	  }
   3143 	},
   3144 	{ "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3145 	  {
   3146 		  { "peer_object", "o", ARG_OUT },
   3147 		  END_ARGS
   3148 	  }
   3149 	},
   3150 	{ "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3151 	  {
   3152 		  { "peer_object", "o", ARG_OUT },
   3153 		  END_ARGS
   3154 	  }
   3155 	},
   3156 	{ "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3157 	  {
   3158 		  { "peer_object", "o", ARG_OUT },
   3159 		  END_ARGS
   3160 	  }
   3161 	},
   3162 	{ "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3163 	  {
   3164 		  { "peer_object", "o", ARG_OUT },
   3165 		  { "status", "i", ARG_OUT },
   3166 		  END_ARGS
   3167 	  }
   3168 	},
   3169 	{ "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3170 	  {
   3171 		  { "properties", "a{sv}", ARG_OUT },
   3172 		  END_ARGS
   3173 	  }
   3174 	},
   3175 	{ "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3176 	  {
   3177 		  { "properties", "a{sv}", ARG_OUT },
   3178 		  END_ARGS
   3179 	  }
   3180 	},
   3181 	{ "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3182 	  {
   3183 		  { "properties", "a{sv}", ARG_OUT },
   3184 		  END_ARGS
   3185 	  }
   3186 	},
   3187 	{ "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3188 	  {
   3189 		  { "path", "o", ARG_OUT },
   3190 		  { "dev_passwd_id", "i", ARG_OUT },
   3191 		  { "device_go_intent", "y", ARG_OUT },
   3192 		  END_ARGS
   3193 	  }
   3194 	},
   3195 	{ "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3196 	  {
   3197 		  { "invite_result", "a{sv}", ARG_OUT },
   3198 		  END_ARGS
   3199 	  }
   3200 	},
   3201 	{ "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3202 	  {
   3203 		  { "properties", "a{sv}", ARG_OUT },
   3204 		  END_ARGS
   3205 	  }
   3206 	},
   3207 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3208 	  {
   3209 		  { "sd_request", "a{sv}", ARG_OUT },
   3210 		  END_ARGS
   3211 	  }
   3212 	},
   3213 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3214 	  {
   3215 		  { "sd_response", "a{sv}", ARG_OUT },
   3216 		  END_ARGS
   3217 	  }
   3218 	},
   3219 	{ "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3220 	  {
   3221 		  { "path", "o", ARG_OUT },
   3222 		  { "properties", "a{sv}", ARG_OUT },
   3223 		  END_ARGS
   3224 	  }
   3225 	},
   3226 	{ "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3227 	  {
   3228 		  { "path", "o", ARG_OUT },
   3229 		  END_ARGS
   3230 	  }
   3231 	},
   3232 	{ "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3233 	  {
   3234 		  { "name", "s", ARG_OUT },
   3235 		  { "args", "a{sv}", ARG_OUT },
   3236 		  END_ARGS
   3237 	  }
   3238 	},
   3239 #endif /* CONFIG_P2P */
   3240 #ifdef CONFIG_AP
   3241 	{ "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3242 	  {
   3243 		  { "args", "a{sv}", ARG_OUT },
   3244 		  END_ARGS
   3245 	  }
   3246 	},
   3247 #endif /* CONFIG_AP */
   3248 	{ "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3249 	  {
   3250 		  { "certification", "a{sv}", ARG_OUT },
   3251 		  END_ARGS
   3252 	  }
   3253 	},
   3254 	{ "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3255 	  {
   3256 		  { "status", "s", ARG_OUT },
   3257 		  { "parameter", "s", ARG_OUT },
   3258 		  END_ARGS
   3259 	  }
   3260 	},
   3261 	{ "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3262 	  {
   3263 		  { "name", "s", ARG_OUT },
   3264 		  END_ARGS
   3265 	  }
   3266 	},
   3267 	{ "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3268 	  {
   3269 		  { "name", "s", ARG_OUT },
   3270 		  END_ARGS
   3271 	  }
   3272 	},
   3273 	{ "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
   3274 	  {
   3275 		  { "path", "o", ARG_OUT },
   3276 		  { "field", "s", ARG_OUT },
   3277 		  { "text", "s", ARG_OUT },
   3278 		  END_ARGS
   3279 	  }
   3280 	},
   3281 	{ NULL, NULL, { END_ARGS } }
   3282 };
   3283 
   3284 
   3285 /**
   3286  * wpas_dbus_register_interface - Register an interface with D-Bus
   3287  * @wpa_s: wpa_supplicant interface structure
   3288  * Returns: 0 on success, -1 on failure
   3289  */
   3290 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
   3291 {
   3292 
   3293 	struct wpa_dbus_object_desc *obj_desc = NULL;
   3294 	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
   3295 	int next;
   3296 
   3297 	/* Do nothing if the control interface is not turned on */
   3298 	if (ctrl_iface == NULL)
   3299 		return 0;
   3300 
   3301 	/* Create and set the interface's object path */
   3302 	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
   3303 	if (wpa_s->dbus_new_path == NULL)
   3304 		return -1;
   3305 	next = ctrl_iface->next_objid++;
   3306 	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3307 		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
   3308 		    next);
   3309 
   3310 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   3311 	if (!obj_desc) {
   3312 		wpa_printf(MSG_ERROR,
   3313 			   "Not enough memory to create object description");
   3314 		goto err;
   3315 	}
   3316 
   3317 	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
   3318 			   wpas_dbus_interface_properties,
   3319 			   wpas_dbus_interface_signals);
   3320 
   3321 	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
   3322 		   wpa_s->dbus_new_path);
   3323 	if (wpa_dbus_register_object_per_iface(ctrl_iface,
   3324 					       wpa_s->dbus_new_path,
   3325 					       wpa_s->ifname, obj_desc))
   3326 		goto err;
   3327 
   3328 	wpas_dbus_signal_interface_added(wpa_s);
   3329 
   3330 	return 0;
   3331 
   3332 err:
   3333 	os_free(wpa_s->dbus_new_path);
   3334 	wpa_s->dbus_new_path = NULL;
   3335 	free_dbus_object_desc(obj_desc);
   3336 	return -1;
   3337 }
   3338 
   3339 
   3340 /**
   3341  * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
   3342  * @wpa_s: wpa_supplicant interface structure
   3343  * Returns: 0 on success, -1 on failure
   3344  */
   3345 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
   3346 {
   3347 	struct wpas_dbus_priv *ctrl_iface;
   3348 
   3349 	/* Do nothing if the control interface is not turned on */
   3350 	if (wpa_s == NULL || wpa_s->global == NULL)
   3351 		return 0;
   3352 	ctrl_iface = wpa_s->global->dbus;
   3353 	if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
   3354 		return 0;
   3355 
   3356 	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
   3357 		   wpa_s->dbus_new_path);
   3358 
   3359 #ifdef CONFIG_AP
   3360 	if (wpa_s->preq_notify_peer) {
   3361 		wpas_dbus_unsubscribe_noc(ctrl_iface);
   3362 		os_free(wpa_s->preq_notify_peer);
   3363 		wpa_s->preq_notify_peer = NULL;
   3364 	}
   3365 #endif /* CONFIG_AP */
   3366 
   3367 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
   3368 						 wpa_s->dbus_new_path))
   3369 		return -1;
   3370 
   3371 	wpas_dbus_signal_interface_removed(wpa_s);
   3372 
   3373 	os_free(wpa_s->dbus_new_path);
   3374 	wpa_s->dbus_new_path = NULL;
   3375 
   3376 	return 0;
   3377 }
   3378 
   3379 #ifdef CONFIG_P2P
   3380 
   3381 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
   3382 	{ "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3383 	  wpas_dbus_getter_p2p_peer_device_name,
   3384 	  NULL
   3385 	},
   3386 	{ "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3387 	  wpas_dbus_getter_p2p_peer_manufacturer,
   3388 	  NULL
   3389 	},
   3390 	{ "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3391 	  wpas_dbus_getter_p2p_peer_modelname,
   3392 	  NULL
   3393 	},
   3394 	{ "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3395 	  wpas_dbus_getter_p2p_peer_modelnumber,
   3396 	  NULL
   3397 	},
   3398 	{ "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
   3399 	  wpas_dbus_getter_p2p_peer_serialnumber,
   3400 	  NULL
   3401 	},
   3402 	{ "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
   3403 	  wpas_dbus_getter_p2p_peer_primary_device_type,
   3404 	  NULL
   3405 	},
   3406 	{ "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
   3407 	  wpas_dbus_getter_p2p_peer_config_method,
   3408 	  NULL
   3409 	},
   3410 	{ "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
   3411 	  wpas_dbus_getter_p2p_peer_level,
   3412 	  NULL
   3413 	},
   3414 	{ "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
   3415 	  wpas_dbus_getter_p2p_peer_device_capability,
   3416 	  NULL
   3417 	},
   3418 	{ "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
   3419 	  wpas_dbus_getter_p2p_peer_group_capability,
   3420 	  NULL
   3421 	},
   3422 	{ "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
   3423 	  wpas_dbus_getter_p2p_peer_secondary_device_types,
   3424 	  NULL
   3425 	},
   3426 	{ "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
   3427 	  wpas_dbus_getter_p2p_peer_vendor_extension,
   3428 	  NULL
   3429 	},
   3430 	{ "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
   3431 	  wpas_dbus_getter_p2p_peer_ies,
   3432 	  NULL
   3433 	},
   3434 	{ "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
   3435 	  wpas_dbus_getter_p2p_peer_device_address,
   3436 	  NULL
   3437 	},
   3438 	{ "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
   3439 	  wpas_dbus_getter_p2p_peer_groups,
   3440 	  NULL
   3441 	},
   3442 	{ NULL, NULL, NULL, NULL, NULL }
   3443 };
   3444 
   3445 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
   3446 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
   3447 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
   3448 	  {
   3449 		  { "properties", "a{sv}", ARG_OUT },
   3450 		  END_ARGS
   3451 	  }
   3452 	},
   3453 	{ NULL, NULL, { END_ARGS } }
   3454 };
   3455 
   3456 /**
   3457  * wpas_dbus_signal_peer - Send a peer related event signal
   3458  * @wpa_s: %wpa_supplicant network interface data
   3459  * @dev: peer device object
   3460  * @interface: name of the interface emitting this signal.
   3461  *	In case of peer objects, it would be emitted by either
   3462  *	the "interface object" or by "peer objects"
   3463  * @sig_name: signal name - DeviceFound
   3464  *
   3465  * Notify listeners about event related with newly found p2p peer device
   3466  */
   3467 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
   3468 				  const u8 *dev_addr, const char *interface,
   3469 				  const char *sig_name)
   3470 {
   3471 	struct wpas_dbus_priv *iface;
   3472 	DBusMessage *msg;
   3473 	DBusMessageIter iter;
   3474 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
   3475 
   3476 	if (wpa_s->p2p_mgmt)
   3477 		wpa_s = wpa_s->parent;
   3478 
   3479 	iface = wpa_s->global->dbus;
   3480 
   3481 	/* Do nothing if the control interface is not turned on */
   3482 	if (iface == NULL || !wpa_s->dbus_new_path)
   3483 		return;
   3484 
   3485 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3486 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   3487 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
   3488 
   3489 	msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
   3490 				      sig_name);
   3491 	if (msg == NULL)
   3492 		return;
   3493 
   3494 	dbus_message_iter_init_append(msg, &iter);
   3495 	path = peer_obj_path;
   3496 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
   3497 					    &path))
   3498 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
   3499 	else
   3500 		dbus_connection_send(iface->con, msg, NULL);
   3501 
   3502 	dbus_message_unref(msg);
   3503 }
   3504 
   3505 
   3506 /**
   3507  * wpas_dbus_signal_peer_found - Send a peer found signal
   3508  * @wpa_s: %wpa_supplicant network interface data
   3509  * @dev_addr: Peer P2P Device Address
   3510  *
   3511  * Notify listeners about find a p2p peer device found
   3512  */
   3513 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
   3514 					const u8 *dev_addr)
   3515 {
   3516 	wpas_dbus_signal_peer(wpa_s, dev_addr,
   3517 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3518 			      "DeviceFound");
   3519 }
   3520 
   3521 /**
   3522  * wpas_dbus_signal_peer_lost - Send a peer lost signal
   3523  * @wpa_s: %wpa_supplicant network interface data
   3524  * @dev_addr: Peer P2P Device Address
   3525  *
   3526  * Notify listeners about lost a p2p peer device
   3527  */
   3528 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
   3529 				       const u8 *dev_addr)
   3530 {
   3531 	wpas_dbus_signal_peer(wpa_s, dev_addr,
   3532 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3533 			      "DeviceLost");
   3534 }
   3535 
   3536 /**
   3537  * wpas_dbus_register_peer - Register a discovered peer object with dbus
   3538  * @wpa_s: wpa_supplicant interface structure
   3539  * @dev_addr: P2P Device Address of the peer
   3540  * Returns: 0 on success, -1 on failure
   3541  *
   3542  * Registers network representing object with dbus
   3543  */
   3544 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
   3545 {
   3546 	struct wpas_dbus_priv *ctrl_iface;
   3547 	struct wpa_dbus_object_desc *obj_desc;
   3548 	struct peer_handler_args *arg;
   3549 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   3550 
   3551 	/* Do nothing if the control interface is not turned on */
   3552 	if (wpa_s == NULL || wpa_s->global == NULL)
   3553 		return 0;
   3554 
   3555 	ctrl_iface = wpa_s->global->dbus;
   3556 	if (ctrl_iface == NULL)
   3557 		return 0;
   3558 
   3559 	wpa_s = wpa_s->parent->parent;
   3560 	if (!wpa_s->dbus_new_path)
   3561 		return 0;
   3562 
   3563 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3564 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   3565 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
   3566 
   3567 	wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
   3568 		   peer_obj_path);
   3569 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   3570 	if (!obj_desc) {
   3571 		wpa_printf(MSG_ERROR,
   3572 			   "Not enough memory to create object description");
   3573 		goto err;
   3574 	}
   3575 
   3576 	/* allocate memory for handlers arguments */
   3577 	arg = os_zalloc(sizeof(struct peer_handler_args));
   3578 	if (!arg) {
   3579 		wpa_printf(MSG_ERROR,
   3580 			   "Not enough memory to create arguments for method");
   3581 		goto err;
   3582 	}
   3583 
   3584 	arg->wpa_s = wpa_s;
   3585 	os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
   3586 
   3587 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
   3588 			   NULL,
   3589 			   wpas_dbus_p2p_peer_properties,
   3590 			   wpas_dbus_p2p_peer_signals);
   3591 
   3592 	if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
   3593 					       wpa_s->ifname, obj_desc))
   3594 		goto err;
   3595 
   3596 	return 0;
   3597 
   3598 err:
   3599 	free_dbus_object_desc(obj_desc);
   3600 	return -1;
   3601 }
   3602 
   3603 /**
   3604  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
   3605  * @wpa_s: wpa_supplicant interface structure
   3606  * @dev_addr: p2p device addr
   3607  * Returns: 0 on success, -1 on failure
   3608  *
   3609  * Registers network representing object with dbus
   3610  */
   3611 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
   3612 				  const u8 *dev_addr)
   3613 {
   3614 	struct wpas_dbus_priv *ctrl_iface;
   3615 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   3616 	int ret;
   3617 
   3618 	/* Do nothing if the control interface is not turned on */
   3619 	if (wpa_s == NULL || wpa_s->global == NULL)
   3620 		return 0;
   3621 
   3622 	wpa_s = wpa_s->parent->parent;
   3623 	if (!wpa_s->dbus_new_path)
   3624 		return 0;
   3625 
   3626 	ctrl_iface = wpa_s->global->dbus;
   3627 	if (ctrl_iface == NULL)
   3628 		return 0;
   3629 
   3630 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3631 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   3632 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
   3633 
   3634 	wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
   3635 		   peer_obj_path);
   3636 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
   3637 
   3638 	return ret;
   3639 }
   3640 
   3641 
   3642 /**
   3643  * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
   3644  * @wpa_s: %wpa_supplicant network interface data
   3645  *
   3646  * Notify listeners about P2P Find stopped
   3647  */
   3648 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
   3649 {
   3650 	struct wpas_dbus_priv *iface;
   3651 	DBusMessage *msg;
   3652 
   3653 	iface = wpa_s->global->dbus;
   3654 
   3655 	/* Do nothing if the control interface is not turned on */
   3656 	if (iface == NULL || !wpa_s->dbus_new_path)
   3657 		return;
   3658 
   3659 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
   3660 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
   3661 				      "FindStopped");
   3662 	if (msg == NULL)
   3663 		return;
   3664 
   3665 	dbus_connection_send(iface->con, msg, NULL);
   3666 
   3667 	dbus_message_unref(msg);
   3668 }
   3669 
   3670 
   3671 /**
   3672  * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
   3673  * @wpa_s: %wpa_supplicant network interface data
   3674  * @dev_addr: P2P Device Address
   3675  *
   3676  * Notify listeners about peer Groups property changes.
   3677  */
   3678 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
   3679 					  const u8 *dev_addr)
   3680 {
   3681 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   3682 
   3683 	if (wpa_s->p2p_mgmt)
   3684 		wpa_s = wpa_s->parent;
   3685 
   3686 	if (!wpa_s->dbus_new_path)
   3687 		return;
   3688 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3689 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
   3690 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
   3691 
   3692 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
   3693 				       WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
   3694 }
   3695 
   3696 
   3697 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
   3698 	{ "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
   3699 	  wpas_dbus_getter_p2p_group_members,
   3700 	  NULL
   3701 	},
   3702 	{ "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
   3703 	  wpas_dbus_getter_p2p_group,
   3704 	  NULL
   3705 	},
   3706 	{ "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
   3707 	  wpas_dbus_getter_p2p_role,
   3708 	  NULL
   3709 	},
   3710 	{ "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
   3711 	  wpas_dbus_getter_p2p_group_ssid,
   3712 	  NULL
   3713 	},
   3714 	{ "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
   3715 	  wpas_dbus_getter_p2p_group_bssid,
   3716 	  NULL
   3717 	},
   3718 	{ "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
   3719 	  wpas_dbus_getter_p2p_group_frequency,
   3720 	  NULL
   3721 	},
   3722 	{ "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
   3723 	  wpas_dbus_getter_p2p_group_passphrase,
   3724 	  NULL
   3725 	},
   3726 	{ "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
   3727 	  wpas_dbus_getter_p2p_group_psk,
   3728 	  NULL
   3729 	},
   3730 	{ "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
   3731 	  wpas_dbus_getter_p2p_group_vendor_ext,
   3732 	  wpas_dbus_setter_p2p_group_vendor_ext
   3733 	},
   3734 	{ NULL, NULL, NULL, NULL, NULL }
   3735 };
   3736 
   3737 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
   3738 	{ "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
   3739 	  {
   3740 		  { "peer", "o", ARG_OUT },
   3741 		  END_ARGS
   3742 	  }
   3743 	},
   3744 	{ "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
   3745 	  {
   3746 		  { "peer", "o", ARG_OUT },
   3747 		  END_ARGS
   3748 	  }
   3749 	},
   3750 	{ NULL, NULL, { END_ARGS } }
   3751 };
   3752 
   3753 /**
   3754  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
   3755  * @wpa_s: wpa_supplicant interface structure
   3756  * @ssid: SSID struct
   3757  * Returns: 0 on success, -1 on failure
   3758  *
   3759  * Registers p2p group representing object with dbus
   3760  */
   3761 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
   3762 				  struct wpa_ssid *ssid)
   3763 {
   3764 	struct wpas_dbus_priv *ctrl_iface;
   3765 	struct wpa_dbus_object_desc *obj_desc;
   3766 	char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   3767 
   3768 	/* Do nothing if the control interface is not turned on */
   3769 	if (wpa_s == NULL || wpa_s->global == NULL)
   3770 		return;
   3771 
   3772 	ctrl_iface = wpa_s->global->dbus;
   3773 	if (ctrl_iface == NULL)
   3774 		return;
   3775 
   3776 	if (wpa_s->dbus_groupobj_path) {
   3777 		wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
   3778 			   __func__, wpa_s->dbus_groupobj_path);
   3779 		return;
   3780 	}
   3781 
   3782 	if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
   3783 		return;
   3784 
   3785 	wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
   3786 	if (wpa_s->dbus_groupobj_path == NULL)
   3787 		return;
   3788 
   3789 	wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
   3790 		   group_obj_path);
   3791 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   3792 	if (!obj_desc) {
   3793 		wpa_printf(MSG_ERROR,
   3794 			   "Not enough memory to create object description");
   3795 		goto err;
   3796 	}
   3797 
   3798 	wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
   3799 			   wpas_dbus_p2p_group_properties,
   3800 			   wpas_dbus_p2p_group_signals);
   3801 
   3802 	if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
   3803 					       wpa_s->ifname, obj_desc))
   3804 		goto err;
   3805 
   3806 	return;
   3807 
   3808 err:
   3809 	if (wpa_s->dbus_groupobj_path) {
   3810 		os_free(wpa_s->dbus_groupobj_path);
   3811 		wpa_s->dbus_groupobj_path = NULL;
   3812 	}
   3813 
   3814 	free_dbus_object_desc(obj_desc);
   3815 }
   3816 
   3817 /**
   3818  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
   3819  * @wpa_s: wpa_supplicant interface structure
   3820  * @ssid: network name of the p2p group started
   3821  */
   3822 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
   3823 				    const struct wpa_ssid *ssid)
   3824 {
   3825 	struct wpas_dbus_priv *ctrl_iface;
   3826 
   3827 	/* Do nothing if the control interface is not turned on */
   3828 	if (wpa_s == NULL || wpa_s->global == NULL)
   3829 		return;
   3830 
   3831 	if (wpa_s->p2p_mgmt)
   3832 		wpa_s = wpa_s->parent;
   3833 
   3834 	ctrl_iface = wpa_s->global->dbus;
   3835 	if (ctrl_iface == NULL)
   3836 		return;
   3837 
   3838 	if (!wpa_s->dbus_groupobj_path) {
   3839 		wpa_printf(MSG_DEBUG,
   3840 			   "%s: Group object '%s' already unregistered",
   3841 			   __func__, wpa_s->dbus_groupobj_path);
   3842 		return;
   3843 	}
   3844 
   3845 	peer_groups_changed(wpa_s);
   3846 
   3847 	wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
   3848 		   wpa_s->dbus_groupobj_path);
   3849 
   3850 	wpa_dbus_unregister_object_per_iface(ctrl_iface,
   3851 					     wpa_s->dbus_groupobj_path);
   3852 
   3853 	os_free(wpa_s->dbus_groupobj_path);
   3854 	wpa_s->dbus_groupobj_path = NULL;
   3855 }
   3856 
   3857 static const struct wpa_dbus_property_desc
   3858 	wpas_dbus_persistent_group_properties[] = {
   3859 	{ "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
   3860 	  wpas_dbus_getter_persistent_group_properties,
   3861 	  wpas_dbus_setter_persistent_group_properties
   3862 	},
   3863 	{ NULL, NULL, NULL, NULL, NULL }
   3864 };
   3865 
   3866 /* No signals intended for persistent group objects */
   3867 
   3868 /**
   3869  * wpas_dbus_register_persistent_group - Register a configured(saved)
   3870  *	persistent group with dbus
   3871  * @wpa_s: wpa_supplicant interface structure
   3872  * @ssid: persistent group (still represented as a network within wpa)
   3873  *	  configuration data
   3874  * Returns: 0 on success, -1 on failure
   3875  *
   3876  * Registers a persistent group representing object with dbus.
   3877  */
   3878 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
   3879 					struct wpa_ssid *ssid)
   3880 {
   3881 	struct wpas_dbus_priv *ctrl_iface;
   3882 	struct wpa_dbus_object_desc *obj_desc;
   3883 	struct network_handler_args *arg;
   3884 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   3885 
   3886 	/* Do nothing if the control interface is not turned on */
   3887 	if (wpa_s == NULL || wpa_s->global == NULL)
   3888 		return 0;
   3889 	wpa_s = wpa_s->parent->parent;
   3890 	if (!wpa_s->dbus_new_path)
   3891 		return 0;
   3892 
   3893 	/* Make sure ssid is a persistent group */
   3894 	if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
   3895 		return -1; /* should we return w/o complaining? */
   3896 
   3897 	if (wpa_s->p2p_mgmt)
   3898 		wpa_s = wpa_s->parent;
   3899 
   3900 	ctrl_iface = wpa_s->global->dbus;
   3901 	if (ctrl_iface == NULL)
   3902 		return 0;
   3903 
   3904 	/*
   3905 	 * Intentionally not coming up with different numbering scheme
   3906 	 * for persistent groups.
   3907 	 */
   3908 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3909 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
   3910 		    wpa_s->dbus_new_path, ssid->id);
   3911 
   3912 	wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
   3913 		   pgrp_obj_path);
   3914 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
   3915 	if (!obj_desc) {
   3916 		wpa_printf(MSG_ERROR,
   3917 			   "dbus: Not enough memory to create object description");
   3918 		goto err;
   3919 	}
   3920 
   3921 	/*
   3922 	 * Reusing the same context structure as that for networks
   3923 	 * since these are represented using same data structure.
   3924 	 */
   3925 	/* allocate memory for handlers arguments */
   3926 	arg = os_zalloc(sizeof(struct network_handler_args));
   3927 	if (!arg) {
   3928 		wpa_printf(MSG_ERROR,
   3929 			   "dbus: Not enough memory to create arguments for method");
   3930 		goto err;
   3931 	}
   3932 
   3933 	arg->wpa_s = wpa_s;
   3934 	arg->ssid = ssid;
   3935 
   3936 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
   3937 			   wpas_dbus_persistent_group_properties,
   3938 			   NULL);
   3939 
   3940 	if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
   3941 					       wpa_s->ifname, obj_desc))
   3942 		goto err;
   3943 
   3944 	wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
   3945 
   3946 	return 0;
   3947 
   3948 err:
   3949 	free_dbus_object_desc(obj_desc);
   3950 	return -1;
   3951 }
   3952 
   3953 
   3954 /**
   3955  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
   3956  *	from dbus
   3957  * @wpa_s: wpa_supplicant interface structure
   3958  * @nid: network id
   3959  * Returns: 0 on success, -1 on failure
   3960  *
   3961  * Unregisters persistent group representing object from dbus
   3962  *
   3963  * NOTE: There is a slight issue with the semantics here. While the
   3964  * implementation simply means the persistent group is unloaded from memory,
   3965  * it should not get interpreted as the group is actually being erased/removed
   3966  * from persistent storage as well.
   3967  */
   3968 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
   3969 					  int nid)
   3970 {
   3971 	struct wpas_dbus_priv *ctrl_iface;
   3972 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
   3973 	int ret;
   3974 
   3975 	/* Do nothing if the control interface is not turned on */
   3976 	if (wpa_s == NULL || wpa_s->global == NULL)
   3977 		return 0;
   3978 
   3979 	wpa_s = wpa_s->parent->parent;
   3980 
   3981 	ctrl_iface = wpa_s->global->dbus;
   3982 	if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
   3983 		return 0;
   3984 
   3985 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
   3986 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
   3987 		    wpa_s->dbus_new_path, nid);
   3988 
   3989 	wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
   3990 		   pgrp_obj_path);
   3991 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
   3992 
   3993 	if (!ret)
   3994 		wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
   3995 
   3996 	return ret;
   3997 }
   3998 
   3999 #endif /* CONFIG_P2P */
   4000