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