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