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