dbus_new.c revision 214501
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 "wps/wps.h"
21#include "../config.h"
22#include "../wpa_supplicant_i.h"
23#include "../bss.h"
24#include "dbus_new_helpers.h"
25#include "dbus_dict_helpers.h"
26#include "dbus_new.h"
27#include "dbus_new_handlers.h"
28#include "dbus_common.h"
29#include "dbus_common_i.h"
30
31
32/**
33 * wpas_dbus_signal_interface - Send a interface related event signal
34 * @wpa_s: %wpa_supplicant network interface data
35 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
36 * @properties: Whether to add second argument with object properties
37 *
38 * Notify listeners about event related with interface
39 */
40static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
41				       const char *sig_name, int properties)
42{
43	struct wpas_dbus_priv *iface;
44	DBusMessage *msg;
45	DBusMessageIter iter, iter_dict;
46
47	iface = wpa_s->global->dbus;
48
49	/* Do nothing if the control interface is not turned on */
50	if (iface == NULL)
51		return;
52
53	msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
54				      WPAS_DBUS_NEW_INTERFACE, sig_name);
55	if (msg == NULL)
56		return;
57
58	dbus_message_iter_init_append(msg, &iter);
59	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
60					    &wpa_s->dbus_new_path))
61		goto err;
62
63	if (properties) {
64		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
65			goto err;
66
67		wpa_dbus_get_object_properties(iface, wpa_s->dbus_new_path,
68					       WPAS_DBUS_NEW_IFACE_INTERFACE,
69					       &iter_dict);
70
71		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
72			goto err;
73	}
74
75	dbus_connection_send(iface->con, msg, NULL);
76	dbus_message_unref(msg);
77	return;
78
79err:
80	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
81	dbus_message_unref(msg);
82}
83
84
85/**
86 * wpas_dbus_signal_interface_added - Send a interface created signal
87 * @wpa_s: %wpa_supplicant network interface data
88 *
89 * Notify listeners about creating new interface
90 */
91static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
92{
93	wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
94}
95
96
97/**
98 * wpas_dbus_signal_interface_removed - Send a interface removed signal
99 * @wpa_s: %wpa_supplicant network interface data
100 *
101 * Notify listeners about removing interface
102 */
103static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
104{
105	wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
106
107}
108
109
110/**
111 * wpas_dbus_signal_scan_done - send scan done signal
112 * @wpa_s: %wpa_supplicant network interface data
113 * @success: indicates if scanning succeed or failed
114 *
115 * Notify listeners about finishing a scan
116 */
117void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
118{
119	struct wpas_dbus_priv *iface;
120	DBusMessage *msg;
121	dbus_bool_t succ;
122
123	iface = wpa_s->global->dbus;
124
125	/* Do nothing if the control interface is not turned on */
126	if (iface == NULL)
127		return;
128
129	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
130				      WPAS_DBUS_NEW_IFACE_INTERFACE,
131				      "ScanDone");
132	if (msg == NULL)
133		return;
134
135	succ = success ? TRUE : FALSE;
136	if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
137				     DBUS_TYPE_INVALID))
138		dbus_connection_send(iface->con, msg, NULL);
139	else
140		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
141	dbus_message_unref(msg);
142}
143
144
145/**
146 * wpas_dbus_signal_blob - Send a BSS related event signal
147 * @wpa_s: %wpa_supplicant network interface data
148 * @bss_obj_path: BSS object path
149 * @sig_name: signal name - BSSAdded or BSSRemoved
150 * @properties: Whether to add second argument with object properties
151 *
152 * Notify listeners about event related with BSS
153 */
154static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
155				 const char *bss_obj_path,
156				 const char *sig_name, int properties)
157{
158	struct wpas_dbus_priv *iface;
159	DBusMessage *msg;
160	DBusMessageIter iter, iter_dict;
161
162	iface = wpa_s->global->dbus;
163
164	/* Do nothing if the control interface is not turned on */
165	if (iface == NULL)
166		return;
167
168	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
169				      WPAS_DBUS_NEW_IFACE_INTERFACE,
170				      sig_name);
171	if (msg == NULL)
172		return;
173
174	dbus_message_iter_init_append(msg, &iter);
175	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
176					    &bss_obj_path))
177		goto err;
178
179	if (properties) {
180		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
181			goto err;
182
183		wpa_dbus_get_object_properties(iface, bss_obj_path,
184					       WPAS_DBUS_NEW_IFACE_BSS,
185					       &iter_dict);
186
187		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
188			goto err;
189	}
190
191	dbus_connection_send(iface->con, msg, NULL);
192	dbus_message_unref(msg);
193	return;
194
195err:
196	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
197	dbus_message_unref(msg);
198}
199
200
201/**
202 * wpas_dbus_signal_bss_added - Send a BSS added signal
203 * @wpa_s: %wpa_supplicant network interface data
204 * @bss_obj_path: new BSS object path
205 *
206 * Notify listeners about adding new BSS
207 */
208static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
209				       const char *bss_obj_path)
210{
211	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
212}
213
214
215/**
216 * wpas_dbus_signal_bss_removed - Send a BSS removed signal
217 * @wpa_s: %wpa_supplicant network interface data
218 * @bss_obj_path: BSS object path
219 *
220 * Notify listeners about removing BSS
221 */
222static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
223					 const char *bss_obj_path)
224{
225	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
226}
227
228
229/**
230 * wpas_dbus_signal_blob - Send a blob related event signal
231 * @wpa_s: %wpa_supplicant network interface data
232 * @name: blob name
233 * @sig_name: signal name - BlobAdded or BlobRemoved
234 *
235 * Notify listeners about event related with blob
236 */
237static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
238				  const char *name, const char *sig_name)
239{
240	struct wpas_dbus_priv *iface;
241	DBusMessage *msg;
242
243	iface = wpa_s->global->dbus;
244
245	/* Do nothing if the control interface is not turned on */
246	if (iface == NULL)
247		return;
248
249	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
250				      WPAS_DBUS_NEW_IFACE_INTERFACE,
251				      sig_name);
252	if (msg == NULL)
253		return;
254
255	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
256				     DBUS_TYPE_INVALID))
257		dbus_connection_send(iface->con, msg, NULL);
258	else
259		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
260	dbus_message_unref(msg);
261}
262
263
264/**
265 * wpas_dbus_signal_blob_added - Send a blob added signal
266 * @wpa_s: %wpa_supplicant network interface data
267 * @name: blob name
268 *
269 * Notify listeners about adding a new blob
270 */
271void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
272				 const char *name)
273{
274	wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
275}
276
277
278/**
279 * wpas_dbus_signal_blob_removed - Send a blob removed signal
280 * @wpa_s: %wpa_supplicant network interface data
281 * @name: blob name
282 *
283 * Notify listeners about removing blob
284 */
285void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
286				   const char *name)
287{
288	wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
289}
290
291
292/**
293 * wpas_dbus_signal_network - Send a network related event signal
294 * @wpa_s: %wpa_supplicant network interface data
295 * @id: new network id
296 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
297 * @properties: determines if add second argument with object properties
298 *
299 * Notify listeners about event related with configured network
300 */
301static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
302				     int id, const char *sig_name,
303				     int properties)
304{
305	struct wpas_dbus_priv *iface;
306	DBusMessage *msg;
307	DBusMessageIter iter, iter_dict;
308	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
309
310	iface = wpa_s->global->dbus;
311
312	/* Do nothing if the control interface is not turned on */
313	if (iface == NULL)
314		return;
315
316	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
317		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
318		    wpa_s->dbus_new_path, id);
319
320	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
321				      WPAS_DBUS_NEW_IFACE_INTERFACE,
322				      sig_name);
323	if (msg == NULL)
324		return;
325
326	dbus_message_iter_init_append(msg, &iter);
327	path = net_obj_path;
328	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
329					    &path))
330		goto err;
331
332	if (properties) {
333		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
334			goto err;
335
336		wpa_dbus_get_object_properties(iface, net_obj_path,
337					       WPAS_DBUS_NEW_IFACE_NETWORK,
338					       &iter_dict);
339
340		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
341			goto err;
342	}
343
344	dbus_connection_send(iface->con, msg, NULL);
345
346	dbus_message_unref(msg);
347	return;
348
349err:
350	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
351	dbus_message_unref(msg);
352}
353
354
355/**
356 * wpas_dbus_signal_network_added - Send a network added signal
357 * @wpa_s: %wpa_supplicant network interface data
358 * @id: new network id
359 *
360 * Notify listeners about adding new network
361 */
362static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
363					   int id)
364{
365	wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
366}
367
368
369/**
370 * wpas_dbus_signal_network_removed - Send a network removed signal
371 * @wpa_s: %wpa_supplicant network interface data
372 * @id: network id
373 *
374 * Notify listeners about removing a network
375 */
376static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
377					     int id)
378{
379	wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
380}
381
382
383/**
384 * wpas_dbus_signal_network_selected - Send a network selected signal
385 * @wpa_s: %wpa_supplicant network interface data
386 * @id: network id
387 *
388 * Notify listeners about selecting a network
389 */
390void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
391{
392	wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
393}
394
395
396/**
397 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
398 * @wpa_s: %wpa_supplicant network interface data
399 * @ssid: configured network which Enabled property has changed
400 *
401 * Sends PropertyChanged signals containing new value of Enabled property
402 * for specified network
403 */
404void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
405					      struct wpa_ssid *ssid)
406{
407
408	char path[WPAS_DBUS_OBJECT_PATH_MAX];
409	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
410		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
411		    wpa_s->dbus_new_path, ssid->id);
412
413	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
414				       WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
415}
416
417
418#ifdef CONFIG_WPS
419
420/**
421 * wpas_dbus_signal_wps_event_success - Signals Success WPS event
422 * @wpa_s: %wpa_supplicant network interface data
423 *
424 * Sends Event dbus signal with name "success" and empty dict as arguments
425 */
426void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
427{
428
429	DBusMessage *msg;
430	DBusMessageIter iter, dict_iter;
431	struct wpas_dbus_priv *iface;
432	char *key = "success";
433
434	iface = wpa_s->global->dbus;
435
436	/* Do nothing if the control interface is not turned on */
437	if (iface == NULL)
438		return;
439
440	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
441				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
442	if (msg == NULL)
443		return;
444
445	dbus_message_iter_init_append(msg, &iter);
446
447	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
448	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
449	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
450		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
451	else
452		dbus_connection_send(iface->con, msg, NULL);
453
454	dbus_message_unref(msg);
455}
456
457
458/**
459 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
460 * @wpa_s: %wpa_supplicant network interface data
461 *
462 * Sends Event dbus signal with name "fail" and dictionary containing
463 * "msg field with fail message number (int32) as arguments
464 */
465void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
466				     struct wps_event_fail *fail)
467{
468
469	DBusMessage *msg;
470	DBusMessageIter iter, dict_iter;
471	struct wpas_dbus_priv *iface;
472	char *key = "fail";
473
474	iface = wpa_s->global->dbus;
475
476	/* Do nothing if the control interface is not turned on */
477	if (iface == NULL)
478		return;
479
480	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
481				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
482	if (msg == NULL)
483		return;
484
485	dbus_message_iter_init_append(msg, &iter);
486
487	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
488	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
489	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
490	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
491		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
492	else
493		dbus_connection_send(iface->con, msg, NULL);
494
495	dbus_message_unref(msg);
496}
497
498
499/**
500 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
501 * @wpa_s: %wpa_supplicant network interface data
502 *
503 * Sends Event dbus signal with name "m2d" and dictionary containing
504 * fields of wps_event_m2d structure.
505 */
506void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
507				    struct wps_event_m2d *m2d)
508{
509
510	DBusMessage *msg;
511	DBusMessageIter iter, dict_iter;
512	struct wpas_dbus_priv *iface;
513	char *key = "m2d";
514
515	iface = wpa_s->global->dbus;
516
517	/* Do nothing if the control interface is not turned on */
518	if (iface == NULL)
519		return;
520
521	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
522				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
523	if (msg == NULL)
524		return;
525
526	dbus_message_iter_init_append(msg, &iter);
527
528	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
529	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
530	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
531					 m2d->config_methods) ||
532	    !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
533					     (const char *) m2d->manufacturer,
534					     m2d->manufacturer_len) ||
535	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
536					     (const char *) m2d->model_name,
537					     m2d->model_name_len) ||
538	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
539					     (const char *) m2d->model_number,
540					     m2d->model_number_len) ||
541	    !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
542					     (const char *)
543					     m2d->serial_number,
544					     m2d->serial_number_len) ||
545	    !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
546					     (const char *) m2d->dev_name,
547					     m2d->dev_name_len) ||
548	    !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
549					     (const char *)
550					     m2d->primary_dev_type, 8) ||
551	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
552					 m2d->config_error) ||
553	    !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
554					 m2d->dev_password_id) ||
555	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
556		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
557	else
558		dbus_connection_send(iface->con, msg, NULL);
559
560	dbus_message_unref(msg);
561}
562
563
564/**
565 * wpas_dbus_signal_wps_cred - Signals new credentials
566 * @wpa_s: %wpa_supplicant network interface data
567 *
568 * Sends signal with credentials in directory argument
569 */
570void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
571			       const struct wps_credential *cred)
572{
573	DBusMessage *msg;
574	DBusMessageIter iter, dict_iter;
575	struct wpas_dbus_priv *iface;
576	char *auth_type[6]; /* we have six possible authorization types */
577	int at_num = 0;
578	char *encr_type[4]; /* we have four possible encryption types */
579	int et_num = 0;
580
581	iface = wpa_s->global->dbus;
582
583	/* Do nothing if the control interface is not turned on */
584	if (iface == NULL)
585		return;
586
587	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
588				      WPAS_DBUS_NEW_IFACE_WPS,
589				      "Credentials");
590	if (msg == NULL)
591		return;
592
593	dbus_message_iter_init_append(msg, &iter);
594	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
595		goto nomem;
596
597	if (cred->auth_type & WPS_AUTH_OPEN)
598		auth_type[at_num++] = "open";
599	if (cred->auth_type & WPS_AUTH_WPAPSK)
600		auth_type[at_num++] = "wpa-psk";
601	if (cred->auth_type & WPS_AUTH_SHARED)
602		auth_type[at_num++] = "shared";
603	if (cred->auth_type & WPS_AUTH_WPA)
604		auth_type[at_num++] = "wpa-eap";
605	if (cred->auth_type & WPS_AUTH_WPA2)
606		auth_type[at_num++] = "wpa2-eap";
607	if (cred->auth_type & WPS_AUTH_WPA2PSK)
608		auth_type[at_num++] =
609		"wpa2-psk";
610
611	if (cred->encr_type & WPS_ENCR_NONE)
612		encr_type[et_num++] = "none";
613	if (cred->encr_type & WPS_ENCR_WEP)
614		encr_type[et_num++] = "wep";
615	if (cred->encr_type & WPS_ENCR_TKIP)
616		encr_type[et_num++] = "tkip";
617	if (cred->encr_type & WPS_ENCR_AES)
618		encr_type[et_num++] = "aes";
619
620	if (wpa_s->current_ssid) {
621		if (!wpa_dbus_dict_append_byte_array(
622			    &dict_iter, "BSSID",
623			    (const char *) wpa_s->current_ssid->bssid,
624			    ETH_ALEN))
625			goto nomem;
626	}
627
628	if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
629					     (const char *) cred->ssid,
630					     cred->ssid_len) ||
631	    !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
632					       (const char **) auth_type,
633					       at_num) ||
634	    !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
635					       (const char **) encr_type,
636					       et_num) ||
637	    !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
638					     (const char *) cred->key,
639					     cred->key_len) ||
640	    !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
641					 cred->key_idx) ||
642	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
643		goto nomem;
644
645	dbus_connection_send(iface->con, msg, NULL);
646
647nomem:
648	dbus_message_unref(msg);
649}
650
651#endif /* CONFIG_WPS */
652
653
654/**
655 * wpas_dbus_signal_prop_changed - Signals change of property
656 * @wpa_s: %wpa_supplicant network interface data
657 * @property: indicates which property has changed
658 *
659 * Sends ProertyChanged signals with path, interface and arguments
660 * depending on which property has changed.
661 */
662void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
663				   enum wpas_dbus_prop property)
664{
665	WPADBusPropertyAccessor getter;
666	char *prop;
667
668	if (wpa_s->dbus_new_path == NULL)
669		return; /* Skip signal since D-Bus setup is not yet ready */
670
671	switch (property) {
672	case WPAS_DBUS_PROP_AP_SCAN:
673		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
674		prop = "ApScan";
675		break;
676	case WPAS_DBUS_PROP_SCANNING:
677		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
678		prop = "Scanning";
679		break;
680	case WPAS_DBUS_PROP_STATE:
681		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state;
682		prop = "State";
683		break;
684	case WPAS_DBUS_PROP_CURRENT_BSS:
685		getter = (WPADBusPropertyAccessor)
686			wpas_dbus_getter_current_bss;
687		prop = "CurrentBSS";
688		break;
689	case WPAS_DBUS_PROP_CURRENT_NETWORK:
690		getter = (WPADBusPropertyAccessor)
691			wpas_dbus_getter_current_network;
692		prop = "CurrentNetwork";
693		break;
694	default:
695		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
696			   __func__, property);
697		return;
698	}
699
700	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
701				       wpa_s->dbus_new_path,
702				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
703}
704
705
706/**
707 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
708 * @wpa_s: %wpa_supplicant network interface data
709 * @property: indicates which property has changed
710 * @id: unique BSS identifier
711 *
712 * Sends PropertyChanged signals with path, interface, and arguments depending
713 * on which property has changed.
714 */
715void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
716				       enum wpas_dbus_bss_prop property,
717				       unsigned int id)
718{
719	char path[WPAS_DBUS_OBJECT_PATH_MAX];
720	char *prop;
721
722	switch (property) {
723	case WPAS_DBUS_BSS_PROP_SIGNAL:
724		prop = "Signal";
725		break;
726	case WPAS_DBUS_BSS_PROP_FREQ:
727		prop = "Frequency";
728		break;
729	case WPAS_DBUS_BSS_PROP_MODE:
730		prop = "Mode";
731		break;
732	case WPAS_DBUS_BSS_PROP_PRIVACY:
733		prop = "Privacy";
734		break;
735	case WPAS_DBUS_BSS_PROP_RATES:
736		prop = "Rates";
737		break;
738	case WPAS_DBUS_BSS_PROP_WPA:
739		prop = "WPA";
740		break;
741	case WPAS_DBUS_BSS_PROP_RSN:
742		prop = "RSN";
743		break;
744	case WPAS_DBUS_BSS_PROP_IES:
745		prop = "IEs";
746		break;
747	default:
748		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
749			   __func__, property);
750		return;
751	}
752
753	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
754		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
755		    wpa_s->dbus_new_path, id);
756
757	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
758				       WPAS_DBUS_NEW_IFACE_BSS, prop);
759}
760
761
762/**
763 * wpas_dbus_signal_debug_level_changed - Signals change of debug param
764 * @global: wpa_global structure
765 *
766 * Sends ProertyChanged signals informing that debug level has changed.
767 */
768void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
769{
770	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
771				       WPAS_DBUS_NEW_INTERFACE,
772				       "DebugLevel");
773}
774
775
776/**
777 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
778 * @global: wpa_global structure
779 *
780 * Sends ProertyChanged signals informing that debug timestamp has changed.
781 */
782void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
783{
784	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
785				       WPAS_DBUS_NEW_INTERFACE,
786				       "DebugTimestamp");
787}
788
789
790/**
791 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
792 * @global: wpa_global structure
793 *
794 * Sends ProertyChanged signals informing that debug show_keys has changed.
795 */
796void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
797{
798	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
799				       WPAS_DBUS_NEW_INTERFACE,
800				       "DebugShowKeys");
801}
802
803
804static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
805			       void *priv,
806			       WPADBusArgumentFreeFunction priv_free,
807			       const struct wpa_dbus_method_desc *methods,
808			       const struct wpa_dbus_property_desc *properties,
809			       const struct wpa_dbus_signal_desc *signals)
810{
811	int n;
812
813	obj_desc->user_data = priv;
814	obj_desc->user_data_free_func = priv_free;
815	obj_desc->methods = methods;
816	obj_desc->properties = properties;
817	obj_desc->signals = signals;
818
819	for (n = 0; properties && properties->dbus_property; properties++)
820		n++;
821
822	obj_desc->prop_changed_flags = os_zalloc(n);
823	if (!obj_desc->prop_changed_flags)
824		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
825			   __func__);
826}
827
828
829static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
830	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
831	  (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
832	  {
833		  { "args", "a{sv}", ARG_IN },
834		  { "path", "o", ARG_OUT },
835		  END_ARGS
836	  }
837	},
838	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
839	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
840	  {
841		  { "path", "o", ARG_IN },
842		  END_ARGS
843	  }
844	},
845	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
846	  (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
847	  {
848		  { "ifname", "s", ARG_IN },
849		  { "path", "o", ARG_OUT },
850		  END_ARGS
851	  }
852	},
853	{ NULL, NULL, NULL, { END_ARGS } }
854};
855
856static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
857	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
858	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
859	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
860	  RW
861	},
862	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
863	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
864	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
865	  RW
866	},
867	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
868	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
869	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
870	  RW
871	},
872	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
873	  (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
874	  NULL,
875	  R
876	},
877	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
878	  (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
879	  NULL,
880	  R
881	},
882	{ NULL, NULL, NULL, NULL, NULL, 0 }
883};
884
885static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
886	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
887	  {
888		  { "path", "o", ARG_OUT },
889		  { "properties", "a{sv}", ARG_OUT },
890		  END_ARGS
891	  }
892	},
893	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
894	  {
895		  { "path", "o", ARG_OUT },
896		  END_ARGS
897	  }
898	},
899	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
900	  {
901		  { "properties", "a{sv}", ARG_OUT },
902		  END_ARGS
903	  }
904	},
905	{ NULL, NULL, { END_ARGS } }
906};
907
908
909/**
910 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
911 * @global: Pointer to global data from wpa_supplicant_init()
912 * Returns: 0 on success or -1 on failure
913 *
914 * Initialize the dbus control interface for wpa_supplicantand and start
915 * receiving commands from external programs over the bus.
916 */
917int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
918{
919	struct wpa_dbus_object_desc *obj_desc;
920	int ret;
921
922	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
923	if (!obj_desc) {
924		wpa_printf(MSG_ERROR, "Not enough memory "
925			   "to create object description");
926		return -1;
927	}
928
929	wpas_dbus_register(obj_desc, priv->global, NULL,
930			   wpas_dbus_global_methods,
931			   wpas_dbus_global_properties,
932			   wpas_dbus_global_signals);
933
934	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
935		   WPAS_DBUS_NEW_PATH);
936	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
937				       WPAS_DBUS_NEW_SERVICE,
938				       obj_desc);
939	if (ret < 0)
940		free_dbus_object_desc(obj_desc);
941	else
942		priv->dbus_new_initialized = 1;
943
944	return ret;
945}
946
947
948/**
949 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
950 * wpa_supplicant
951 * @iface: Pointer to dbus private data from wpas_dbus_init()
952 *
953 * Deinitialize the dbus control interface that was initialized with
954 * wpas_dbus_ctrl_iface_init().
955 */
956void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
957{
958	if (!iface->dbus_new_initialized)
959		return;
960	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
961		   WPAS_DBUS_NEW_PATH);
962	dbus_connection_unregister_object_path(iface->con,
963					       WPAS_DBUS_NEW_PATH);
964}
965
966
967static void wpa_dbus_free(void *ptr)
968{
969	os_free(ptr);
970}
971
972
973static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
974	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
975	  (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
976	  (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
977	  RW
978	},
979	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
980	  (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
981	  (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
982	  RW
983	},
984	{ NULL, NULL, NULL, NULL, NULL, 0 }
985};
986
987
988static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
989	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
990	  {
991		  { "properties", "a{sv}", ARG_OUT },
992		  END_ARGS
993	  }
994	},
995	{ NULL, NULL, { END_ARGS } }
996};
997
998
999/**
1000 * wpas_dbus_register_network - Register a configured network with dbus
1001 * @wpa_s: wpa_supplicant interface structure
1002 * @ssid: network configuration data
1003 * Returns: 0 on success, -1 on failure
1004 *
1005 * Registers network representing object with dbus
1006 */
1007int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
1008			       struct wpa_ssid *ssid)
1009{
1010	struct wpas_dbus_priv *ctrl_iface;
1011	struct wpa_dbus_object_desc *obj_desc;
1012	struct network_handler_args *arg;
1013	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1014
1015	/* Do nothing if the control interface is not turned on */
1016	if (wpa_s == NULL || wpa_s->global == NULL)
1017		return 0;
1018	ctrl_iface = wpa_s->global->dbus;
1019	if (ctrl_iface == NULL)
1020		return 0;
1021
1022	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1023		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1024		    wpa_s->dbus_new_path, ssid->id);
1025
1026	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
1027		   net_obj_path);
1028	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1029	if (!obj_desc) {
1030		wpa_printf(MSG_ERROR, "Not enough memory "
1031			   "to create object description");
1032		goto err;
1033	}
1034
1035	/* allocate memory for handlers arguments */
1036	arg = os_zalloc(sizeof(struct network_handler_args));
1037	if (!arg) {
1038		wpa_printf(MSG_ERROR, "Not enough memory "
1039			   "to create arguments for method");
1040		goto err;
1041	}
1042
1043	arg->wpa_s = wpa_s;
1044	arg->ssid = ssid;
1045
1046	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1047			   wpas_dbus_network_properties,
1048			   wpas_dbus_network_signals);
1049
1050	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
1051					       wpa_s->ifname, obj_desc))
1052		goto err;
1053
1054	wpas_dbus_signal_network_added(wpa_s, ssid->id);
1055
1056	return 0;
1057
1058err:
1059	free_dbus_object_desc(obj_desc);
1060	return -1;
1061}
1062
1063
1064/**
1065 * wpas_dbus_unregister_network - Unregister a configured network from dbus
1066 * @wpa_s: wpa_supplicant interface structure
1067 * @nid: network id
1068 * Returns: 0 on success, -1 on failure
1069 *
1070 * Unregisters network representing object from dbus
1071 */
1072int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
1073{
1074	struct wpas_dbus_priv *ctrl_iface;
1075	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1076	int ret;
1077
1078	/* Do nothing if the control interface is not turned on */
1079	if (wpa_s == NULL || wpa_s->global == NULL ||
1080	    wpa_s->dbus_new_path == NULL)
1081		return 0;
1082	ctrl_iface = wpa_s->global->dbus;
1083	if (ctrl_iface == NULL)
1084		return 0;
1085
1086	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1087		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
1088		    wpa_s->dbus_new_path, nid);
1089
1090	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
1091		   net_obj_path);
1092	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
1093
1094	if (!ret)
1095		wpas_dbus_signal_network_removed(wpa_s, nid);
1096
1097	return ret;
1098}
1099
1100
1101static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
1102	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
1103	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
1104	  NULL,
1105	  R
1106	},
1107	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
1108	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
1109	  NULL,
1110	  R
1111	},
1112	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
1113	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
1114	  NULL,
1115	  R
1116	},
1117	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
1118	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
1119	  NULL,
1120	  R
1121	},
1122	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
1123	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
1124	  NULL,
1125	  R
1126	},
1127	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
1128	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
1129	  NULL,
1130	  R
1131	},
1132	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
1133	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates,
1134	  NULL,
1135	  R
1136	},
1137	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
1138	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpa,
1139	  NULL,
1140	  R
1141	},
1142	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
1143	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsn,
1144	  NULL,
1145	  R
1146	},
1147	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
1148	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ies,
1149	  NULL,
1150	  R
1151	},
1152	{ NULL, NULL, NULL, NULL, NULL, 0 }
1153};
1154
1155
1156static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
1157	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
1158	  {
1159		  { "properties", "a{sv}", ARG_OUT },
1160		  END_ARGS
1161	  }
1162	},
1163	{ NULL, NULL, { END_ARGS } }
1164};
1165
1166
1167/**
1168 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
1169 * @wpa_s: wpa_supplicant interface structure
1170 * @bssid: scanned network bssid
1171 * @id: unique BSS identifier
1172 * Returns: 0 on success, -1 on failure
1173 *
1174 * Unregisters BSS representing object from dbus
1175 */
1176int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
1177			     u8 bssid[ETH_ALEN], unsigned int id)
1178{
1179	struct wpas_dbus_priv *ctrl_iface;
1180	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1181
1182	/* Do nothing if the control interface is not turned on */
1183	if (wpa_s == NULL || wpa_s->global == NULL)
1184		return 0;
1185	ctrl_iface = wpa_s->global->dbus;
1186	if (ctrl_iface == NULL)
1187		return 0;
1188
1189	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1190		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1191		    wpa_s->dbus_new_path, id);
1192
1193	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
1194		   bss_obj_path);
1195	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
1196		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
1197			   bss_obj_path);
1198		return -1;
1199	}
1200
1201	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
1202
1203	return 0;
1204}
1205
1206
1207/**
1208 * wpas_dbus_register_bss - Register a scanned BSS with dbus
1209 * @wpa_s: wpa_supplicant interface structure
1210 * @bssid: scanned network bssid
1211 * @id: unique BSS identifier
1212 * Returns: 0 on success, -1 on failure
1213 *
1214 * Registers BSS representing object with dbus
1215 */
1216int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
1217			   u8 bssid[ETH_ALEN], unsigned int id)
1218{
1219	struct wpas_dbus_priv *ctrl_iface;
1220	struct wpa_dbus_object_desc *obj_desc;
1221	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1222	struct bss_handler_args *arg;
1223
1224	/* Do nothing if the control interface is not turned on */
1225	if (wpa_s == NULL || wpa_s->global == NULL)
1226		return 0;
1227	ctrl_iface = wpa_s->global->dbus;
1228	if (ctrl_iface == NULL)
1229		return 0;
1230
1231	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1232		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1233		    wpa_s->dbus_new_path, id);
1234
1235	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1236	if (!obj_desc) {
1237		wpa_printf(MSG_ERROR, "Not enough memory "
1238			   "to create object description");
1239		goto err;
1240	}
1241
1242	arg = os_zalloc(sizeof(struct bss_handler_args));
1243	if (!arg) {
1244		wpa_printf(MSG_ERROR, "Not enough memory "
1245			   "to create arguments for handler");
1246		goto err;
1247	}
1248	arg->wpa_s = wpa_s;
1249	arg->id = id;
1250
1251	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
1252			   wpas_dbus_bss_properties,
1253			   wpas_dbus_bss_signals);
1254
1255	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
1256		   bss_obj_path);
1257	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
1258					       wpa_s->ifname, obj_desc)) {
1259		wpa_printf(MSG_ERROR,
1260			   "Cannot register BSSID dbus object %s.",
1261			   bss_obj_path);
1262		goto err;
1263	}
1264
1265	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
1266
1267	return 0;
1268
1269err:
1270	free_dbus_object_desc(obj_desc);
1271	return -1;
1272}
1273
1274
1275static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
1276	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1277	  (WPADBusMethodHandler) &wpas_dbus_handler_scan,
1278	  {
1279		  { "args", "a{sv}", ARG_IN },
1280		  END_ARGS
1281	  }
1282	},
1283	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
1284	  (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
1285	  {
1286		  END_ARGS
1287	  }
1288	},
1289	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1290	  (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
1291	  {
1292		  { "args", "a{sv}", ARG_IN },
1293		  { "path", "o", ARG_OUT },
1294		  END_ARGS
1295	  }
1296	},
1297	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1298	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
1299	  {
1300		  { "path", "o", ARG_IN },
1301		  END_ARGS
1302	  }
1303	},
1304	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
1305	  (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
1306	  {
1307		  { "path", "o", ARG_IN },
1308		  END_ARGS
1309	  }
1310	},
1311	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1312	  (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
1313	  {
1314		  { "name", "s", ARG_IN },
1315		  { "data", "ay", ARG_IN },
1316		  END_ARGS
1317	  }
1318	},
1319	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1320	  (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
1321	  {
1322		  { "name", "s", ARG_IN },
1323		  { "data", "ay", ARG_OUT },
1324		  END_ARGS
1325	  }
1326	},
1327	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
1328	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
1329	  {
1330		  { "name", "s", ARG_IN },
1331		  END_ARGS
1332	  }
1333	},
1334#ifdef CONFIG_WPS
1335	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
1336	  (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
1337	  {
1338		  { "args", "a{sv}", ARG_IN },
1339		  { "output", "a{sv}", ARG_OUT },
1340		  END_ARGS
1341	  }
1342	},
1343#endif /* CONFIG_WPS */
1344	{ NULL, NULL, NULL, { END_ARGS } }
1345};
1346
1347static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
1348	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
1349	  (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
1350	  NULL, R
1351	},
1352	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1353	  (WPADBusPropertyAccessor) wpas_dbus_getter_state,
1354	  NULL, R
1355	},
1356	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
1357	  (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
1358	  NULL, R
1359	},
1360	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
1361	  (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
1362	  (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
1363	  RW
1364	},
1365	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1366	  (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
1367	  NULL, R
1368	},
1369	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1370	  (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
1371	  NULL, R
1372	},
1373	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
1374	  (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
1375	  NULL, R
1376	},
1377	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1378	  (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
1379	  NULL, R
1380	},
1381	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
1382	  (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
1383	  NULL, R
1384	},
1385	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
1386	  (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
1387	  NULL, R
1388	},
1389	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1390	  (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
1391	  NULL, R
1392	},
1393	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
1394	  (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
1395	  NULL, R
1396	},
1397#ifdef CONFIG_WPS
1398	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
1399	  (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
1400	  (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
1401	  RW
1402	},
1403#endif /* CONFIG_WPS */
1404	{ NULL, NULL, NULL, NULL, NULL, 0 }
1405};
1406
1407static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
1408	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
1409	  {
1410		  { "success", "b", ARG_OUT },
1411		  END_ARGS
1412	  }
1413	},
1414	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1415	  {
1416		  { "path", "o", ARG_OUT },
1417		  { "properties", "a{sv}", ARG_OUT },
1418		  END_ARGS
1419	  }
1420	},
1421	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1422	  {
1423		  { "path", "o", ARG_OUT },
1424		  END_ARGS
1425	  }
1426	},
1427	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1428	  {
1429		  { "name", "s", ARG_OUT },
1430		  END_ARGS
1431	  }
1432	},
1433	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1434	  {
1435		  { "name", "s", ARG_OUT },
1436		  END_ARGS
1437	  }
1438	},
1439	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
1440	  {
1441		  { "path", "o", ARG_OUT },
1442		  { "properties", "a{sv}", ARG_OUT },
1443		  END_ARGS
1444	  }
1445	},
1446	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
1447	  {
1448		  { "path", "o", ARG_OUT },
1449		  END_ARGS
1450	  }
1451	},
1452	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
1453	  {
1454		  { "path", "o", ARG_OUT },
1455		  END_ARGS
1456	  }
1457	},
1458	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
1459	  {
1460		  { "properties", "a{sv}", ARG_OUT },
1461		  END_ARGS
1462	  }
1463	},
1464#ifdef CONFIG_WPS
1465	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
1466	  {
1467		  { "name", "s", ARG_OUT },
1468		  { "args", "a{sv}", ARG_OUT },
1469		  END_ARGS
1470	  }
1471	},
1472	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
1473	  {
1474		  { "credentials", "a{sv}", ARG_OUT },
1475		  END_ARGS
1476	  }
1477	},
1478	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
1479	  {
1480		  { "properties", "a{sv}", ARG_OUT },
1481		  END_ARGS
1482	  }
1483	},
1484#endif /* CONFIG_WPS */
1485	{ NULL, NULL, { END_ARGS } }
1486};
1487
1488
1489int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
1490{
1491
1492	struct wpa_dbus_object_desc *obj_desc = NULL;
1493	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
1494	int next;
1495
1496	/* Do nothing if the control interface is not turned on */
1497	if (ctrl_iface == NULL)
1498		return 0;
1499
1500	/* Create and set the interface's object path */
1501	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
1502	if (wpa_s->dbus_new_path == NULL)
1503		return -1;
1504	next = ctrl_iface->next_objid++;
1505	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
1506		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
1507		    next);
1508
1509	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
1510	if (!obj_desc) {
1511		wpa_printf(MSG_ERROR, "Not enough memory "
1512			   "to create object description");
1513		goto err;
1514	}
1515
1516	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
1517			   wpas_dbus_interface_properties,
1518			   wpas_dbus_interface_signals);
1519
1520	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
1521		   wpa_s->dbus_new_path);
1522	if (wpa_dbus_register_object_per_iface(ctrl_iface,
1523					       wpa_s->dbus_new_path,
1524					       wpa_s->ifname, obj_desc))
1525		goto err;
1526
1527	wpas_dbus_signal_interface_added(wpa_s);
1528
1529	return 0;
1530
1531err:
1532	os_free(wpa_s->dbus_new_path);
1533	wpa_s->dbus_new_path = NULL;
1534	free_dbus_object_desc(obj_desc);
1535	return -1;
1536}
1537
1538
1539int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
1540{
1541	struct wpas_dbus_priv *ctrl_iface;
1542
1543	/* Do nothing if the control interface is not turned on */
1544	if (wpa_s == NULL || wpa_s->global == NULL)
1545		return 0;
1546	ctrl_iface = wpa_s->global->dbus;
1547	if (ctrl_iface == NULL)
1548		return 0;
1549
1550	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
1551		   wpa_s->dbus_new_path);
1552	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
1553						 wpa_s->dbus_new_path))
1554		return -1;
1555
1556	wpas_dbus_signal_interface_removed(wpa_s);
1557
1558	os_free(wpa_s->dbus_new_path);
1559	wpa_s->dbus_new_path = NULL;
1560
1561	return 0;
1562}
1563