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