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