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