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