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