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