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