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