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