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