xref: /freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.c (revision 884a2a699669ec61e2366e3e358342dbc94be24a)
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  */
40 static 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 
79 err:
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  */
91 static 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  */
103 static 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  */
117 void 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  */
154 static 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 
195 err:
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  */
208 static 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  */
222 static 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  */
237 static 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  */
271 void 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  */
285 void 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  */
301 static 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 
349 err:
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  */
362 static 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  */
376 static 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  */
390 void 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  */
404 void 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  */
426 void 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  */
465 void 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  */
506 void 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  */
570 void 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 
647 nomem:
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  */
662 void 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  */
715 void 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  */
768 void 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  */
782 void 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  */
796 void 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 
804 static 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 
829 static 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 
856 static 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 
885 static 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  */
917 int 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  */
956 void 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 
967 static void wpa_dbus_free(void *ptr)
968 {
969 	os_free(ptr);
970 }
971 
972 
973 static 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 
988 static 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  */
1007 int 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 
1058 err:
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  */
1072 int 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 
1101 static 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 
1156 static 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  */
1176 int 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  */
1216 int 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 
1269 err:
1270 	free_dbus_object_desc(obj_desc);
1271 	return -1;
1272 }
1273 
1274 
1275 static 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 
1347 static 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 
1407 static 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 
1489 int 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 
1531 err:
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 
1539 int 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