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