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