xref: /freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.c (revision 71e72c9e91c4b8007a4292e09669e8b549c29e97)
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 "ap/sta_info.h"
17 #include "../config.h"
18 #include "../wpa_supplicant_i.h"
19 #include "../bss.h"
20 #include "../wpas_glue.h"
21 #include "dbus_new_helpers.h"
22 #include "dbus_dict_helpers.h"
23 #include "dbus_new.h"
24 #include "dbus_new_handlers.h"
25 #include "dbus_common_i.h"
26 #include "dbus_new_handlers_p2p.h"
27 #include "p2p/p2p.h"
28 #include "../p2p_supplicant.h"
29 
30 #ifdef CONFIG_AP /* until needed by something else */
31 
32 /*
33  * NameOwnerChanged handling
34  *
35  * Some services we provide allow an application to register for
36  * a signal that it needs. While it can also unregister, we must
37  * be prepared for the case where the application simply crashes
38  * and thus doesn't clean up properly. The way to handle this in
39  * DBus is to register for the NameOwnerChanged signal which will
40  * signal an owner change to NULL if the peer closes the socket
41  * for whatever reason.
42  *
43  * Handle this signal via a filter function whenever necessary.
44  * The code below also handles refcounting in case in the future
45  * there will be multiple instances of this subscription scheme.
46  */
47 static const char wpas_dbus_noc_filter_str[] =
48 	"interface=org.freedesktop.DBus,member=NameOwnerChanged";
49 
50 
noc_filter(DBusConnection * conn,DBusMessage * message,void * data)51 static DBusHandlerResult noc_filter(DBusConnection *conn,
52 				    DBusMessage *message, void *data)
53 {
54 	struct wpas_dbus_priv *priv = data;
55 
56 	if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
57 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
58 
59 	if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
60 				   "NameOwnerChanged")) {
61 		const char *name;
62 		const char *prev_owner;
63 		const char *new_owner;
64 		DBusError derr;
65 		struct wpa_supplicant *wpa_s;
66 
67 		dbus_error_init(&derr);
68 
69 		if (!dbus_message_get_args(message, &derr,
70 					   DBUS_TYPE_STRING, &name,
71 					   DBUS_TYPE_STRING, &prev_owner,
72 					   DBUS_TYPE_STRING, &new_owner,
73 					   DBUS_TYPE_INVALID)) {
74 			/* Ignore this error */
75 			dbus_error_free(&derr);
76 			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
77 		}
78 
79 		for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
80 			if (wpa_s->preq_notify_peer != NULL &&
81 			    os_strcmp(name, wpa_s->preq_notify_peer) == 0 &&
82 			    (new_owner == NULL || os_strlen(new_owner) == 0)) {
83 				/* probe request owner disconnected */
84 				os_free(wpa_s->preq_notify_peer);
85 				wpa_s->preq_notify_peer = NULL;
86 				wpas_dbus_unsubscribe_noc(priv);
87 			}
88 		}
89 	}
90 
91 	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
92 }
93 
94 
wpas_dbus_subscribe_noc(struct wpas_dbus_priv * priv)95 void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv)
96 {
97 	priv->dbus_noc_refcnt++;
98 	if (priv->dbus_noc_refcnt > 1)
99 		return;
100 
101 	if (!dbus_connection_add_filter(priv->con, noc_filter, priv, NULL)) {
102 		wpa_printf(MSG_ERROR, "dbus: failed to add filter");
103 		return;
104 	}
105 
106 	dbus_bus_add_match(priv->con, wpas_dbus_noc_filter_str, NULL);
107 }
108 
109 
wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv * priv)110 void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv)
111 {
112 	priv->dbus_noc_refcnt--;
113 	if (priv->dbus_noc_refcnt > 0)
114 		return;
115 
116 	dbus_bus_remove_match(priv->con, wpas_dbus_noc_filter_str, NULL);
117 	dbus_connection_remove_filter(priv->con, noc_filter, priv);
118 }
119 
120 #endif /* CONFIG_AP */
121 
122 
123 /**
124  * wpas_dbus_signal_interface - Send a interface related event signal
125  * @wpa_s: %wpa_supplicant network interface data
126  * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
127  * @properties: Whether to add second argument with object properties
128  *
129  * Notify listeners about event related with interface
130  */
wpas_dbus_signal_interface(struct wpa_supplicant * wpa_s,const char * sig_name,dbus_bool_t properties)131 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
132 				       const char *sig_name,
133 				       dbus_bool_t properties)
134 {
135 	struct wpas_dbus_priv *iface;
136 	DBusMessage *msg;
137 	DBusMessageIter iter;
138 
139 	iface = wpa_s->global->dbus;
140 
141 	/* Do nothing if the control interface is not turned on */
142 	if (iface == NULL || !wpa_s->dbus_new_path)
143 		return;
144 
145 	msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
146 				      WPAS_DBUS_NEW_INTERFACE, sig_name);
147 	if (msg == NULL)
148 		return;
149 
150 	dbus_message_iter_init_append(msg, &iter);
151 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
152 					    &wpa_s->dbus_new_path) ||
153 	    (properties &&
154 	     !wpa_dbus_get_object_properties(
155 		     iface, wpa_s->dbus_new_path,
156 		     WPAS_DBUS_NEW_IFACE_INTERFACE, &iter)))
157 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
158 	else
159 		dbus_connection_send(iface->con, msg, NULL);
160 	dbus_message_unref(msg);
161 }
162 
163 
164 /**
165  * wpas_dbus_signal_interface_added - Send a interface created signal
166  * @wpa_s: %wpa_supplicant network interface data
167  *
168  * Notify listeners about creating new interface
169  */
wpas_dbus_signal_interface_added(struct wpa_supplicant * wpa_s)170 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
171 {
172 	wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
173 }
174 
175 
176 /**
177  * wpas_dbus_signal_interface_removed - Send a interface removed signal
178  * @wpa_s: %wpa_supplicant network interface data
179  *
180  * Notify listeners about removing interface
181  */
wpas_dbus_signal_interface_removed(struct wpa_supplicant * wpa_s)182 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
183 {
184 	wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
185 
186 }
187 
188 
189 /**
190  * wpas_dbus_signal_scan_done - send scan done signal
191  * @wpa_s: %wpa_supplicant network interface data
192  * @success: indicates if scanning succeed or failed
193  *
194  * Notify listeners about finishing a scan
195  */
wpas_dbus_signal_scan_done(struct wpa_supplicant * wpa_s,int success)196 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
197 {
198 	struct wpas_dbus_priv *iface;
199 	DBusMessage *msg;
200 	dbus_bool_t succ;
201 
202 	iface = wpa_s->global->dbus;
203 
204 	/* Do nothing if the control interface is not turned on */
205 	if (iface == NULL || !wpa_s->dbus_new_path)
206 		return;
207 
208 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
209 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
210 				      "ScanDone");
211 	if (msg == NULL)
212 		return;
213 
214 	succ = success ? TRUE : FALSE;
215 	if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
216 				     DBUS_TYPE_INVALID))
217 		dbus_connection_send(iface->con, msg, NULL);
218 	else
219 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
220 	dbus_message_unref(msg);
221 }
222 
223 
224 /**
225  * wpas_dbus_signal_bss - Send a BSS related event signal
226  * @wpa_s: %wpa_supplicant network interface data
227  * @bss_obj_path: BSS object path
228  * @sig_name: signal name - BSSAdded or BSSRemoved
229  * @properties: Whether to add second argument with object properties
230  *
231  * Notify listeners about event related with BSS
232  */
wpas_dbus_signal_bss(struct wpa_supplicant * wpa_s,const char * bss_obj_path,const char * sig_name,dbus_bool_t properties)233 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
234 				 const char *bss_obj_path,
235 				 const char *sig_name, dbus_bool_t properties)
236 {
237 	struct wpas_dbus_priv *iface;
238 	DBusMessage *msg;
239 	DBusMessageIter iter;
240 
241 	iface = wpa_s->global->dbus;
242 
243 	/* Do nothing if the control interface is not turned on */
244 	if (iface == NULL || !wpa_s->dbus_new_path)
245 		return;
246 
247 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
248 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
249 				      sig_name);
250 	if (msg == NULL)
251 		return;
252 
253 	dbus_message_iter_init_append(msg, &iter);
254 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
255 					    &bss_obj_path) ||
256 	    (properties &&
257 	     !wpa_dbus_get_object_properties(iface, bss_obj_path,
258 					     WPAS_DBUS_NEW_IFACE_BSS,
259 					     &iter)))
260 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
261 	else
262 		dbus_connection_send(iface->con, msg, NULL);
263 	dbus_message_unref(msg);
264 }
265 
266 
267 /**
268  * wpas_dbus_signal_bss_added - Send a BSS added signal
269  * @wpa_s: %wpa_supplicant network interface data
270  * @bss_obj_path: new BSS object path
271  *
272  * Notify listeners about adding new BSS
273  */
wpas_dbus_signal_bss_added(struct wpa_supplicant * wpa_s,const char * bss_obj_path)274 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
275 				       const char *bss_obj_path)
276 {
277 	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
278 }
279 
280 
281 /**
282  * wpas_dbus_signal_bss_removed - Send a BSS removed signal
283  * @wpa_s: %wpa_supplicant network interface data
284  * @bss_obj_path: BSS object path
285  *
286  * Notify listeners about removing BSS
287  */
wpas_dbus_signal_bss_removed(struct wpa_supplicant * wpa_s,const char * bss_obj_path)288 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
289 					 const char *bss_obj_path)
290 {
291 	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
292 }
293 
294 
295 /**
296  * wpas_dbus_signal_blob - Send a blob related event signal
297  * @wpa_s: %wpa_supplicant network interface data
298  * @name: blob name
299  * @sig_name: signal name - BlobAdded or BlobRemoved
300  *
301  * Notify listeners about event related with blob
302  */
wpas_dbus_signal_blob(struct wpa_supplicant * wpa_s,const char * name,const char * sig_name)303 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
304 				  const char *name, const char *sig_name)
305 {
306 	struct wpas_dbus_priv *iface;
307 	DBusMessage *msg;
308 
309 	iface = wpa_s->global->dbus;
310 
311 	/* Do nothing if the control interface is not turned on */
312 	if (iface == NULL || !wpa_s->dbus_new_path)
313 		return;
314 
315 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
316 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
317 				      sig_name);
318 	if (msg == NULL)
319 		return;
320 
321 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
322 				     DBUS_TYPE_INVALID))
323 		dbus_connection_send(iface->con, msg, NULL);
324 	else
325 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
326 	dbus_message_unref(msg);
327 }
328 
329 
330 /**
331  * wpas_dbus_signal_blob_added - Send a blob added signal
332  * @wpa_s: %wpa_supplicant network interface data
333  * @name: blob name
334  *
335  * Notify listeners about adding a new blob
336  */
wpas_dbus_signal_blob_added(struct wpa_supplicant * wpa_s,const char * name)337 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
338 				 const char *name)
339 {
340 	wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
341 }
342 
343 
344 /**
345  * wpas_dbus_signal_blob_removed - Send a blob removed signal
346  * @wpa_s: %wpa_supplicant network interface data
347  * @name: blob name
348  *
349  * Notify listeners about removing blob
350  */
wpas_dbus_signal_blob_removed(struct wpa_supplicant * wpa_s,const char * name)351 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
352 				   const char *name)
353 {
354 	wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
355 }
356 
357 
358 /**
359  * wpas_dbus_signal_network - Send a network related event signal
360  * @wpa_s: %wpa_supplicant network interface data
361  * @id: new network id
362  * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
363  * @properties: determines if add second argument with object properties
364  *
365  * Notify listeners about event related with configured network
366  */
wpas_dbus_signal_network(struct wpa_supplicant * wpa_s,int id,const char * sig_name,dbus_bool_t properties)367 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
368 				     int id, const char *sig_name,
369 				     dbus_bool_t properties)
370 {
371 	struct wpas_dbus_priv *iface;
372 	DBusMessage *msg;
373 	DBusMessageIter iter;
374 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
375 
376 	iface = wpa_s->global->dbus;
377 
378 	/* Do nothing if the control interface is not turned on */
379 	if (iface == NULL || !wpa_s->dbus_new_path)
380 		return;
381 
382 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
383 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
384 		    wpa_s->dbus_new_path, id);
385 
386 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
387 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
388 				      sig_name);
389 	if (msg == NULL)
390 		return;
391 
392 	dbus_message_iter_init_append(msg, &iter);
393 	path = net_obj_path;
394 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
395 					    &path) ||
396 	    (properties &&
397 	     !wpa_dbus_get_object_properties(
398 		     iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK,
399 		     &iter)))
400 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
401 	else
402 		dbus_connection_send(iface->con, msg, NULL);
403 	dbus_message_unref(msg);
404 }
405 
406 
407 /**
408  * wpas_dbus_signal_network_added - Send a network added signal
409  * @wpa_s: %wpa_supplicant network interface data
410  * @id: new network id
411  *
412  * Notify listeners about adding new network
413  */
wpas_dbus_signal_network_added(struct wpa_supplicant * wpa_s,int id)414 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
415 					   int id)
416 {
417 	wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
418 }
419 
420 
421 /**
422  * wpas_dbus_signal_network_removed - Send a network removed signal
423  * @wpa_s: %wpa_supplicant network interface data
424  * @id: network id
425  *
426  * Notify listeners about removing a network
427  */
wpas_dbus_signal_network_removed(struct wpa_supplicant * wpa_s,int id)428 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
429 					     int id)
430 {
431 	wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
432 }
433 
434 
435 /**
436  * wpas_dbus_signal_network_selected - Send a network selected signal
437  * @wpa_s: %wpa_supplicant network interface data
438  * @id: network id
439  *
440  * Notify listeners about selecting a network
441  */
wpas_dbus_signal_network_selected(struct wpa_supplicant * wpa_s,int id)442 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
443 {
444 	wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
445 }
446 
447 
448 /**
449  * wpas_dbus_signal_network_request - Indicate that additional information
450  * (EAP password, etc.) is required to complete the association to this SSID
451  * @wpa_s: %wpa_supplicant network interface data
452  * @rtype: The specific additional information required
453  * @default_text: Optional description of required information
454  *
455  * Request additional information or passwords to complete an association
456  * request.
457  */
wpas_dbus_signal_network_request(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,enum wpa_ctrl_req_type rtype,const char * default_txt)458 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s,
459 				      struct wpa_ssid *ssid,
460 				      enum wpa_ctrl_req_type rtype,
461 				      const char *default_txt)
462 {
463 	struct wpas_dbus_priv *iface;
464 	DBusMessage *msg;
465 	DBusMessageIter iter;
466 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
467 	const char *field, *txt = NULL, *net_ptr;
468 
469 	iface = wpa_s->global->dbus;
470 
471 	/* Do nothing if the control interface is not turned on */
472 	if (iface == NULL || !wpa_s->dbus_new_path)
473 		return;
474 
475 	field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt);
476 	if (field == NULL)
477 		return;
478 
479 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
480 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
481 				      "NetworkRequest");
482 	if (msg == NULL)
483 		return;
484 
485 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
486 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
487 		    wpa_s->dbus_new_path, ssid->id);
488 	net_ptr = &net_obj_path[0];
489 
490 	dbus_message_iter_init_append(msg, &iter);
491 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
492 					    &net_ptr) ||
493 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field) ||
494 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt))
495 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
496 	else
497 		dbus_connection_send(iface->con, msg, NULL);
498 	dbus_message_unref(msg);
499 }
500 
501 
502 /**
503  * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
504  * @wpa_s: %wpa_supplicant network interface data
505  * @ssid: configured network which Enabled property has changed
506  *
507  * Sends PropertyChanged signals containing new value of Enabled property
508  * for specified network
509  */
wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)510 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
511 					      struct wpa_ssid *ssid)
512 {
513 
514 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
515 
516 	if (!wpa_s->dbus_new_path)
517 		return;
518 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
519 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
520 		    wpa_s->dbus_new_path, ssid->id);
521 
522 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
523 				       WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
524 }
525 
526 
527 #ifdef CONFIG_WPS
528 
529 /**
530  * wpas_dbus_signal_wps_event_pbc_overlap - Signals PBC overlap WPS event
531  * @wpa_s: %wpa_supplicant network interface data
532  *
533  * Sends Event dbus signal with name "pbc-overlap" and empty dict as arguments
534  */
wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant * wpa_s)535 void wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
536 {
537 
538 	DBusMessage *msg;
539 	DBusMessageIter iter, dict_iter;
540 	struct wpas_dbus_priv *iface;
541 	char *key = "pbc-overlap";
542 
543 	iface = wpa_s->global->dbus;
544 
545 	/* Do nothing if the control interface is not turned on */
546 	if (iface == NULL || !wpa_s->dbus_new_path)
547 		return;
548 
549 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
550 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
551 	if (msg == NULL)
552 		return;
553 
554 	dbus_message_iter_init_append(msg, &iter);
555 
556 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
557 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
558 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
559 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
560 	else
561 		dbus_connection_send(iface->con, msg, NULL);
562 
563 	dbus_message_unref(msg);
564 }
565 
566 
567 /**
568  * wpas_dbus_signal_wps_event_success - Signals Success WPS event
569  * @wpa_s: %wpa_supplicant network interface data
570  *
571  * Sends Event dbus signal with name "success" and empty dict as arguments
572  */
wpas_dbus_signal_wps_event_success(struct wpa_supplicant * wpa_s)573 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
574 {
575 
576 	DBusMessage *msg;
577 	DBusMessageIter iter, dict_iter;
578 	struct wpas_dbus_priv *iface;
579 	char *key = "success";
580 
581 	iface = wpa_s->global->dbus;
582 
583 	/* Do nothing if the control interface is not turned on */
584 	if (iface == NULL || !wpa_s->dbus_new_path)
585 		return;
586 
587 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
588 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
589 	if (msg == NULL)
590 		return;
591 
592 	dbus_message_iter_init_append(msg, &iter);
593 
594 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
595 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
596 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
597 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
598 	else
599 		dbus_connection_send(iface->con, msg, NULL);
600 
601 	dbus_message_unref(msg);
602 }
603 
604 
605 /**
606  * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
607  * @wpa_s: %wpa_supplicant network interface data
608  * @fail: WPS failure information
609  *
610  * Sends Event dbus signal with name "fail" and dictionary containing
611  * "msg field with fail message number (int32) as arguments
612  */
wpas_dbus_signal_wps_event_fail(struct wpa_supplicant * wpa_s,struct wps_event_fail * fail)613 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
614 				     struct wps_event_fail *fail)
615 {
616 
617 	DBusMessage *msg;
618 	DBusMessageIter iter, dict_iter;
619 	struct wpas_dbus_priv *iface;
620 	char *key = "fail";
621 
622 	iface = wpa_s->global->dbus;
623 
624 	/* Do nothing if the control interface is not turned on */
625 	if (iface == NULL || !wpa_s->dbus_new_path)
626 		return;
627 
628 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
629 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
630 	if (msg == NULL)
631 		return;
632 
633 	dbus_message_iter_init_append(msg, &iter);
634 
635 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
636 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
637 	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
638 	    !wpa_dbus_dict_append_int32(&dict_iter, "config_error",
639 					fail->config_error) ||
640 	    !wpa_dbus_dict_append_int32(&dict_iter, "error_indication",
641 					fail->error_indication) ||
642 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
643 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
644 	else
645 		dbus_connection_send(iface->con, msg, NULL);
646 
647 	dbus_message_unref(msg);
648 }
649 
650 
651 /**
652  * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
653  * @wpa_s: %wpa_supplicant network interface data
654  * @m2d: M2D event data information
655  *
656  * Sends Event dbus signal with name "m2d" and dictionary containing
657  * fields of wps_event_m2d structure.
658  */
wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant * wpa_s,struct wps_event_m2d * m2d)659 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
660 				    struct wps_event_m2d *m2d)
661 {
662 
663 	DBusMessage *msg;
664 	DBusMessageIter iter, dict_iter;
665 	struct wpas_dbus_priv *iface;
666 	char *key = "m2d";
667 
668 	iface = wpa_s->global->dbus;
669 
670 	/* Do nothing if the control interface is not turned on */
671 	if (iface == NULL || !wpa_s->dbus_new_path)
672 		return;
673 
674 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
675 				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
676 	if (msg == NULL)
677 		return;
678 
679 	dbus_message_iter_init_append(msg, &iter);
680 
681 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
682 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
683 	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
684 					 m2d->config_methods) ||
685 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
686 					     (const char *) m2d->manufacturer,
687 					     m2d->manufacturer_len) ||
688 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
689 					     (const char *) m2d->model_name,
690 					     m2d->model_name_len) ||
691 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
692 					     (const char *) m2d->model_number,
693 					     m2d->model_number_len) ||
694 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
695 					     (const char *)
696 					     m2d->serial_number,
697 					     m2d->serial_number_len) ||
698 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
699 					     (const char *) m2d->dev_name,
700 					     m2d->dev_name_len) ||
701 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
702 					     (const char *)
703 					     m2d->primary_dev_type, 8) ||
704 	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
705 					 m2d->config_error) ||
706 	    !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
707 					 m2d->dev_password_id) ||
708 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
709 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
710 	else
711 		dbus_connection_send(iface->con, msg, NULL);
712 
713 	dbus_message_unref(msg);
714 }
715 
716 
717 /**
718  * wpas_dbus_signal_wps_cred - Signals new credentials
719  * @wpa_s: %wpa_supplicant network interface data
720  * @cred: WPS Credential information
721  *
722  * Sends signal with credentials in directory argument
723  */
wpas_dbus_signal_wps_cred(struct wpa_supplicant * wpa_s,const struct wps_credential * cred)724 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
725 			       const struct wps_credential *cred)
726 {
727 	DBusMessage *msg;
728 	DBusMessageIter iter, dict_iter;
729 	struct wpas_dbus_priv *iface;
730 	char *auth_type[5]; /* we have five possible authentication types */
731 	int at_num = 0;
732 	char *encr_type[3]; /* we have three possible encryption types */
733 	int et_num = 0;
734 
735 	iface = wpa_s->global->dbus;
736 
737 	/* Do nothing if the control interface is not turned on */
738 	if (iface == NULL || !wpa_s->dbus_new_path)
739 		return;
740 
741 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
742 				      WPAS_DBUS_NEW_IFACE_WPS,
743 				      "Credentials");
744 	if (msg == NULL)
745 		return;
746 
747 	dbus_message_iter_init_append(msg, &iter);
748 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
749 		goto nomem;
750 
751 	if (cred->auth_type & WPS_AUTH_OPEN)
752 		auth_type[at_num++] = "open";
753 #ifndef CONFIG_NO_TKIP
754 	if (cred->auth_type & WPS_AUTH_WPAPSK)
755 		auth_type[at_num++] = "wpa-psk";
756 	if (cred->auth_type & WPS_AUTH_WPA)
757 		auth_type[at_num++] = "wpa-eap";
758 #endif /* CONFIG_NO_TKIP */
759 	if (cred->auth_type & WPS_AUTH_WPA2)
760 		auth_type[at_num++] = "wpa2-eap";
761 	if (cred->auth_type & WPS_AUTH_WPA2PSK)
762 		auth_type[at_num++] = "wpa2-psk";
763 
764 	if (cred->encr_type & WPS_ENCR_NONE)
765 		encr_type[et_num++] = "none";
766 #ifndef CONFIG_NO_TKIP
767 	if (cred->encr_type & WPS_ENCR_TKIP)
768 		encr_type[et_num++] = "tkip";
769 #endif /* CONFIG_NO_TKIP */
770 	if (cred->encr_type & WPS_ENCR_AES)
771 		encr_type[et_num++] = "aes";
772 
773 	if ((wpa_s->current_ssid &&
774 	     !wpa_dbus_dict_append_byte_array(
775 		     &dict_iter, "BSSID",
776 		     (const char *) wpa_s->current_ssid->bssid, ETH_ALEN)) ||
777 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
778 					     (const char *) cred->ssid,
779 					     cred->ssid_len) ||
780 	    !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
781 					       (const char **) auth_type,
782 					       at_num) ||
783 	    !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
784 					       (const char **) encr_type,
785 					       et_num) ||
786 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
787 					     (const char *) cred->key,
788 					     cred->key_len) ||
789 	    !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
790 					 cred->key_idx) ||
791 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
792 		goto nomem;
793 
794 	dbus_connection_send(iface->con, msg, NULL);
795 
796 nomem:
797 	dbus_message_unref(msg);
798 }
799 
800 #endif /* CONFIG_WPS */
801 
802 
803 #ifdef CONFIG_MESH
804 
wpas_dbus_signal_mesh_group_started(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)805 void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
806 					 struct wpa_ssid *ssid)
807 {
808 	struct wpas_dbus_priv *iface;
809 	DBusMessage *msg;
810 	DBusMessageIter iter, dict_iter;
811 
812 	iface = wpa_s->global->dbus;
813 
814 	/* Do nothing if the control interface is not turned on */
815 	if (!iface || !wpa_s->dbus_new_path)
816 		return;
817 
818 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
819 				      WPAS_DBUS_NEW_IFACE_MESH,
820 				      "MeshGroupStarted");
821 	if (!msg)
822 		return;
823 
824 	dbus_message_iter_init_append(msg, &iter);
825 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
826 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
827 					     (const char *) ssid->ssid,
828 					     ssid->ssid_len) ||
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_mesh_group_removed(struct wpa_supplicant * wpa_s,const u8 * meshid,u8 meshid_len,int reason)837 void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
838 					 const u8 *meshid, u8 meshid_len,
839 					 int reason)
840 {
841 	struct wpas_dbus_priv *iface;
842 	DBusMessage *msg;
843 	DBusMessageIter iter, dict_iter;
844 
845 	iface = wpa_s->global->dbus;
846 
847 	/* Do nothing if the control interface is not turned on */
848 	if (!iface || !wpa_s->dbus_new_path)
849 		return;
850 
851 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
852 				      WPAS_DBUS_NEW_IFACE_MESH,
853 				      "MeshGroupRemoved");
854 	if (!msg)
855 		return;
856 
857 	dbus_message_iter_init_append(msg, &iter);
858 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
859 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
860 					     (const char *) meshid,
861 					     meshid_len) ||
862 	    !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
863 					reason) ||
864 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
865 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
866 	else
867 		dbus_connection_send(iface->con, msg, NULL);
868 	dbus_message_unref(msg);
869 }
870 
871 
wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant * wpa_s,const u8 * peer_addr)872 void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
873 					  const u8 *peer_addr)
874 {
875 	struct wpas_dbus_priv *iface;
876 	DBusMessage *msg;
877 	DBusMessageIter iter, dict_iter;
878 
879 	iface = wpa_s->global->dbus;
880 
881 	/* Do nothing if the control interface is not turned on */
882 	if (!iface || !wpa_s->dbus_new_path)
883 		return;
884 
885 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
886 				      WPAS_DBUS_NEW_IFACE_MESH,
887 				      "MeshPeerConnected");
888 	if (!msg)
889 		return;
890 
891 	dbus_message_iter_init_append(msg, &iter);
892 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
893 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
894 					     (const char *) peer_addr,
895 					     ETH_ALEN) ||
896 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
897 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
898 	else
899 		dbus_connection_send(iface->con, msg, NULL);
900 	dbus_message_unref(msg);
901 }
902 
903 
wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * peer_addr,int reason)904 void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
905 					     const u8 *peer_addr, int reason)
906 {
907 	struct wpas_dbus_priv *iface;
908 	DBusMessage *msg;
909 	DBusMessageIter iter, dict_iter;
910 
911 	iface = wpa_s->global->dbus;
912 
913 	/* Do nothing if the control interface is not turned on */
914 	if (!iface || !wpa_s->dbus_new_path)
915 		return;
916 
917 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
918 				      WPAS_DBUS_NEW_IFACE_MESH,
919 				      "MeshPeerDisconnected");
920 	if (!msg)
921 		return;
922 
923 	dbus_message_iter_init_append(msg, &iter);
924 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
925 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
926 					     (const char *) peer_addr,
927 					     ETH_ALEN) ||
928 	    !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
929 					reason) ||
930 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
931 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
932 	else
933 		dbus_connection_send(iface->con, msg, NULL);
934 	dbus_message_unref(msg);
935 }
936 
937 #endif /* CONFIG_MESH */
938 
939 
940 #ifdef CONFIG_INTERWORKING
941 
wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,struct wpa_cred * cred,const char * type,int excluded,int bh,int bss_load,int conn_capab)942 void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
943 					    struct wpa_bss *bss,
944 					    struct wpa_cred *cred,
945 					    const char *type,
946 					    int excluded,
947 					    int bh,
948 					    int bss_load,
949 					    int conn_capab)
950 {
951 	struct wpas_dbus_priv *iface;
952 	DBusMessage *msg;
953 	DBusMessageIter iter, dict_iter;
954 	char bss_path[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path;
955 	char cred_path[WPAS_DBUS_OBJECT_PATH_MAX], *cred_obj_path;
956 
957 	iface = wpa_s->global->dbus;
958 
959 	/* Do nothing if the control interface is not turned on */
960 	if (!iface || !wpa_s->dbus_new_path)
961 		return;
962 
963 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
964 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
965 				      "InterworkingAPAdded");
966 	if (!msg)
967 		return;
968 
969 	os_snprintf(bss_path, WPAS_DBUS_OBJECT_PATH_MAX,
970 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
971 		    wpa_s->dbus_new_path, bss->id);
972 	bss_obj_path = bss_path;
973 
974 	os_snprintf(cred_path, WPAS_DBUS_OBJECT_PATH_MAX,
975 		    "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%u",
976 		    wpa_s->dbus_new_path, cred->id);
977 	cred_obj_path = cred_path;
978 
979 	dbus_message_iter_init_append(msg, &iter);
980 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
981 					    &bss_obj_path) ||
982 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
983 					    &cred_obj_path) ||
984 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
985 	    !wpa_dbus_dict_append_string(&dict_iter, "type", type) ||
986 	    !wpa_dbus_dict_append_int32(&dict_iter, "excluded", excluded) ||
987 	    !wpa_dbus_dict_append_int32(&dict_iter, "priority",
988 					cred->priority) ||
989 	    !wpa_dbus_dict_append_int32(&dict_iter, "sp_priority",
990 					cred->sp_priority) ||
991 	    !wpa_dbus_dict_append_int32(&dict_iter, "below_min_backhaul", bh) ||
992 	    !wpa_dbus_dict_append_int32(&dict_iter, "over_max_bss_load",
993 					bss_load) ||
994 	    !wpa_dbus_dict_append_int32(&dict_iter, "conn_capab_missing",
995 					conn_capab) ||
996 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
997 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
998 	else
999 		dbus_connection_send(iface->con, msg, NULL);
1000 	dbus_message_unref(msg);
1001 }
1002 
1003 
wpas_dbus_signal_interworking_select_done(struct wpa_supplicant * wpa_s)1004 void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
1005 {
1006 	struct wpas_dbus_priv *iface;
1007 	DBusMessage *msg;
1008 
1009 	iface = wpa_s->global->dbus;
1010 
1011 	/* Do nothing if the control interface is not turned on */
1012 	if (!iface || !wpa_s->dbus_new_path)
1013 		return;
1014 
1015 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1016 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
1017 				      "InterworkingSelectDone");
1018 	if (!msg)
1019 		return;
1020 
1021 	dbus_connection_send(iface->con, msg, NULL);
1022 
1023 	dbus_message_unref(msg);
1024 }
1025 
1026 
wpas_dbus_signal_anqp_query_done(struct wpa_supplicant * wpa_s,const u8 * dst,const char * result)1027 void wpas_dbus_signal_anqp_query_done(struct wpa_supplicant *wpa_s,
1028 				      const u8 *dst, const char *result)
1029 {
1030 	struct wpas_dbus_priv *iface;
1031 	DBusMessage *msg;
1032 	DBusMessageIter iter;
1033 	char addr[WPAS_DBUS_OBJECT_PATH_MAX], *bssid;
1034 
1035 	os_snprintf(addr, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(dst));
1036 	bssid = addr;
1037 
1038 	iface = wpa_s->global->dbus;
1039 
1040 	/* Do nothing if the control interface is not turned on */
1041 	if (!iface || !wpa_s->dbus_new_path)
1042 		return;
1043 
1044 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1045 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
1046 				      "ANQPQueryDone");
1047 	if (!msg)
1048 		return;
1049 
1050 	dbus_message_iter_init_append(msg, &iter);
1051 
1052 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bssid) ||
1053 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &result))
1054 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1055 	else
1056 		dbus_connection_send(iface->con, msg, NULL);
1057 	dbus_message_unref(msg);
1058 }
1059 
1060 #endif /* CONFIG_INTERWORKING */
1061 
1062 
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)1063 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
1064 				    int depth, const char *subject,
1065 				    const char *altsubject[],
1066 				    int num_altsubject,
1067 				    const char *cert_hash,
1068 				    const struct wpabuf *cert)
1069 {
1070 	struct wpas_dbus_priv *iface;
1071 	DBusMessage *msg;
1072 	DBusMessageIter iter, dict_iter;
1073 
1074 	iface = wpa_s->global->dbus;
1075 
1076 	/* Do nothing if the control interface is not turned on */
1077 	if (iface == NULL || !wpa_s->dbus_new_path)
1078 		return;
1079 
1080 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1081 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
1082 				      "Certification");
1083 	if (msg == NULL)
1084 		return;
1085 
1086 	dbus_message_iter_init_append(msg, &iter);
1087 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1088 	    !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
1089 	    !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) ||
1090 	    (altsubject && num_altsubject &&
1091 	     !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject",
1092 						altsubject, num_altsubject)) ||
1093 	    (cert_hash &&
1094 	     !wpa_dbus_dict_append_string(&dict_iter, "cert_hash",
1095 					  cert_hash)) ||
1096 	    (cert &&
1097 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
1098 					      wpabuf_head(cert),
1099 					      wpabuf_len(cert))) ||
1100 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1101 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1102 	else
1103 		dbus_connection_send(iface->con, msg, NULL);
1104 	dbus_message_unref(msg);
1105 }
1106 
1107 
wpas_dbus_signal_eap_status(struct wpa_supplicant * wpa_s,const char * status,const char * parameter)1108 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
1109 				 const char *status, const char *parameter)
1110 {
1111 	struct wpas_dbus_priv *iface;
1112 	DBusMessage *msg;
1113 	DBusMessageIter iter;
1114 
1115 	iface = wpa_s->global->dbus;
1116 
1117 	/* Do nothing if the control interface is not turned on */
1118 	if (iface == NULL || !wpa_s->dbus_new_path)
1119 		return;
1120 
1121 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1122 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
1123 				      "EAP");
1124 	if (msg == NULL)
1125 		return;
1126 
1127 	dbus_message_iter_init_append(msg, &iter);
1128 
1129 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) ||
1130 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1131 					    &parameter))
1132 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1133 	else
1134 		dbus_connection_send(iface->con, msg, NULL);
1135 	dbus_message_unref(msg);
1136 }
1137 
1138 
wpas_dbus_signal_psk_mismatch(struct wpa_supplicant * wpa_s)1139 void wpas_dbus_signal_psk_mismatch(struct wpa_supplicant *wpa_s)
1140 {
1141 	struct wpas_dbus_priv *iface;
1142 	DBusMessage *msg;
1143 
1144 	iface = wpa_s->global->dbus;
1145 
1146 	/* Do nothing if the control interface is not turned on */
1147 	if (!iface || !wpa_s->dbus_new_path)
1148 		return;
1149 
1150 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1151 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
1152 				      "PskMismatch");
1153 	if (!msg)
1154 		return;
1155 
1156 	dbus_connection_send(iface->con, msg, NULL);
1157 
1158 	dbus_message_unref(msg);
1159 }
1160 
1161 
wpas_dbus_signal_sae_password_mismatch(struct wpa_supplicant * wpa_s)1162 void wpas_dbus_signal_sae_password_mismatch(struct wpa_supplicant *wpa_s)
1163 {
1164 	struct wpas_dbus_priv *iface;
1165 	DBusMessage *msg;
1166 
1167 	iface = wpa_s->global->dbus;
1168 
1169 	/* Do nothing if the control interface is not turned on */
1170 	if (!iface || !wpa_s->dbus_new_path)
1171 		return;
1172 
1173 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1174 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
1175 				      "SaePasswordMismatch");
1176 	if (!msg)
1177 		return;
1178 
1179 	dbus_connection_send(iface->con, msg, NULL);
1180 
1181 	dbus_message_unref(msg);
1182 }
1183 
1184 
1185 /**
1186  * wpas_dbus_signal_sta - Send a station related event signal
1187  * @wpa_s: %wpa_supplicant network interface data
1188  * @sta: station mac address
1189  * @sig_name: signal name - StaAuthorized or StaDeauthorized
1190  *
1191  * Notify listeners about event related with station
1192  */
wpas_dbus_signal_sta(struct wpa_supplicant * wpa_s,const u8 * sta,const char * sig_name)1193 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s,
1194 				 const u8 *sta, const char *sig_name)
1195 {
1196 	struct wpas_dbus_priv *iface;
1197 	DBusMessage *msg;
1198 	char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX];
1199 	char *dev_mac;
1200 
1201 	os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta));
1202 	dev_mac = sta_mac;
1203 
1204 	iface = wpa_s->global->dbus;
1205 
1206 	/* Do nothing if the control interface is not turned on */
1207 	if (iface == NULL || !wpa_s->dbus_new_path)
1208 		return;
1209 
1210 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1211 				      WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1212 	if (msg == NULL)
1213 		return;
1214 
1215 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac,
1216 				     DBUS_TYPE_INVALID))
1217 		dbus_connection_send(iface->con, msg, NULL);
1218 	else
1219 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1220 	dbus_message_unref(msg);
1221 
1222 	wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'",
1223 		   sta_mac, sig_name);
1224 }
1225 
1226 
1227 /**
1228  * wpas_dbus_signal_sta_authorized - Send a STA authorized signal
1229  * @wpa_s: %wpa_supplicant network interface data
1230  * @sta: station mac address
1231  *
1232  * Notify listeners a new station has been authorized
1233  */
wpas_dbus_signal_sta_authorized(struct wpa_supplicant * wpa_s,const u8 * sta)1234 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
1235 				     const u8 *sta)
1236 {
1237 	wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized");
1238 }
1239 
1240 
1241 /**
1242  * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal
1243  * @wpa_s: %wpa_supplicant network interface data
1244  * @sta: station mac address
1245  *
1246  * Notify listeners a station has been deauthorized
1247  */
wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant * wpa_s,const u8 * sta)1248 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
1249 				       const u8 *sta)
1250 {
1251 	wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized");
1252 }
1253 
1254 
1255 /**
1256  * wpas_dbus_signal_station - Send an event signal related to a station object
1257  * @wpa_s: %wpa_supplicant network interface data
1258  * @station_obj_path: Station object path
1259  * @sig_name: signal name - StationAdded or StationRemoved
1260  * @properties: Whether to add second argument with object properties
1261  *
1262  * Notify listeners about event related with station.
1263  */
wpas_dbus_signal_station(struct wpa_supplicant * wpa_s,const char * station_obj_path,const char * sig_name,dbus_bool_t properties)1264 static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s,
1265 				     const char *station_obj_path,
1266 				     const char *sig_name,
1267 				     dbus_bool_t properties)
1268 {
1269 	struct wpas_dbus_priv *iface;
1270 	DBusMessage *msg;
1271 	DBusMessageIter iter;
1272 
1273 	iface = wpa_s->global->dbus;
1274 
1275 	/* Do nothing if the control interface is not turned on */
1276 	if (!iface || !wpa_s->dbus_new_path)
1277 		return;
1278 
1279 	wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name);
1280 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1281 				      WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1282 	if (!msg)
1283 		return;
1284 
1285 	dbus_message_iter_init_append(msg, &iter);
1286 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1287 					    &station_obj_path) ||
1288 	    (properties &&
1289 	     !wpa_dbus_get_object_properties(iface, station_obj_path,
1290 					     WPAS_DBUS_NEW_IFACE_STA,
1291 					     &iter)))
1292 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1293 	else
1294 		dbus_connection_send(iface->con, msg, NULL);
1295 	dbus_message_unref(msg);
1296 }
1297 
1298 
1299 /**
1300  * wpas_dbus_signal_station_added - Send a Station added signal
1301  * @wpa_s: %wpa_supplicant network interface data
1302  * @station_obj_path: new Station object path
1303  *
1304  * Notify listeners about adding new Station
1305  */
wpas_dbus_signal_station_added(struct wpa_supplicant * wpa_s,const char * station_obj_path)1306 static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s,
1307 					   const char *station_obj_path)
1308 {
1309 	wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE);
1310 }
1311 
1312 
1313 /**
1314  * wpas_dbus_signal_station_removed - Send a Station removed signal
1315  * @wpa_s: %wpa_supplicant network interface data
1316  * @station_obj_path: Station object path
1317  *
1318  * Notify listeners about removing Station
1319  */
wpas_dbus_signal_station_removed(struct wpa_supplicant * wpa_s,const char * station_obj_path)1320 static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s,
1321 					     const char *station_obj_path)
1322 {
1323 	wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved",
1324 				 FALSE);
1325 }
1326 
1327 
1328 #ifdef CONFIG_P2P
1329 
1330 /**
1331  * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
1332  * @wpa_s: %wpa_supplicant network interface data
1333  * @role: role of this device (client or GO)
1334  * Sends signal with i/f name and role as string arguments
1335  */
wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant * wpa_s,const char * role)1336 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
1337 					const char *role)
1338 {
1339 	DBusMessage *msg;
1340 	DBusMessageIter iter, dict_iter;
1341 	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
1342 	struct wpa_supplicant *parent;
1343 
1344 	/* Do nothing if the control interface is not turned on */
1345 	if (iface == NULL)
1346 		return;
1347 
1348 	parent = wpa_s->parent;
1349 	if (parent->p2p_mgmt)
1350 		parent = parent->parent;
1351 
1352 	if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path ||
1353 	    !parent->dbus_new_path)
1354 		return;
1355 
1356 	msg = dbus_message_new_signal(parent->dbus_new_path,
1357 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1358 				      "GroupFinished");
1359 	if (msg == NULL)
1360 		return;
1361 
1362 	dbus_message_iter_init_append(msg, &iter);
1363 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1364 	    !wpa_dbus_dict_append_object_path(&dict_iter,
1365 					      "interface_object",
1366 					      wpa_s->dbus_new_path) ||
1367 	    !wpa_dbus_dict_append_string(&dict_iter, "role", role) ||
1368 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1369 					      wpa_s->dbus_groupobj_path) ||
1370 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1371 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1372 	else
1373 		dbus_connection_send(iface->con, msg, NULL);
1374 	dbus_message_unref(msg);
1375 }
1376 
1377 
1378 /**
1379  * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
1380  *
1381  * @dev_addr - who sent the request or responded to our request.
1382  * @request - Will be 1 if request, 0 for response.
1383  * @status - valid only in case of response
1384  * @config_methods - wps config methods
1385  * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
1386  *
1387  * Sends following provision discovery related events:
1388  *	ProvisionDiscoveryRequestDisplayPin
1389  *	ProvisionDiscoveryResponseDisplayPin
1390  *	ProvisionDiscoveryRequestEnterPin
1391  *	ProvisionDiscoveryResponseEnterPin
1392  *	ProvisionDiscoveryPBCRequest
1393  *	ProvisionDiscoveryPBCResponse
1394  *
1395  *	TODO::
1396  *	ProvisionDiscoveryFailure (timeout case)
1397  */
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)1398 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
1399 					      const u8 *dev_addr, int request,
1400 					      enum p2p_prov_disc_status status,
1401 					      u16 config_methods,
1402 					      unsigned int generated_pin)
1403 {
1404 	DBusMessage *msg;
1405 	DBusMessageIter iter;
1406 	struct wpas_dbus_priv *iface;
1407 	char *_signal;
1408 	int add_pin = 0;
1409 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1410 	int error_ret = 1;
1411 	char pin[9], *p_pin = NULL;
1412 
1413 	iface = wpa_s->global->dbus;
1414 
1415 	/* Do nothing if the control interface is not turned on */
1416 	if (iface == NULL)
1417 		return;
1418 
1419 	if (wpa_s->p2p_mgmt)
1420 		wpa_s = wpa_s->parent;
1421 	if (!wpa_s->dbus_new_path)
1422 		return;
1423 
1424 	if (request || !status) {
1425 		if (config_methods & WPS_CONFIG_DISPLAY)
1426 			_signal = request ?
1427 				 "ProvisionDiscoveryRequestDisplayPin" :
1428 				 "ProvisionDiscoveryResponseEnterPin";
1429 		else if (config_methods & WPS_CONFIG_KEYPAD)
1430 			_signal = request ?
1431 				 "ProvisionDiscoveryRequestEnterPin" :
1432 				 "ProvisionDiscoveryResponseDisplayPin";
1433 		else if (config_methods & WPS_CONFIG_PUSHBUTTON)
1434 			_signal = request ? "ProvisionDiscoveryPBCRequest" :
1435 				   "ProvisionDiscoveryPBCResponse";
1436 		else
1437 			return; /* Unknown or un-supported method */
1438 	} else {
1439 		/* Explicit check for failure response */
1440 		_signal = "ProvisionDiscoveryFailure";
1441 	}
1442 
1443 	add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
1444 		   (!request && !status &&
1445 			(config_methods & WPS_CONFIG_KEYPAD)));
1446 
1447 	if (add_pin) {
1448 		os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
1449 		p_pin = pin;
1450 	}
1451 
1452 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1453 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
1454 	if (msg == NULL)
1455 		return;
1456 
1457 	/* Check if this is a known peer */
1458 	if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
1459 		goto error;
1460 
1461 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1462 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1463 			COMPACT_MACSTR,
1464 			wpa_s->dbus_new_path, MAC2STR(dev_addr));
1465 
1466 	path = peer_obj_path;
1467 
1468 	dbus_message_iter_init_append(msg, &iter);
1469 
1470 	if (!dbus_message_iter_append_basic(&iter,
1471 					    DBUS_TYPE_OBJECT_PATH,
1472 					    &path))
1473 			goto error;
1474 
1475 	if (!request && status)
1476 		/* Attach status to ProvisionDiscoveryFailure */
1477 		error_ret = !dbus_message_iter_append_basic(&iter,
1478 						    DBUS_TYPE_INT32,
1479 						    &status);
1480 	else
1481 		error_ret = (add_pin &&
1482 				 !dbus_message_iter_append_basic(&iter,
1483 							DBUS_TYPE_STRING,
1484 							&p_pin));
1485 
1486 error:
1487 	if (!error_ret)
1488 		dbus_connection_send(iface->con, msg, NULL);
1489 	else
1490 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1491 
1492 	dbus_message_unref(msg);
1493 }
1494 
1495 
1496 /**
1497  * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX
1498  * @wpa_s: %wpa_supplicant network interface data
1499  * @src: Source address of the message triggering this notification
1500  * @dev_passwd_id: WPS Device Password Id
1501  * @go_intent: Peer's GO Intent value
1502  *
1503  * Sends signal to notify that a peer P2P Device is requesting group owner
1504  * negotiation with us.
1505  */
wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant * wpa_s,const u8 * src,u16 dev_passwd_id,u8 go_intent)1506 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
1507 				     const u8 *src, u16 dev_passwd_id,
1508 				     u8 go_intent)
1509 {
1510 	DBusMessage *msg;
1511 	DBusMessageIter iter;
1512 	struct wpas_dbus_priv *iface;
1513 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1514 
1515 	iface = wpa_s->global->dbus;
1516 
1517 	/* Do nothing if the control interface is not turned on */
1518 	if (iface == NULL)
1519 		return;
1520 
1521 	if (wpa_s->p2p_mgmt)
1522 		wpa_s = wpa_s->parent;
1523 	if (!wpa_s->dbus_new_path)
1524 		return;
1525 
1526 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1527 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1528 		    wpa_s->dbus_new_path, MAC2STR(src));
1529 	path = peer_obj_path;
1530 
1531 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1532 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1533 				      "GONegotiationRequest");
1534 	if (msg == NULL)
1535 		return;
1536 
1537 	dbus_message_iter_init_append(msg, &iter);
1538 
1539 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1540 					    &path) ||
1541 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
1542 					    &dev_passwd_id) ||
1543 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
1544 					    &go_intent))
1545 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1546 	else
1547 		dbus_connection_send(iface->con, msg, NULL);
1548 
1549 	dbus_message_unref(msg);
1550 }
1551 
1552 
wpas_dbus_get_group_obj_path(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid,char * group_obj_path)1553 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
1554 					const struct wpa_ssid *ssid,
1555 					char *group_obj_path)
1556 {
1557 	char group_name[3];
1558 
1559 	if (!wpa_s->dbus_new_path ||
1560 	    os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
1561 		return -1;
1562 
1563 	os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
1564 	group_name[2] = '\0';
1565 
1566 	os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1567 		    "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
1568 		    wpa_s->dbus_new_path, group_name);
1569 
1570 	return 0;
1571 }
1572 
1573 
1574 struct group_changed_data {
1575 	struct wpa_supplicant *wpa_s;
1576 	struct p2p_peer_info *info;
1577 };
1578 
1579 
match_group_where_peer_is_client(struct p2p_group * group,void * user_data)1580 static int match_group_where_peer_is_client(struct p2p_group *group,
1581 					    void *user_data)
1582 {
1583 	struct group_changed_data *data = user_data;
1584 	const struct p2p_group_config *cfg;
1585 	struct wpa_supplicant *wpa_s_go;
1586 
1587 	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1588 		return 1;
1589 
1590 	cfg = p2p_group_get_config(group);
1591 
1592 	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1593 					 cfg->ssid_len);
1594 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1595 		wpas_dbus_signal_peer_groups_changed(
1596 			data->wpa_s->p2pdev, data->info->p2p_device_addr);
1597 		return 0;
1598 	}
1599 
1600 	return 1;
1601 }
1602 
1603 
signal_peer_groups_changed(struct p2p_peer_info * info,void * user_data)1604 static void signal_peer_groups_changed(struct p2p_peer_info *info,
1605 				       void *user_data)
1606 {
1607 	struct group_changed_data *data = user_data;
1608 	struct wpa_supplicant *wpa_s_go;
1609 
1610 	wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
1611 					     info->p2p_device_addr);
1612 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1613 		wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
1614 						     info->p2p_device_addr);
1615 		return;
1616 	}
1617 
1618 	data->info = info;
1619 	p2p_loop_on_all_groups(data->wpa_s->global->p2p,
1620 			       match_group_where_peer_is_client, data);
1621 	data->info = NULL;
1622 }
1623 
1624 
peer_groups_changed(struct wpa_supplicant * wpa_s)1625 static void peer_groups_changed(struct wpa_supplicant *wpa_s)
1626 {
1627 	struct group_changed_data data;
1628 
1629 	os_memset(&data, 0, sizeof(data));
1630 	data.wpa_s = wpa_s;
1631 
1632 	p2p_loop_on_known_peers(wpa_s->global->p2p,
1633 				signal_peer_groups_changed, &data);
1634 }
1635 
1636 
1637 /**
1638  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
1639  * started. Emitted when a group is successfully started
1640  * irrespective of the role (client/GO) of the current device
1641  *
1642  * @wpa_s: %wpa_supplicant network interface data
1643  * @client: this device is P2P client
1644  * @persistent: 0 - non persistent group, 1 - persistent group
1645  * @ip: When group role is client, it contains local IP address, netmask, and
1646  *	GO's IP address, if assigned; otherwise, NULL
1647  */
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant * wpa_s,int client,int persistent,const u8 * ip)1648 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
1649 					int client, int persistent,
1650 					const u8 *ip)
1651 {
1652 	DBusMessage *msg;
1653 	DBusMessageIter iter, dict_iter;
1654 	struct wpas_dbus_priv *iface;
1655 	struct wpa_supplicant *parent;
1656 
1657 	parent = wpa_s->parent;
1658 	if (parent->p2p_mgmt)
1659 		parent = parent->parent;
1660 
1661 	iface = parent->global->dbus;
1662 
1663 	/* Do nothing if the control interface is not turned on */
1664 	if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path)
1665 		return;
1666 
1667 	if (wpa_s->dbus_groupobj_path == NULL)
1668 		return;
1669 
1670 	/* New interface has been created for this group */
1671 	msg = dbus_message_new_signal(parent->dbus_new_path,
1672 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1673 				      "GroupStarted");
1674 	if (msg == NULL)
1675 		return;
1676 
1677 	dbus_message_iter_init_append(msg, &iter);
1678 	/*
1679 	 * In case the device supports creating a separate interface the
1680 	 * DBus client will need to know the object path for the interface
1681 	 * object this group was created on, so include it here.
1682 	 */
1683 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1684 	    !wpa_dbus_dict_append_object_path(&dict_iter,
1685 					      "interface_object",
1686 					      wpa_s->dbus_new_path) ||
1687 	    !wpa_dbus_dict_append_string(&dict_iter, "role",
1688 					 client ? "client" : "GO") ||
1689 	    !wpa_dbus_dict_append_bool(&dict_iter, "persistent",
1690 				       !!persistent) ||
1691 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1692 					      wpa_s->dbus_groupobj_path) ||
1693 	    (ip &&
1694 	     (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr",
1695 					       (char *) ip, 4) ||
1696 	      !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
1697 					       (char *) ip + 4, 4) ||
1698 	      !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
1699 					       (char *) ip + 8, 4))) ||
1700 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
1701 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1702 	} else {
1703 		dbus_connection_send(iface->con, msg, NULL);
1704 		if (client)
1705 			peer_groups_changed(wpa_s);
1706 	}
1707 	dbus_message_unref(msg);
1708 }
1709 
1710 
1711 /**
1712  * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal
1713  * @wpa_s: %wpa_supplicant network interface data
1714  * @res: Result of the GO Neg Request
1715  */
wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant * wpa_s,struct p2p_go_neg_results * res)1716 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
1717 				      struct p2p_go_neg_results *res)
1718 {
1719 	DBusMessage *msg;
1720 	DBusMessageIter iter, dict_iter;
1721 	DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
1722 	struct wpas_dbus_priv *iface;
1723 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1724 	dbus_int32_t freqs[P2P_MAX_CHANNELS];
1725 	dbus_int32_t *f_array = freqs;
1726 
1727 
1728 	iface = wpa_s->global->dbus;
1729 
1730 	if (wpa_s->p2p_mgmt)
1731 		wpa_s = wpa_s->parent;
1732 
1733 	os_memset(freqs, 0, sizeof(freqs));
1734 	/* Do nothing if the control interface is not turned on */
1735 	if (iface == NULL || !wpa_s->dbus_new_path)
1736 		return;
1737 
1738 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1739 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1740 		    wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
1741 	path = peer_obj_path;
1742 
1743 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1744 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1745 				      res->status ? "GONegotiationFailure" :
1746 						    "GONegotiationSuccess");
1747 	if (msg == NULL)
1748 		return;
1749 
1750 	dbus_message_iter_init_append(msg, &iter);
1751 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1752 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1753 					      path) ||
1754 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
1755 		goto err;
1756 
1757 	if (!res->status) {
1758 		int i = 0;
1759 		int freq_list_num = 0;
1760 
1761 		if ((res->role_go &&
1762 		     !wpa_dbus_dict_append_string(&dict_iter, "passphrase",
1763 						  res->passphrase)) ||
1764 		    !wpa_dbus_dict_append_string(&dict_iter, "role_go",
1765 						 res->role_go ? "GO" :
1766 						 "client") ||
1767 		    !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
1768 						res->freq) ||
1769 		    !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
1770 						     (const char *) res->ssid,
1771 						     res->ssid_len) ||
1772 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
1773 						     "peer_device_addr",
1774 						     (const char *)
1775 						     res->peer_device_addr,
1776 						     ETH_ALEN) ||
1777 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
1778 						     "peer_interface_addr",
1779 						     (const char *)
1780 						     res->peer_interface_addr,
1781 						     ETH_ALEN) ||
1782 		    !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
1783 						 p2p_wps_method_text(
1784 							 res->wps_method)))
1785 			goto err;
1786 
1787 		for (i = 0; i < P2P_MAX_CHANNELS; i++) {
1788 			if (res->freq_list[i]) {
1789 				freqs[i] = res->freq_list[i];
1790 				freq_list_num++;
1791 			}
1792 		}
1793 
1794 		if (!wpa_dbus_dict_begin_array(&dict_iter,
1795 					       "frequency_list",
1796 					       DBUS_TYPE_INT32_AS_STRING,
1797 					       &iter_dict_entry,
1798 					       &iter_dict_val,
1799 					       &iter_dict_array) ||
1800 		    !dbus_message_iter_append_fixed_array(&iter_dict_array,
1801 							  DBUS_TYPE_INT32,
1802 							  &f_array,
1803 							  freq_list_num) ||
1804 		    !wpa_dbus_dict_end_array(&dict_iter,
1805 					     &iter_dict_entry,
1806 					     &iter_dict_val,
1807 					     &iter_dict_array) ||
1808 		    !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
1809 						res->persistent_group) ||
1810 		    !wpa_dbus_dict_append_uint32(&dict_iter,
1811 						 "peer_config_timeout",
1812 						 res->peer_config_timeout))
1813 			goto err;
1814 	}
1815 
1816 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1817 		goto err;
1818 
1819 	dbus_connection_send(iface->con, msg, NULL);
1820 err:
1821 	dbus_message_unref(msg);
1822 }
1823 
1824 
1825 /**
1826  * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
1827  * @wpa_s: %wpa_supplicant network interface data
1828  * @status: Status of invitation process
1829  * @bssid: Basic Service Set Identifier
1830  */
wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant * wpa_s,int status,const u8 * bssid)1831 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1832 					    int status, const u8 *bssid)
1833 {
1834 	DBusMessage *msg;
1835 	DBusMessageIter iter, dict_iter;
1836 	struct wpas_dbus_priv *iface;
1837 
1838 	wpa_printf(MSG_DEBUG, "%s", __func__);
1839 
1840 	iface = wpa_s->global->dbus;
1841 	/* Do nothing if the control interface is not turned on */
1842 	if (iface == NULL)
1843 		return;
1844 
1845 	if (wpa_s->p2p_mgmt)
1846 		wpa_s = wpa_s->parent;
1847 	if (!wpa_s->dbus_new_path)
1848 		return;
1849 
1850 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1851 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1852 				      "InvitationResult");
1853 
1854 	if (msg == NULL)
1855 		return;
1856 
1857 	dbus_message_iter_init_append(msg, &iter);
1858 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1859 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", status) ||
1860 	    (bssid &&
1861 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1862 					      (const char *) bssid,
1863 					      ETH_ALEN)) ||
1864 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1865 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1866 	else
1867 		dbus_connection_send(iface->con, msg, NULL);
1868 	dbus_message_unref(msg);
1869 }
1870 
1871 
1872 /**
1873  *
1874  * Method to emit a signal for a peer joining the group.
1875  * The signal will carry path to the group member object
1876  * constructed using p2p i/f addr used for connecting.
1877  *
1878  * @wpa_s: %wpa_supplicant network interface data
1879  * @peer_addr: P2P Device Address of the peer joining the group
1880  */
wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1881 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1882 				      const u8 *peer_addr)
1883 {
1884 	struct wpas_dbus_priv *iface;
1885 	DBusMessage *msg;
1886 	DBusMessageIter iter;
1887 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1888 	struct wpa_supplicant *parent;
1889 
1890 	iface = wpa_s->global->dbus;
1891 
1892 	/* Do nothing if the control interface is not turned on */
1893 	if (iface == NULL)
1894 		return;
1895 
1896 	if (!wpa_s->dbus_groupobj_path)
1897 		return;
1898 
1899 	parent = wpa_s->parent;
1900 	if (parent->p2p_mgmt)
1901 		parent = parent->parent;
1902 	if (!parent->dbus_new_path)
1903 		return;
1904 
1905 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1906 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1907 			COMPACT_MACSTR,
1908 			parent->dbus_new_path, MAC2STR(peer_addr));
1909 
1910 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1911 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1912 				      "PeerJoined");
1913 	if (msg == NULL)
1914 		return;
1915 
1916 	dbus_message_iter_init_append(msg, &iter);
1917 	path = peer_obj_path;
1918 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1919 					    &path)) {
1920 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1921 	} else {
1922 		dbus_connection_send(iface->con, msg, NULL);
1923 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1924 	}
1925 	dbus_message_unref(msg);
1926 }
1927 
1928 
1929 /**
1930  *
1931  * Method to emit a signal for a peer disconnecting the group.
1932  * The signal will carry path to the group member object
1933  * constructed using the P2P Device Address of the peer.
1934  *
1935  * @wpa_s: %wpa_supplicant network interface data
1936  * @peer_addr: P2P Device Address of the peer joining the group
1937  */
wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1938 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1939 					    const u8 *peer_addr)
1940 {
1941 	struct wpas_dbus_priv *iface;
1942 	DBusMessage *msg;
1943 	DBusMessageIter iter;
1944 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1945 	struct wpa_supplicant *parent;
1946 
1947 	iface = wpa_s->global->dbus;
1948 
1949 	/* Do nothing if the control interface is not turned on */
1950 	if (iface == NULL)
1951 		return;
1952 
1953 	if (!wpa_s->dbus_groupobj_path)
1954 		return;
1955 
1956 	parent = wpa_s->parent;
1957 	if (parent->p2p_mgmt)
1958 		parent = parent->parent;
1959 	if (!parent->dbus_new_path)
1960 		return;
1961 
1962 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1963 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1964 			COMPACT_MACSTR,
1965 			parent->dbus_new_path, MAC2STR(peer_addr));
1966 
1967 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1968 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1969 				      "PeerDisconnected");
1970 	if (msg == NULL)
1971 		return;
1972 
1973 	dbus_message_iter_init_append(msg, &iter);
1974 	path = peer_obj_path;
1975 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1976 					    &path)) {
1977 		wpa_printf(MSG_ERROR,
1978 			   "dbus: Failed to construct PeerDisconnected signal");
1979 	} else {
1980 		dbus_connection_send(iface->con, msg, NULL);
1981 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1982 	}
1983 	dbus_message_unref(msg);
1984 }
1985 
1986 
1987 /**
1988  *
1989  * Method to emit a signal for a service discovery request.
1990  * The signal will carry station address, frequency, dialog token,
1991  * update indicator and it tlvs
1992  *
1993  * @wpa_s: %wpa_supplicant network interface data
1994  * @sa: station addr (p2p i/f) of the peer
1995  * @dialog_token: service discovery request dialog token
1996  * @update_indic: service discovery request update indicator
1997  * @tlvs: service discovery request generated byte array of tlvs
1998  * @tlvs_len: service discovery request tlvs length
1999  */
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)2000 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
2001 				     int freq, const u8 *sa, u8 dialog_token,
2002 				     u16 update_indic, const u8 *tlvs,
2003 				     size_t tlvs_len)
2004 {
2005 	DBusMessage *msg;
2006 	DBusMessageIter iter, dict_iter;
2007 	struct wpas_dbus_priv *iface;
2008 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2009 
2010 	iface = wpa_s->global->dbus;
2011 
2012 	/* Do nothing if the control interface is not turned on */
2013 	if (iface == NULL)
2014 		return;
2015 
2016 	if (wpa_s->p2p_mgmt)
2017 		wpa_s = wpa_s->parent;
2018 	if (!wpa_s->dbus_new_path)
2019 		return;
2020 
2021 	/* Check if this is a known peer */
2022 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
2023 		return;
2024 
2025 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2026 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2027 				      "ServiceDiscoveryRequest");
2028 	if (msg == NULL)
2029 		return;
2030 
2031 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2032 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
2033 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
2034 
2035 	path = peer_obj_path;
2036 
2037 	dbus_message_iter_init_append(msg, &iter);
2038 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2039 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
2040 					      path) ||
2041 	    !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
2042 	    !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
2043 					dialog_token) ||
2044 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
2045 					 update_indic) ||
2046 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
2047 					     (const char *) tlvs,
2048 					     tlvs_len) ||
2049 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
2050 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2051 	else
2052 		dbus_connection_send(iface->con, msg, NULL);
2053 	dbus_message_unref(msg);
2054 }
2055 
2056 
2057 /**
2058  *
2059  * Method to emit a signal for a service discovery response.
2060  * The signal will carry station address, update indicator and it
2061  * tlvs
2062  *
2063  * @wpa_s: %wpa_supplicant network interface data
2064  * @sa: station addr (p2p i/f) of the peer
2065  * @update_indic: service discovery request update indicator
2066  * @tlvs: service discovery request generated byte array of tlvs
2067  * @tlvs_len: service discovery request tlvs length
2068  */
wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant * wpa_s,const u8 * sa,u16 update_indic,const u8 * tlvs,size_t tlvs_len)2069 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
2070 				      const u8 *sa, u16 update_indic,
2071 				      const u8 *tlvs, size_t tlvs_len)
2072 {
2073 	DBusMessage *msg;
2074 	DBusMessageIter iter, dict_iter;
2075 	struct wpas_dbus_priv *iface;
2076 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2077 
2078 	iface = wpa_s->global->dbus;
2079 
2080 	/* Do nothing if the control interface is not turned on */
2081 	if (iface == NULL)
2082 		return;
2083 
2084 	if (wpa_s->p2p_mgmt)
2085 		wpa_s = wpa_s->parent;
2086 	if (!wpa_s->dbus_new_path)
2087 		return;
2088 
2089 	/* Check if this is a known peer */
2090 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
2091 		return;
2092 
2093 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2094 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2095 				      "ServiceDiscoveryResponse");
2096 	if (msg == NULL)
2097 		return;
2098 
2099 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2100 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
2101 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
2102 
2103 	path = peer_obj_path;
2104 
2105 	dbus_message_iter_init_append(msg, &iter);
2106 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2107 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
2108 					      path) ||
2109 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
2110 					 update_indic) ||
2111 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
2112 					     (const char *) tlvs,
2113 					     tlvs_len) ||
2114 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
2115 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2116 	else
2117 		dbus_connection_send(iface->con, msg, NULL);
2118 	dbus_message_unref(msg);
2119 }
2120 
2121 
2122 /**
2123  * wpas_dbus_signal_persistent_group - Send a persistent group related
2124  *	event signal
2125  * @wpa_s: %wpa_supplicant network interface data
2126  * @id: new persistent group id
2127  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
2128  * @properties: determines if add second argument with object properties
2129  *
2130  * Notify listeners about an event related to persistent groups.
2131  */
wpas_dbus_signal_persistent_group(struct wpa_supplicant * wpa_s,int id,const char * sig_name,dbus_bool_t properties)2132 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
2133 					      int id, const char *sig_name,
2134 					      dbus_bool_t properties)
2135 {
2136 	struct wpas_dbus_priv *iface;
2137 	DBusMessage *msg;
2138 	DBusMessageIter iter;
2139 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2140 
2141 	iface = wpa_s->global->dbus;
2142 
2143 	/* Do nothing if the control interface is not turned on */
2144 	if (iface == NULL)
2145 		return;
2146 
2147 	if (wpa_s->p2p_mgmt)
2148 		wpa_s = wpa_s->parent;
2149 	if (!wpa_s->dbus_new_path)
2150 		return;
2151 
2152 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2153 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
2154 		    wpa_s->dbus_new_path, id);
2155 
2156 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2157 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2158 				      sig_name);
2159 	if (msg == NULL)
2160 		return;
2161 
2162 	dbus_message_iter_init_append(msg, &iter);
2163 	path = pgrp_obj_path;
2164 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2165 					    &path) ||
2166 	    (properties &&
2167 	     !wpa_dbus_get_object_properties(
2168 		     iface, pgrp_obj_path,
2169 		     WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
2170 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2171 	else
2172 		dbus_connection_send(iface->con, msg, NULL);
2173 
2174 	dbus_message_unref(msg);
2175 }
2176 
2177 
2178 /**
2179  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
2180  *	added signal
2181  * @wpa_s: %wpa_supplicant network interface data
2182  * @id: new persistent group id
2183  *
2184  * Notify listeners about addition of a new persistent group.
2185  */
wpas_dbus_signal_persistent_group_added(struct wpa_supplicant * wpa_s,int id)2186 static void wpas_dbus_signal_persistent_group_added(
2187 	struct wpa_supplicant *wpa_s, int id)
2188 {
2189 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
2190 					  TRUE);
2191 }
2192 
2193 
2194 /**
2195  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
2196  *	removed signal
2197  * @wpa_s: %wpa_supplicant network interface data
2198  * @id: persistent group id
2199  *
2200  * Notify listeners about removal of a persistent group.
2201  */
wpas_dbus_signal_persistent_group_removed(struct wpa_supplicant * wpa_s,int id)2202 static void wpas_dbus_signal_persistent_group_removed(
2203 	struct wpa_supplicant *wpa_s, int id)
2204 {
2205 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
2206 					  FALSE);
2207 }
2208 
2209 
2210 /**
2211  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
2212  * @wpa_s: %wpa_supplicant network interface data
2213  * @fail: WPS failure information
2214  *
2215  * Sends Event dbus signal with name "fail" and dictionary containing
2216  * "msg" field with fail message number (int32) as arguments
2217  */
wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant * wpa_s,struct wps_event_fail * fail)2218 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
2219 				     struct wps_event_fail *fail)
2220 {
2221 
2222 	DBusMessage *msg;
2223 	DBusMessageIter iter, dict_iter;
2224 	struct wpas_dbus_priv *iface;
2225 	char *key = "fail";
2226 
2227 	iface = wpa_s->global->dbus;
2228 
2229 	/* Do nothing if the control interface is not turned on */
2230 	if (iface == NULL)
2231 		return;
2232 
2233 	if (wpa_s->p2p_mgmt)
2234 		wpa_s = wpa_s->parent;
2235 
2236 	if (!wpa_s->dbus_new_path)
2237 		return;
2238 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2239 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2240 				      "WpsFailed");
2241 	if (msg == NULL)
2242 		return;
2243 
2244 	dbus_message_iter_init_append(msg, &iter);
2245 
2246 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
2247 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2248 	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
2249 	    !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
2250 					fail->config_error) ||
2251 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
2252 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2253 	else
2254 		dbus_connection_send(iface->con, msg, NULL);
2255 
2256 	dbus_message_unref(msg);
2257 }
2258 
2259 
2260 /**
2261  * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event
2262  * @wpa_s: %wpa_supplicant network interface data
2263  * @reason: indicates the reason code for group formation failure
2264  *
2265  * Sends Event dbus signal and string reason code when available.
2266  */
wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant * wpa_s,const char * reason)2267 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
2268 						  const char *reason)
2269 {
2270 	DBusMessage *msg;
2271 	struct wpas_dbus_priv *iface;
2272 
2273 	iface = wpa_s->global->dbus;
2274 
2275 	/* Do nothing if the control interface is not turned on */
2276 	if (iface == NULL)
2277 		return;
2278 
2279 	if (wpa_s->p2p_mgmt)
2280 		wpa_s = wpa_s->parent;
2281 
2282 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2283 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2284 				      "GroupFormationFailure");
2285 	if (msg == NULL)
2286 		return;
2287 
2288 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
2289 				     DBUS_TYPE_INVALID))
2290 		dbus_connection_send(iface->con, msg, NULL);
2291 	else
2292 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2293 
2294 	dbus_message_unref(msg);
2295 }
2296 
2297 
2298 /**
2299  * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal
2300  * @wpa_s: %wpa_supplicant network interface data
2301  * @sa: Source address of the Invitation Request
2302  * @dev_add: GO Device Address
2303  * @bssid: P2P Group BSSID or %NULL if not received
2304  * @id: Persistent group id or %0 if not persistent group
2305  * @op_freq: Operating frequency for the group
2306  */
2307 
wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant * wpa_s,const u8 * sa,const u8 * dev_addr,const u8 * bssid,int id,int op_freq)2308 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
2309 					      const u8 *sa, const u8 *dev_addr,
2310 					      const u8 *bssid, int id,
2311 					      int op_freq)
2312 {
2313 	DBusMessage *msg;
2314 	DBusMessageIter iter, dict_iter;
2315 	struct wpas_dbus_priv *iface;
2316 
2317 	iface = wpa_s->global->dbus;
2318 
2319 	/* Do nothing if the control interface is not turned on */
2320 	if (iface == NULL)
2321 		return;
2322 
2323 	if (wpa_s->p2p_mgmt)
2324 		wpa_s = wpa_s->parent;
2325 
2326 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2327 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2328 				      "InvitationReceived");
2329 	if (msg == NULL)
2330 		return;
2331 
2332 	dbus_message_iter_init_append(msg, &iter);
2333 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2334 	    (sa &&
2335 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "sa",
2336 					      (const char *) sa, ETH_ALEN)) ||
2337 	    (dev_addr &&
2338 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr",
2339 					      (const char *) dev_addr,
2340 					      ETH_ALEN)) ||
2341 	    (bssid &&
2342 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
2343 					      (const char *) bssid,
2344 					      ETH_ALEN)) ||
2345 	    (id &&
2346 	     !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) ||
2347 	    !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) ||
2348 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
2349 		dbus_message_unref(msg);
2350 		return;
2351 	}
2352 
2353 	dbus_connection_send(iface->con, msg, NULL);
2354 	dbus_message_unref(msg);
2355 }
2356 
2357 
2358 /**
2359  * wpas_dbus_signal_p2p_bootstrap_req - Signals BootstrappingRequest event
2360  * @wpa_s: %wpa_supplicant network interface data
2361  * @src: Source address of the message triggering this notification
2362  * @bootstrap_method: Peer's bootstrap method
2363  *
2364  * Sends a signal to notify that a peer P2P Device is requesting bootstrapping
2365  * negotiation with us.
2366  */
wpas_dbus_signal_p2p_bootstrap_req(struct wpa_supplicant * wpa_s,const u8 * src,u16 bootstrap_method)2367 void wpas_dbus_signal_p2p_bootstrap_req(struct wpa_supplicant *wpa_s,
2368 					const u8 *src, u16 bootstrap_method)
2369 {
2370 	DBusMessage *msg;
2371 	DBusMessageIter iter;
2372 	struct wpas_dbus_priv *iface;
2373 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2374 
2375 	iface = wpa_s->global->dbus;
2376 
2377 	/* Do nothing if the control interface is not turned on */
2378 	if (!iface)
2379 		return;
2380 
2381 	if (wpa_s->p2p_mgmt)
2382 		wpa_s = wpa_s->parent;
2383 	if (!wpa_s->dbus_new_path)
2384 		return;
2385 
2386 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2387 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2388 		    wpa_s->dbus_new_path, MAC2STR(src));
2389 	path = peer_obj_path;
2390 
2391 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2392 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2393 				      "BootstrappingRequest");
2394 	if (!msg)
2395 		return;
2396 
2397 	dbus_message_iter_init_append(msg, &iter);
2398 
2399 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2400 					    &path) ||
2401 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
2402 					    &bootstrap_method))
2403 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2404 	else
2405 		dbus_connection_send(iface->con, msg, NULL);
2406 
2407 	dbus_message_unref(msg);
2408 }
2409 
2410 
2411 /**
2412  * wpas_dbus_signal_p2p_bootstrap_rsp - Signals BootstrappingResponse event
2413  * @wpa_s: %wpa_supplicant network interface data
2414  * @src: Source address of the peer with which bootstrapping is done
2415  * @status: Status of Bootstrapping handshake
2416  * @bootstrap_method: Local device requested bootstrap method
2417  *
2418  * Sends a signal to notify that a peer P2P Device is requesting bootstrapping
2419  * negotiation with us.
2420  */
wpas_dbus_signal_p2p_bootstrap_rsp(struct wpa_supplicant * wpa_s,const u8 * src,int status,u16 bootstrap_method)2421 void wpas_dbus_signal_p2p_bootstrap_rsp(struct wpa_supplicant *wpa_s,
2422 					const u8 *src, int status,
2423 					u16 bootstrap_method)
2424 {
2425 	DBusMessage *msg;
2426 	DBusMessageIter iter;
2427 	struct wpas_dbus_priv *iface;
2428 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
2429 
2430 	iface = wpa_s->global->dbus;
2431 
2432 	/* Do nothing if the control interface is not turned on */
2433 	if (!iface)
2434 		return;
2435 
2436 	if (wpa_s->p2p_mgmt)
2437 		wpa_s = wpa_s->parent;
2438 	if (!wpa_s->dbus_new_path)
2439 		return;
2440 
2441 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2442 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
2443 		    wpa_s->dbus_new_path, MAC2STR(src));
2444 	path = peer_obj_path;
2445 
2446 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2447 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2448 				      "BootstrappingCompleted");
2449 	if (!msg)
2450 		return;
2451 
2452 	dbus_message_iter_init_append(msg, &iter);
2453 
2454 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
2455 					    &path) ||
2456 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
2457 					    &status) ||
2458 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
2459 					    &bootstrap_method))
2460 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2461 	else
2462 		dbus_connection_send(iface->con, msg, NULL);
2463 
2464 	dbus_message_unref(msg);
2465 }
2466 
2467 
2468 #endif /* CONFIG_P2P */
2469 
2470 
2471 /**
2472  * wpas_dbus_signal_prop_changed - Signals change of property
2473  * @wpa_s: %wpa_supplicant network interface data
2474  * @property: indicates which property has changed
2475  *
2476  * Sends PropertyChanged signals with path, interface and arguments
2477  * depending on which property has changed.
2478  */
wpas_dbus_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_prop property)2479 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
2480 				   enum wpas_dbus_prop property)
2481 {
2482 	char *prop;
2483 	dbus_bool_t flush;
2484 
2485 	if (wpa_s->dbus_new_path == NULL)
2486 		return; /* Skip signal since D-Bus setup is not yet ready */
2487 
2488 	flush = FALSE;
2489 	switch (property) {
2490 	case WPAS_DBUS_PROP_AP_SCAN:
2491 		prop = "ApScan";
2492 		break;
2493 	case WPAS_DBUS_PROP_SCANNING:
2494 		prop = "Scanning";
2495 		break;
2496 	case WPAS_DBUS_PROP_STATE:
2497 		prop = "State";
2498 		break;
2499 	case WPAS_DBUS_PROP_CURRENT_BSS:
2500 		prop = "CurrentBSS";
2501 		break;
2502 	case WPAS_DBUS_PROP_CURRENT_NETWORK:
2503 		prop = "CurrentNetwork";
2504 		break;
2505 	case WPAS_DBUS_PROP_BSSS:
2506 		prop = "BSSs";
2507 		break;
2508 	case WPAS_DBUS_PROP_STATIONS:
2509 		prop = "Stations";
2510 		break;
2511 	case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
2512 		prop = "CurrentAuthMode";
2513 		break;
2514 	case WPAS_DBUS_PROP_DISCONNECT_REASON:
2515 		prop = "DisconnectReason";
2516 		flush = TRUE;
2517 		break;
2518 	case WPAS_DBUS_PROP_AUTH_STATUS_CODE:
2519 		prop = "AuthStatusCode";
2520 		flush = TRUE;
2521 		break;
2522 	case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
2523 		prop = "AssocStatusCode";
2524 		flush = TRUE;
2525 		break;
2526 	case WPAS_DBUS_PROP_ROAM_TIME:
2527 		prop = "RoamTime";
2528 		break;
2529 	case WPAS_DBUS_PROP_ROAM_COMPLETE:
2530 		prop = "RoamComplete";
2531 		break;
2532 	case WPAS_DBUS_PROP_SCAN_IN_PROGRESS_6GHZ:
2533 		prop = "ScanInProgress6GHz";
2534 		flush = TRUE;
2535 		break;
2536 	case WPAS_DBUS_PROP_SESSION_LENGTH:
2537 		prop = "SessionLength";
2538 		break;
2539 	case WPAS_DBUS_PROP_BSS_TM_STATUS:
2540 		prop = "BSSTMStatus";
2541 		break;
2542 	case WPAS_DBUS_PROP_MAC_ADDRESS:
2543 		prop = "MACAddress";
2544 		break;
2545 	case WPAS_DBUS_PROP_SIGNAL_CHANGE:
2546 		prop = "SignalChange";
2547 		break;
2548 	default:
2549 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2550 			   __func__, property);
2551 		return;
2552 	}
2553 
2554 	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
2555 				       wpa_s->dbus_new_path,
2556 				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
2557 	if (flush) {
2558 		wpa_dbus_flush_object_changed_properties(
2559 			wpa_s->global->dbus->con, wpa_s->dbus_new_path);
2560 	}
2561 }
2562 
2563 
2564 /**
2565  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
2566  * @wpa_s: %wpa_supplicant network interface data
2567  * @property: indicates which property has changed
2568  * @id: unique BSS identifier
2569  *
2570  * Sends PropertyChanged signals with path, interface, and arguments depending
2571  * on which property has changed.
2572  */
wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,unsigned int id)2573 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
2574 				       enum wpas_dbus_bss_prop property,
2575 				       unsigned int id)
2576 {
2577 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
2578 	char *prop;
2579 
2580 	if (!wpa_s->dbus_new_path)
2581 		return;
2582 
2583 	switch (property) {
2584 	case WPAS_DBUS_BSS_PROP_SIGNAL:
2585 		prop = "Signal";
2586 		break;
2587 	case WPAS_DBUS_BSS_PROP_FREQ:
2588 		prop = "Frequency";
2589 		break;
2590 	case WPAS_DBUS_BSS_PROP_MODE:
2591 		prop = "Mode";
2592 		break;
2593 	case WPAS_DBUS_BSS_PROP_PRIVACY:
2594 		prop = "Privacy";
2595 		break;
2596 	case WPAS_DBUS_BSS_PROP_RATES:
2597 		prop = "Rates";
2598 		break;
2599 	case WPAS_DBUS_BSS_PROP_WPA:
2600 		prop = "WPA";
2601 		break;
2602 	case WPAS_DBUS_BSS_PROP_RSN:
2603 		prop = "RSN";
2604 		break;
2605 	case WPAS_DBUS_BSS_PROP_WPS:
2606 		prop = "WPS";
2607 		break;
2608 	case WPAS_DBUS_BSS_PROP_IES:
2609 		prop = "IEs";
2610 		break;
2611 	case WPAS_DBUS_BSS_PROP_AGE:
2612 		prop = "Age";
2613 		break;
2614 	case WPAS_DBUS_BSS_PROP_ANQP:
2615 		prop = "ANQP";
2616 		break;
2617 	default:
2618 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2619 			   __func__, property);
2620 		return;
2621 	}
2622 
2623 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2624 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2625 		    wpa_s->dbus_new_path, id);
2626 
2627 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2628 				       WPAS_DBUS_NEW_IFACE_BSS, prop);
2629 }
2630 
2631 
2632 /**
2633  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
2634  * @global: wpa_global structure
2635  *
2636  * Sends PropertyChanged signals informing that debug level has changed.
2637  */
wpas_dbus_signal_debug_level_changed(struct wpa_global * global)2638 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
2639 {
2640 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2641 				       WPAS_DBUS_NEW_INTERFACE,
2642 				       "DebugLevel");
2643 }
2644 
2645 
2646 /**
2647  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
2648  * @global: wpa_global structure
2649  *
2650  * Sends PropertyChanged signals informing that debug timestamp has changed.
2651  */
wpas_dbus_signal_debug_timestamp_changed(struct wpa_global * global)2652 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
2653 {
2654 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2655 				       WPAS_DBUS_NEW_INTERFACE,
2656 				       "DebugTimestamp");
2657 }
2658 
2659 
2660 /**
2661  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
2662  * @global: wpa_global structure
2663  *
2664  * Sends PropertyChanged signals informing that debug show_keys has changed.
2665  */
wpas_dbus_signal_debug_show_keys_changed(struct wpa_global * global)2666 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
2667 {
2668 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2669 				       WPAS_DBUS_NEW_INTERFACE,
2670 				       "DebugShowKeys");
2671 }
2672 
2673 
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)2674 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
2675 			       void *priv,
2676 			       WPADBusArgumentFreeFunction priv_free,
2677 			       const struct wpa_dbus_method_desc *methods,
2678 			       const struct wpa_dbus_property_desc *properties,
2679 			       const struct wpa_dbus_signal_desc *signals)
2680 {
2681 	int n;
2682 
2683 	obj_desc->user_data = priv;
2684 	obj_desc->user_data_free_func = priv_free;
2685 	obj_desc->methods = methods;
2686 	obj_desc->properties = properties;
2687 	obj_desc->signals = signals;
2688 
2689 	for (n = 0; properties && properties->dbus_property; properties++)
2690 		n++;
2691 
2692 	obj_desc->prop_changed_flags = os_zalloc(n);
2693 	if (!obj_desc->prop_changed_flags)
2694 		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
2695 			   __func__);
2696 }
2697 
2698 
2699 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
2700 	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
2701 	  (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
2702 	  {
2703 		  { "args", "a{sv}", ARG_IN },
2704 		  { "path", "o", ARG_OUT },
2705 		  END_ARGS
2706 	  }
2707 	},
2708 	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
2709 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
2710 	  {
2711 		  { "path", "o", ARG_IN },
2712 		  END_ARGS
2713 	  }
2714 	},
2715 	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
2716 	  (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
2717 	  {
2718 		  { "ifname", "s", ARG_IN },
2719 		  { "path", "o", ARG_OUT },
2720 		  END_ARGS
2721 	  }
2722 	},
2723 	{ "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
2724 	  (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
2725 	  {
2726 		END_ARGS
2727 	  }
2728 	},
2729 	{ NULL, NULL, NULL, { END_ARGS } }
2730 };
2731 
2732 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
2733 	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
2734 	  wpas_dbus_getter_debug_level,
2735 	  wpas_dbus_setter_debug_level,
2736 	  NULL
2737 	},
2738 	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
2739 	  wpas_dbus_getter_debug_timestamp,
2740 	  wpas_dbus_setter_debug_timestamp,
2741 	  NULL
2742 	},
2743 	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
2744 	  wpas_dbus_getter_debug_show_keys,
2745 	  wpas_dbus_setter_debug_show_keys,
2746 	  NULL
2747 	},
2748 	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
2749 	  wpas_dbus_getter_interfaces,
2750 	  NULL,
2751 	  NULL
2752 	},
2753 	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
2754 	  wpas_dbus_getter_eap_methods,
2755 	  NULL,
2756 	  NULL
2757 	},
2758 	{ "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
2759 	  wpas_dbus_getter_global_capabilities,
2760 	  NULL,
2761 	  NULL
2762 	},
2763 #ifdef CONFIG_WIFI_DISPLAY
2764 	{ "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
2765 	  wpas_dbus_getter_global_wfd_ies,
2766 	  wpas_dbus_setter_global_wfd_ies,
2767 	  NULL
2768 	},
2769 #endif /* CONFIG_WIFI_DISPLAY */
2770 	{ NULL, NULL, NULL, NULL, NULL, NULL }
2771 };
2772 
2773 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2774 	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2775 	  {
2776 		  { "path", "o", ARG_OUT },
2777 		  { "properties", "a{sv}", ARG_OUT },
2778 		  END_ARGS
2779 	  }
2780 	},
2781 	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2782 	  {
2783 		  { "path", "o", ARG_OUT },
2784 		  END_ARGS
2785 	  }
2786 	},
2787 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2788 	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2789 	  {
2790 		  { "properties", "a{sv}", ARG_OUT },
2791 		  END_ARGS
2792 	  }
2793 	},
2794 	{ NULL, NULL, { END_ARGS } }
2795 };
2796 
2797 
uscore_to_dbus(const char * uscore)2798 static char * uscore_to_dbus(const char *uscore)
2799 {
2800 	const char *p = uscore;
2801 	char *str, *s;
2802 	dbus_bool_t last_was_uscore = TRUE;
2803 
2804 	s = str = os_zalloc(os_strlen(uscore) + 1);
2805 	if (!str)
2806 		return NULL;
2807 	while (p && *p) {
2808 		if (*p == '_') {
2809 			last_was_uscore = TRUE;
2810 		} else {
2811 			*s++ = last_was_uscore ? toupper(*p) : *p;
2812 			last_was_uscore = FALSE;
2813 		}
2814 		p++;
2815 	}
2816 
2817 	return str;
2818 }
2819 
2820 
2821 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
2822 
2823 
wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv * priv)2824 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
2825 {
2826 	int idx = priv->globals_start;
2827 
2828 	/* Free all allocated property values */
2829 	while (priv->all_interface_properties[idx].dbus_property)
2830 		os_free((char *)
2831 			priv->all_interface_properties[idx++].dbus_property);
2832 	os_free((char *) priv->all_interface_properties);
2833 }
2834 
2835 
2836 /**
2837  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2838  * @global: Pointer to global data from wpa_supplicant_init()
2839  * Returns: 0 on success or -1 on failure
2840  *
2841  * Initialize the dbus control interface for wpa_supplicant and start
2842  * receiving commands from external programs over the bus.
2843  */
wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv * priv)2844 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2845 {
2846 	struct wpa_dbus_object_desc *obj_desc;
2847 	int ret;
2848 
2849 	ret = wpa_dbus_ctrl_iface_props_init(priv);
2850 	if (ret < 0) {
2851 		wpa_printf(MSG_ERROR,
2852 			   "dbus: Not enough memory to init interface properties");
2853 		return -1;
2854 	}
2855 
2856 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2857 	if (!obj_desc) {
2858 		wpa_printf(MSG_ERROR,
2859 			   "Not enough memory to create object description");
2860 		goto error;
2861 	}
2862 
2863 	wpas_dbus_register(obj_desc, priv->global, NULL,
2864 			   wpas_dbus_global_methods,
2865 			   wpas_dbus_global_properties,
2866 			   wpas_dbus_global_signals);
2867 
2868 	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2869 		   WPAS_DBUS_NEW_PATH);
2870 	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2871 				       WPAS_DBUS_NEW_SERVICE,
2872 				       obj_desc);
2873 	if (ret < 0) {
2874 		free_dbus_object_desc(obj_desc);
2875 		goto error;
2876 	}
2877 
2878 	priv->dbus_new_initialized = 1;
2879 	return 0;
2880 
2881 error:
2882 	wpa_dbus_ctrl_iface_props_deinit(priv);
2883 	return -1;
2884 }
2885 
2886 
2887 /**
2888  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2889  * wpa_supplicant
2890  * @priv: Pointer to dbus private data from wpas_dbus_init()
2891  *
2892  * Deinitialize the dbus control interface that was initialized with
2893  * wpas_dbus_ctrl_iface_init().
2894  */
wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv * priv)2895 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
2896 {
2897 	if (!priv->dbus_new_initialized)
2898 		return;
2899 	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2900 		   WPAS_DBUS_NEW_PATH);
2901 	dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
2902 	wpa_dbus_ctrl_iface_props_deinit(priv);
2903 }
2904 
2905 
wpa_dbus_free(void * ptr)2906 static void wpa_dbus_free(void *ptr)
2907 {
2908 	os_free(ptr);
2909 }
2910 
2911 
2912 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2913 	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2914 	  wpas_dbus_getter_network_properties,
2915 	  wpas_dbus_setter_network_properties,
2916 	  NULL
2917 	},
2918 	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2919 	  wpas_dbus_getter_enabled,
2920 	  wpas_dbus_setter_enabled,
2921 	  NULL
2922 	},
2923 	{ NULL, NULL, NULL, NULL, NULL, NULL }
2924 };
2925 
2926 
2927 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2928 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2929 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2930 	  {
2931 		  { "properties", "a{sv}", ARG_OUT },
2932 		  END_ARGS
2933 	  }
2934 	},
2935 	{ NULL, NULL, { END_ARGS } }
2936 };
2937 
2938 
2939 /**
2940  * wpas_dbus_register_network - Register a configured network with dbus
2941  * @wpa_s: wpa_supplicant interface structure
2942  * @ssid: network configuration data
2943  * Returns: 0 on success, -1 on failure
2944  *
2945  * Registers network representing object with dbus
2946  */
wpas_dbus_register_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2947 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2948 			       struct wpa_ssid *ssid)
2949 {
2950 	struct wpas_dbus_priv *ctrl_iface;
2951 	struct wpa_dbus_object_desc *obj_desc;
2952 	struct network_handler_args *arg;
2953 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2954 
2955 #ifdef CONFIG_P2P
2956 	/*
2957 	 * If it is a persistent group register it as such.
2958 	 * This is to handle cases where an interface is being initialized
2959 	 * with a list of networks read from config.
2960 	 */
2961 	if (network_is_persistent_group(ssid))
2962 		return wpas_dbus_register_persistent_group(wpa_s, ssid);
2963 #endif /* CONFIG_P2P */
2964 
2965 	/* Do nothing if the control interface is not turned on */
2966 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2967 		return 0;
2968 	ctrl_iface = wpa_s->global->dbus;
2969 	if (ctrl_iface == NULL)
2970 		return 0;
2971 
2972 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2973 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2974 		    wpa_s->dbus_new_path, ssid->id);
2975 
2976 	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2977 		   net_obj_path);
2978 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2979 	if (!obj_desc) {
2980 		wpa_printf(MSG_ERROR,
2981 			   "Not enough memory to create object description");
2982 		goto err;
2983 	}
2984 
2985 	/* allocate memory for handlers arguments */
2986 	arg = os_zalloc(sizeof(struct network_handler_args));
2987 	if (!arg) {
2988 		wpa_printf(MSG_ERROR,
2989 			   "Not enough memory to create arguments for method");
2990 		goto err;
2991 	}
2992 
2993 	arg->wpa_s = wpa_s;
2994 	arg->ssid = ssid;
2995 
2996 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2997 			   wpas_dbus_network_properties,
2998 			   wpas_dbus_network_signals);
2999 
3000 	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
3001 					       wpa_s->ifname, obj_desc))
3002 		goto err;
3003 
3004 	wpas_dbus_signal_network_added(wpa_s, ssid->id);
3005 
3006 	return 0;
3007 
3008 err:
3009 	free_dbus_object_desc(obj_desc);
3010 	return -1;
3011 }
3012 
3013 
3014 /**
3015  * wpas_dbus_unregister_network - Unregister a configured network from dbus
3016  * @wpa_s: wpa_supplicant interface structure
3017  * @nid: network id
3018  * Returns: 0 on success, -1 on failure
3019  *
3020  * Unregisters network representing object from dbus
3021  */
wpas_dbus_unregister_network(struct wpa_supplicant * wpa_s,int nid)3022 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
3023 {
3024 	struct wpas_dbus_priv *ctrl_iface;
3025 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3026 	int ret;
3027 #ifdef CONFIG_P2P
3028 	struct wpa_ssid *ssid;
3029 
3030 	ssid = wpa_config_get_network(wpa_s->conf, nid);
3031 
3032 	/* If it is a persistent group unregister it as such */
3033 	if (ssid && network_is_persistent_group(ssid))
3034 		return wpas_dbus_unregister_persistent_group(wpa_s, nid);
3035 #endif /* CONFIG_P2P */
3036 
3037 	/* Do nothing if the control interface is not turned on */
3038 	if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
3039 		return 0;
3040 	ctrl_iface = wpa_s->global->dbus;
3041 	if (ctrl_iface == NULL)
3042 		return 0;
3043 
3044 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3045 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
3046 		    wpa_s->dbus_new_path, nid);
3047 
3048 	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
3049 		   net_obj_path);
3050 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
3051 
3052 	if (!ret)
3053 		wpas_dbus_signal_network_removed(wpa_s, nid);
3054 
3055 	return ret;
3056 }
3057 
3058 
3059 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
3060 	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
3061 	  wpas_dbus_getter_bss_ssid,
3062 	  NULL,
3063 	  NULL
3064 	},
3065 	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
3066 	  wpas_dbus_getter_bss_bssid,
3067 	  NULL,
3068 	  NULL
3069 	},
3070 	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
3071 	  wpas_dbus_getter_bss_privacy,
3072 	  NULL,
3073 	  NULL
3074 	},
3075 	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
3076 	  wpas_dbus_getter_bss_mode,
3077 	  NULL,
3078 	  NULL
3079 	},
3080 	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
3081 	  wpas_dbus_getter_bss_signal,
3082 	  NULL,
3083 	  NULL
3084 	},
3085 	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
3086 	  wpas_dbus_getter_bss_frequency,
3087 	  NULL,
3088 	  NULL
3089 	},
3090 	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
3091 	  wpas_dbus_getter_bss_rates,
3092 	  NULL,
3093 	  NULL
3094 	},
3095 	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3096 	  wpas_dbus_getter_bss_wpa,
3097 	  NULL,
3098 	  NULL
3099 	},
3100 	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3101 	  wpas_dbus_getter_bss_rsn,
3102 	  NULL,
3103 	  NULL
3104 	},
3105 	{ "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3106 	  wpas_dbus_getter_bss_wps,
3107 	  NULL,
3108 	  NULL
3109 	},
3110 	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
3111 	  wpas_dbus_getter_bss_ies,
3112 	  NULL,
3113 	  NULL
3114 	},
3115 	{ "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
3116 	  wpas_dbus_getter_bss_age,
3117 	  NULL,
3118 	  NULL
3119 	},
3120 	{"ANQP", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
3121 	  wpas_dbus_getter_bss_anqp,
3122 	  NULL,
3123 	  NULL,
3124 	},
3125 	{ NULL, NULL, NULL, NULL, NULL, NULL }
3126 };
3127 
3128 
3129 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
3130 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3131 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
3132 	  {
3133 		  { "properties", "a{sv}", ARG_OUT },
3134 		  END_ARGS
3135 	  }
3136 	},
3137 	{ NULL, NULL, { END_ARGS } }
3138 };
3139 
3140 
3141 /**
3142  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
3143  * @wpa_s: wpa_supplicant interface structure
3144  * @bssid: scanned network bssid
3145  * @id: unique BSS identifier
3146  * Returns: 0 on success, -1 on failure
3147  *
3148  * Unregisters BSS representing object from dbus
3149  */
wpas_dbus_unregister_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)3150 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
3151 			     u8 bssid[ETH_ALEN], unsigned int id)
3152 {
3153 	struct wpas_dbus_priv *ctrl_iface;
3154 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3155 
3156 	/* Do nothing if the control interface is not turned on */
3157 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
3158 		return 0;
3159 	ctrl_iface = wpa_s->global->dbus;
3160 	if (ctrl_iface == NULL)
3161 		return 0;
3162 
3163 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3164 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3165 		    wpa_s->dbus_new_path, id);
3166 
3167 	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
3168 		   bss_obj_path);
3169 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
3170 		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
3171 			   bss_obj_path);
3172 		return -1;
3173 	}
3174 
3175 	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
3176 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
3177 
3178 	return 0;
3179 }
3180 
3181 
3182 /**
3183  * wpas_dbus_register_bss - Register a scanned BSS with dbus
3184  * @wpa_s: wpa_supplicant interface structure
3185  * @bssid: scanned network bssid
3186  * @id: unique BSS identifier
3187  * Returns: 0 on success, -1 on failure
3188  *
3189  * Registers BSS representing object with dbus
3190  */
wpas_dbus_register_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)3191 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
3192 			   u8 bssid[ETH_ALEN], unsigned int id)
3193 {
3194 	struct wpas_dbus_priv *ctrl_iface;
3195 	struct wpa_dbus_object_desc *obj_desc;
3196 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3197 	struct bss_handler_args *arg;
3198 
3199 	/* Do nothing if the control interface is not turned on */
3200 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
3201 		return 0;
3202 	ctrl_iface = wpa_s->global->dbus;
3203 	if (ctrl_iface == NULL)
3204 		return 0;
3205 
3206 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3207 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
3208 		    wpa_s->dbus_new_path, id);
3209 
3210 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3211 	if (!obj_desc) {
3212 		wpa_printf(MSG_ERROR,
3213 			   "Not enough memory to create object description");
3214 		goto err;
3215 	}
3216 
3217 	arg = os_zalloc(sizeof(struct bss_handler_args));
3218 	if (!arg) {
3219 		wpa_printf(MSG_ERROR,
3220 			   "Not enough memory to create arguments for handler");
3221 		goto err;
3222 	}
3223 	arg->wpa_s = wpa_s;
3224 	arg->id = id;
3225 
3226 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3227 			   wpas_dbus_bss_properties,
3228 			   wpas_dbus_bss_signals);
3229 
3230 	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
3231 		   bss_obj_path);
3232 	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
3233 					       wpa_s->ifname, obj_desc)) {
3234 		wpa_printf(MSG_ERROR,
3235 			   "Cannot register BSSID dbus object %s.",
3236 			   bss_obj_path);
3237 		goto err;
3238 	}
3239 
3240 	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
3241 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
3242 
3243 	return 0;
3244 
3245 err:
3246 	free_dbus_object_desc(obj_desc);
3247 	return -1;
3248 }
3249 
3250 
3251 static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = {
3252 	{ "Address", WPAS_DBUS_NEW_IFACE_STA, "ay",
3253 	  wpas_dbus_getter_sta_address,
3254 	  NULL, NULL
3255 	},
3256 	{ "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
3257 	  wpas_dbus_getter_sta_aid,
3258 	  NULL, NULL
3259 	},
3260 	{ "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
3261 	  wpas_dbus_getter_sta_caps,
3262 	  NULL, NULL
3263 	},
3264 	{ "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3265 	  wpas_dbus_getter_sta_rx_packets,
3266 	  NULL, NULL
3267 	},
3268 	{ "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3269 	  wpas_dbus_getter_sta_tx_packets,
3270 	  NULL, NULL
3271 	},
3272 	{ "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3273 	  wpas_dbus_getter_sta_rx_bytes,
3274 	  NULL, NULL
3275 	},
3276 	{ "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3277 	  wpas_dbus_getter_sta_tx_bytes,
3278 	  NULL, NULL
3279 	},
3280 	{ NULL, NULL, NULL, NULL, NULL, NULL }
3281 };
3282 
3283 
3284 static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = {
3285 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3286 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA,
3287 	  {
3288 		  { "properties", "a{sv}", ARG_OUT },
3289 		  END_ARGS
3290 	  }
3291 	},
3292 	{ NULL, NULL, { END_ARGS } }
3293 };
3294 
3295 
3296 /**
3297  * wpas_dbus_unregister_sta - Unregister a connected station from dbus
3298  * @wpa_s: wpa_supplicant interface structure
3299  * @sta: station MAC address
3300  * Returns: 0 on success, -1 on failure
3301  *
3302  * Unregisters STA representing object from dbus.
3303  */
wpas_dbus_unregister_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3304 int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3305 {
3306 	struct wpas_dbus_priv *ctrl_iface;
3307 	char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3308 
3309 	/* Do nothing if the control interface is not turned on */
3310 	if (!wpa_s || !wpa_s->global)
3311 		return 0;
3312 	ctrl_iface = wpa_s->global->dbus;
3313 	if (!ctrl_iface)
3314 		return 0;
3315 
3316 	os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3317 		    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3318 		    wpa_s->dbus_new_path, MAC2STR(sta));
3319 
3320 	wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
3321 		   station_obj_path);
3322 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3323 						 station_obj_path)) {
3324 		wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
3325 			   station_obj_path);
3326 		return -1;
3327 	}
3328 
3329 	wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
3330 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3331 
3332 	return 0;
3333 }
3334 
3335 
3336 /**
3337  * wpas_dbus_register_sta - Register a connected station with dbus
3338  * @wpa_s: wpa_supplicant interface structure
3339  * @sta: station MAC address
3340  * Returns: 0 on success, -1 on failure
3341  *
3342  * Registers STA representing object with dbus.
3343  */
wpas_dbus_register_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3344 int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3345 {
3346 	struct wpas_dbus_priv *ctrl_iface;
3347 	struct wpa_dbus_object_desc *obj_desc;
3348 	char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3349 	struct sta_handler_args *arg;
3350 
3351 	/* Do nothing if the control interface is not turned on */
3352 	if (!wpa_s || !wpa_s->global)
3353 		return 0;
3354 	ctrl_iface = wpa_s->global->dbus;
3355 	if (!ctrl_iface)
3356 		return 0;
3357 
3358 	os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3359 		    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3360 		    wpa_s->dbus_new_path, MAC2STR(sta));
3361 
3362 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3363 	if (!obj_desc) {
3364 		wpa_printf(MSG_ERROR,
3365 			   "Not enough memory to create object description");
3366 		goto err;
3367 	}
3368 
3369 	arg = os_zalloc(sizeof(struct sta_handler_args));
3370 	if (!arg) {
3371 		wpa_printf(MSG_ERROR,
3372 			   "Not enough memory to create arguments for handler");
3373 		goto err;
3374 	}
3375 	arg->wpa_s = wpa_s;
3376 	arg->sta = sta;
3377 
3378 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3379 			   wpas_dbus_sta_properties, wpas_dbus_sta_signals);
3380 
3381 	wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
3382 		   station_obj_path);
3383 	if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
3384 					       wpa_s->ifname, obj_desc)) {
3385 		wpa_printf(MSG_ERROR,
3386 			   "Cannot register STA dbus object %s",
3387 			   station_obj_path);
3388 		goto err;
3389 	}
3390 
3391 	wpas_dbus_signal_station_added(wpa_s, station_obj_path);
3392 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3393 
3394 	return 0;
3395 
3396 err:
3397 	free_dbus_object_desc(obj_desc);
3398 	return -1;
3399 }
3400 
3401 
3402 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
3403 	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3404 	  (WPADBusMethodHandler) wpas_dbus_handler_scan,
3405 	  {
3406 		  { "args", "a{sv}", ARG_IN },
3407 		  END_ARGS
3408 	  }
3409 	},
3410 	{ "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
3411 	  (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
3412 	  {
3413 		  { "args", "a{sv}", ARG_OUT },
3414 		  END_ARGS
3415 	  }
3416 	},
3417 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3418 	  (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
3419 	  {
3420 		  END_ARGS
3421 	  }
3422 	},
3423 	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3424 	  (WPADBusMethodHandler) wpas_dbus_handler_add_network,
3425 	  {
3426 		  { "args", "a{sv}", ARG_IN },
3427 		  { "path", "o", ARG_OUT },
3428 		  END_ARGS
3429 	  }
3430 	},
3431 	{ "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
3432 	  (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
3433 	  {
3434 		  END_ARGS
3435 	  }
3436 	},
3437 	{ "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
3438 	  (WPADBusMethodHandler) wpas_dbus_handler_reattach,
3439 	  {
3440 		  END_ARGS
3441 	  }
3442 	},
3443 	{ "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3444 	  (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
3445 	  {
3446 		  END_ARGS
3447 	  }
3448 	},
3449 	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3450 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
3451 	  {
3452 		  { "path", "o", ARG_IN },
3453 		  END_ARGS
3454 	  }
3455 	},
3456 	{ "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
3457 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
3458 	  {
3459 		  END_ARGS
3460 	  }
3461 	},
3462 	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3463 	  (WPADBusMethodHandler) wpas_dbus_handler_select_network,
3464 	  {
3465 		  { "path", "o", ARG_IN },
3466 		  END_ARGS
3467 	  }
3468 	},
3469 	{ "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
3470 	  (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
3471 	  {
3472 		  { "path", "o", ARG_IN },
3473 		  { "field", "s", ARG_IN },
3474 		  { "value", "s", ARG_IN },
3475 		  END_ARGS
3476 	  }
3477 	},
3478 	{ "Roam", WPAS_DBUS_NEW_IFACE_INTERFACE,
3479 	  (WPADBusMethodHandler) wpas_dbus_handler_roam,
3480 	  {
3481 		  { "addr", "s", ARG_IN },
3482 		  END_ARGS
3483 	  }
3484 	},
3485 
3486 #ifndef CONFIG_NO_CONFIG_BLOBS
3487 	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3488 	  (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
3489 	  {
3490 		  { "name", "s", ARG_IN },
3491 		  { "data", "ay", ARG_IN },
3492 		  END_ARGS
3493 	  }
3494 	},
3495 	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3496 	  (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
3497 	  {
3498 		  { "name", "s", ARG_IN },
3499 		  { "data", "ay", ARG_OUT },
3500 		  END_ARGS
3501 	  }
3502 	},
3503 	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3504 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
3505 	  {
3506 		  { "name", "s", ARG_IN },
3507 		  END_ARGS
3508 	  }
3509 	},
3510 #endif /* CONFIG_NO_CONFIG_BLOBS */
3511 	{ "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
3512 	  (WPADBusMethodHandler)
3513 	  wpas_dbus_handler_set_pkcs11_engine_and_module_path,
3514 	  {
3515 		  { "pkcs11_engine_path", "s", ARG_IN },
3516 		  { "pkcs11_module_path", "s", ARG_IN },
3517 		  END_ARGS
3518 	  }
3519 	},
3520 #ifdef CONFIG_WPS
3521 	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
3522 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
3523 	  {
3524 		  { "args", "a{sv}", ARG_IN },
3525 		  { "output", "a{sv}", ARG_OUT },
3526 		  END_ARGS
3527 	  }
3528 	},
3529 	{ "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
3530 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
3531 	  {
3532 		  END_ARGS
3533 	  }
3534 	},
3535 #endif /* CONFIG_WPS */
3536 #ifdef CONFIG_P2P
3537 	{ "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3538 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
3539 	  {
3540 		  { "args", "a{sv}", ARG_IN },
3541 		  END_ARGS
3542 	  }
3543 	},
3544 	{ "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3545 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
3546 	  {
3547 		  END_ARGS
3548 	  }
3549 	},
3550 	{ "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3551 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
3552 	  {
3553 		  { "timeout", "i", ARG_IN },
3554 		  END_ARGS
3555 	  }
3556 	},
3557 	{ "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3558 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
3559 	  {
3560 		  { "args", "a{sv}", ARG_IN },
3561 		  END_ARGS
3562 	  }
3563 	},
3564 	{ "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3565 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
3566 	  {
3567 		  { "args", "a{sv}", ARG_IN },
3568 		  END_ARGS
3569 	  }
3570 	},
3571 	{ "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3572 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
3573 	  {
3574 		  { "peer", "o", ARG_IN },
3575 		  { "config_method", "s", ARG_IN },
3576 		  END_ARGS
3577 	  }
3578 	},
3579 	{ "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3580 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
3581 	  {
3582 		  { "args", "a{sv}", ARG_IN },
3583 		  { "generated_pin", "s", ARG_OUT },
3584 		  END_ARGS
3585 	  }
3586 	},
3587 	{ "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3588 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
3589 	  {
3590 		  { "args", "a{sv}", ARG_IN },
3591 		  END_ARGS
3592 	  }
3593 	},
3594 	{ "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3595 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
3596 	  {
3597 		  END_ARGS
3598 	  }
3599 	},
3600 	{ "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3601 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
3602 	  {
3603 		  { "args", "a{sv}", ARG_IN },
3604 		  END_ARGS
3605 	  }
3606 	},
3607 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3608 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
3609 	  {
3610 		  END_ARGS
3611 	  }
3612 	},
3613 	{ "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3614 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
3615 	  {
3616 		  { "peer", "o", ARG_IN },
3617 		  END_ARGS
3618 	  }
3619 	},
3620 	{ "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3621 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
3622 	  {
3623 		  { "args", "a{sv}", ARG_IN },
3624 		  END_ARGS
3625 	  }
3626 	},
3627 	{ "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3628 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
3629 	  {
3630 		  END_ARGS
3631 	  }
3632 	},
3633 	{ "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3634 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
3635 	  {
3636 		  { "args", "a{sv}", ARG_IN },
3637 		  END_ARGS
3638 	  }
3639 	},
3640 	{ "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3641 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
3642 	  {
3643 		  { "args", "a{sv}", ARG_IN },
3644 		  END_ARGS
3645 	  }
3646 	},
3647 	{ "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3648 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
3649 	  {
3650 		  END_ARGS
3651 	  }
3652 	},
3653 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3654 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
3655 	  {
3656 		  { "args", "a{sv}", ARG_IN },
3657 		  { "ref", "t", ARG_OUT },
3658 		  END_ARGS
3659 	  }
3660 	},
3661 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3662 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
3663 	  {
3664 		  { "args", "a{sv}", ARG_IN },
3665 		  END_ARGS
3666 	  }
3667 	},
3668 	{ "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3669 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
3670 	  {
3671 		  { "args", "t", ARG_IN },
3672 		  END_ARGS
3673 	  }
3674 	},
3675 	{ "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3676 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
3677 	  {
3678 		  END_ARGS
3679 	  }
3680 	},
3681 	{ "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3682 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
3683 	  {
3684 		  { "arg", "i", ARG_IN },
3685 		  END_ARGS
3686 	  }
3687 	},
3688 	{ "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3689 	  (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
3690 	  {
3691 		  { "args", "a{sv}", ARG_IN },
3692 		  { "path", "o", ARG_OUT },
3693 		  END_ARGS
3694 	  }
3695 	},
3696 	{ "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3697 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
3698 	  {
3699 		  { "path", "o", ARG_IN },
3700 		  END_ARGS
3701 	  }
3702 	},
3703 	{ "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3704 	  (WPADBusMethodHandler)
3705 	  wpas_dbus_handler_remove_all_persistent_groups,
3706 	  {
3707 		  END_ARGS
3708 	  }
3709 	},
3710 #endif /* CONFIG_P2P */
3711 	{ "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
3712 	  (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
3713 	  {
3714 		  { "age", "u", ARG_IN },
3715 		  END_ARGS
3716 	  }
3717 	},
3718 #ifdef CONFIG_AP
3719 	{ "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3720 	  (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
3721 	  {
3722 		  END_ARGS
3723 	  }
3724 	},
3725 	{ "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3726 	  (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
3727 	  {
3728 		  END_ARGS
3729 	  }
3730 	},
3731 #endif /* CONFIG_AP */
3732 	{ "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
3733 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
3734 	  {
3735 		  END_ARGS
3736 	  }
3737 	},
3738 	{ "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
3739 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
3740 	  {
3741 		  END_ARGS
3742 	  }
3743 	},
3744 #ifdef CONFIG_AUTOSCAN
3745 	{ "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3746 	  (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
3747 	  {
3748 		  { "arg", "s", ARG_IN },
3749 		  END_ARGS
3750 	  }
3751 	},
3752 #endif /* CONFIG_AUTOSCAN */
3753 #ifdef CONFIG_TDLS
3754 	{ "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
3755 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
3756 	  {
3757 		  { "peer_address", "s", ARG_IN },
3758 		  END_ARGS
3759 	  }
3760 	},
3761 	{ "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
3762 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
3763 	  {
3764 		  { "peer_address", "s", ARG_IN },
3765 		  END_ARGS
3766 	  }
3767 	},
3768 	{ "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
3769 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
3770 	  {
3771 		  { "peer_address", "s", ARG_IN },
3772 		  { "status", "s", ARG_OUT },
3773 		  END_ARGS
3774 	  }
3775 	},
3776 	{ "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
3777 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
3778 	  {
3779 		  { "peer_address", "s", ARG_IN },
3780 		  END_ARGS
3781 	  }
3782 	},
3783 	{ "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3784 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch,
3785 	  {
3786 		  { "args", "a{sv}", ARG_IN },
3787 		  END_ARGS
3788 	  }
3789 	},
3790 	{ "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3791 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch,
3792 	  {
3793 		  { "peer_address", "s", ARG_IN },
3794 		  END_ARGS
3795 	  }
3796 	},
3797 #endif /* CONFIG_TDLS */
3798 	{ "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
3799 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
3800 	  {
3801 		  { "frame_id", "i", ARG_IN },
3802 		  { "ielems", "ay", ARG_IN },
3803 		  END_ARGS
3804 	  }
3805 	},
3806 	{ "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3807 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
3808 	  {
3809 		  { "frame_id", "i", ARG_IN },
3810 		  { "ielems", "ay", ARG_OUT },
3811 		  END_ARGS
3812 	  }
3813 	},
3814 	{ "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
3815 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
3816 	  {
3817 		  { "frame_id", "i", ARG_IN },
3818 		  { "ielems", "ay", ARG_IN },
3819 		  END_ARGS
3820 	  }
3821 	},
3822 #ifndef CONFIG_NO_CONFIG_WRITE
3823 	{ "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
3824 	  (WPADBusMethodHandler) wpas_dbus_handler_save_config,
3825 	  {
3826 		  END_ARGS
3827 	  }
3828 	},
3829 #endif /* CONFIG_NO_CONFIG_WRITE */
3830 	{ "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3831 	  (WPADBusMethodHandler) wpas_dbus_handler_abort_scan,
3832 	  {
3833 		  END_ARGS
3834 	  }
3835 	},
3836 #ifdef CONFIG_INTERWORKING
3837 	{ "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
3838 	  (WPADBusMethodHandler) wpas_dbus_handler_add_cred,
3839 	  {
3840 		  { "args", "a{sv}", ARG_IN },
3841 		  { "path", "o", ARG_OUT },
3842 		  END_ARGS
3843 	  }
3844 	},
3845 	{ "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE,
3846 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_cred,
3847 	  {
3848 		  { "path", "o", ARG_IN },
3849 		  END_ARGS
3850 	  }
3851 	},
3852 	{ "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE,
3853 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds,
3854 	  {
3855 		  END_ARGS
3856 	  }
3857 	},
3858 	{ "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3859 	  (WPADBusMethodHandler) wpas_dbus_handler_interworking_select,
3860 	  {
3861 		  END_ARGS
3862 	  }
3863 	},
3864 	{"ANQPGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3865 	  (WPADBusMethodHandler) wpas_dbus_handler_anqp_get,
3866 	  {
3867 		  { "args", "a{sv}", ARG_IN },
3868 		  END_ARGS
3869 	  },
3870 	},
3871 #endif /* CONFIG_INTERWORKING */
3872 #ifdef CONFIG_NAN_USD
3873 	{ "NANPublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
3874 	  (WPADBusMethodHandler) wpas_dbus_handler_nan_publish,
3875 	  {
3876 		  { "args", "a{sv}", ARG_IN },
3877 		  { "publish_id", "u", ARG_OUT },
3878 		  END_ARGS
3879 	  }
3880 	},
3881 	{ "NANCancelPublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
3882 	  (WPADBusMethodHandler) wpas_dbus_handler_nan_cancel_publish,
3883 	  {
3884 		  { "publish_id", "u", ARG_IN },
3885 		  END_ARGS
3886 	  }
3887 	},
3888 	{ "NANUpdatePublish", WPAS_DBUS_NEW_IFACE_INTERFACE,
3889 	  (WPADBusMethodHandler) wpas_dbus_handler_nan_update_publish,
3890 	  {
3891 		  { "args", "a{sv}", ARG_IN },
3892 		  END_ARGS
3893 	  }
3894 	},
3895 	{ "NANPublishStopListen", WPAS_DBUS_NEW_IFACE_INTERFACE,
3896 	  (WPADBusMethodHandler) wpas_dbus_handler_nan_publish_stop_listen,
3897 	  {
3898 		  { "publish_id", "u", ARG_IN },
3899 		  END_ARGS
3900 	  }
3901 	},
3902 	{ "NANSubscribe", WPAS_DBUS_NEW_IFACE_INTERFACE,
3903 	  (WPADBusMethodHandler) wpas_dbus_handler_nan_subscribe,
3904 	  {
3905 		  { "args", "a{sv}", ARG_IN },
3906 		  { "subscribe_id", "u", ARG_OUT },
3907 		  END_ARGS
3908 	  }
3909 	},
3910 	{ "NANCancelSubscribe", WPAS_DBUS_NEW_IFACE_INTERFACE,
3911 	  (WPADBusMethodHandler) wpas_dbus_handler_nan_cancel_subscribe,
3912 	  {
3913 		  { "subscribe_id", "u", ARG_IN },
3914 		  END_ARGS
3915 	  }
3916 	},
3917 	{ "NANSubscribeStopListen", WPAS_DBUS_NEW_IFACE_INTERFACE,
3918 	  (WPADBusMethodHandler) wpas_dbus_handler_nan_subscribe_stop_listen,
3919 	  {
3920 		  { "subscribe_id", "u", ARG_IN },
3921 		  END_ARGS
3922 	  }
3923 	},
3924 	{ "NANTransmit", WPAS_DBUS_NEW_IFACE_INTERFACE,
3925 	  (WPADBusMethodHandler) wpas_dbus_handler_nan_transmit,
3926 	  {
3927 		  { "args", "a{sv}", ARG_IN },
3928 		  END_ARGS
3929 	  }
3930 	},
3931 #endif /* CONFIG_NAN_USD */
3932 	{ NULL, NULL, NULL, { END_ARGS } }
3933 };
3934 
3935 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
3936 	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
3937 	  wpas_dbus_getter_capabilities,
3938 	  NULL,
3939 	  NULL
3940 	},
3941 	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3942 	  wpas_dbus_getter_state,
3943 	  NULL,
3944 	  NULL
3945 	},
3946 	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3947 	  wpas_dbus_getter_scanning,
3948 	  NULL,
3949 	  NULL
3950 	},
3951 	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3952 	  wpas_dbus_getter_ap_scan,
3953 	  wpas_dbus_setter_ap_scan,
3954 	  NULL
3955 	},
3956 	{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3957 	  wpas_dbus_getter_bss_expire_age,
3958 	  wpas_dbus_setter_bss_expire_age,
3959 	  NULL
3960 	},
3961 	{ "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3962 	  wpas_dbus_getter_bss_expire_count,
3963 	  wpas_dbus_setter_bss_expire_count,
3964 	  NULL
3965 	},
3966 	{ "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3967 	  wpas_dbus_getter_country,
3968 	  wpas_dbus_setter_country,
3969 	  NULL
3970 	},
3971 	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3972 	  wpas_dbus_getter_ifname,
3973 	  NULL,
3974 	  NULL
3975 	},
3976 	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3977 	  wpas_dbus_getter_driver,
3978 	  NULL,
3979 	  NULL
3980 	},
3981 	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3982 	  wpas_dbus_getter_bridge_ifname,
3983 	  wpas_dbus_setter_bridge_ifname,
3984 	  NULL
3985 	},
3986 	{ "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3987 	  wpas_dbus_getter_config_file,
3988 	  NULL,
3989 	  NULL
3990 	},
3991 	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3992 	  wpas_dbus_getter_current_bss,
3993 	  NULL,
3994 	  NULL
3995 	},
3996 	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3997 	  wpas_dbus_getter_current_network,
3998 	  NULL,
3999 	  NULL
4000 	},
4001 	{ "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
4002 	  wpas_dbus_getter_current_auth_mode,
4003 	  NULL,
4004 	  NULL
4005 	},
4006 	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
4007 	  wpas_dbus_getter_blobs,
4008 	  NULL,
4009 	  NULL
4010 	},
4011 	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
4012 	  wpas_dbus_getter_bsss,
4013 	  NULL,
4014 	  NULL
4015 	},
4016 	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
4017 	  wpas_dbus_getter_networks,
4018 	  NULL,
4019 	  NULL
4020 	},
4021 	{ "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
4022 	  wpas_dbus_getter_fast_reauth,
4023 	  wpas_dbus_setter_fast_reauth,
4024 	  NULL
4025 	},
4026 	{ "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
4027 	  wpas_dbus_getter_scan_interval,
4028 	  wpas_dbus_setter_scan_interval,
4029 	  NULL
4030 	},
4031 	{ "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
4032 	  wpas_dbus_getter_pkcs11_engine_path,
4033 	  NULL,
4034 	  NULL
4035 	},
4036 	{ "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
4037 	  wpas_dbus_getter_pkcs11_module_path,
4038 	  NULL,
4039 	  NULL
4040 	},
4041 #ifdef CONFIG_WPS
4042 	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
4043 	  wpas_dbus_getter_process_credentials,
4044 	  wpas_dbus_setter_process_credentials,
4045 	  NULL
4046 	},
4047 	{ "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
4048 	  wpas_dbus_getter_config_methods,
4049 	  wpas_dbus_setter_config_methods,
4050 	  NULL
4051 	},
4052 	{
4053 	  "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
4054 	  wpas_dbus_getter_wps_device_name,
4055 	  wpas_dbus_setter_wps_device_name,
4056 	  NULL
4057 	},
4058 	{
4059 	  "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
4060 	  wpas_dbus_getter_wps_manufacturer,
4061 	  wpas_dbus_setter_wps_manufacturer,
4062 	  NULL
4063 	},
4064 	{
4065 	  "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
4066 	  wpas_dbus_getter_wps_device_model_name,
4067 	  wpas_dbus_setter_wps_device_model_name,
4068 	  NULL
4069 	},
4070 	{
4071 	  "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
4072 	  wpas_dbus_getter_wps_device_model_number,
4073 	  wpas_dbus_setter_wps_device_model_number,
4074 	  NULL
4075 	},
4076 	{
4077 	  "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
4078 	  wpas_dbus_getter_wps_device_serial_number,
4079 	  wpas_dbus_setter_wps_device_serial_number,
4080 	  NULL
4081 	},
4082 	{
4083 	  "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
4084 	  wpas_dbus_getter_wps_device_device_type,
4085 	  wpas_dbus_setter_wps_device_device_type,
4086 	  NULL
4087 	},
4088 #endif /* CONFIG_WPS */
4089 #ifdef CONFIG_P2P
4090 	{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
4091 	  wpas_dbus_getter_p2p_device_config,
4092 	  wpas_dbus_setter_p2p_device_config,
4093 	  NULL
4094 	},
4095 	{ "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ay",
4096 	  wpas_dbus_getter_p2p_device_address,
4097 	  NULL,
4098 	  NULL
4099 	},
4100 	{ "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
4101 	  wpas_dbus_getter_p2p_peers,
4102 	  NULL,
4103 	  NULL
4104 	},
4105 	{ "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
4106 	  wpas_dbus_getter_p2p_role,
4107 	  NULL,
4108 	  NULL
4109 	},
4110 	{ "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
4111 	  wpas_dbus_getter_p2p_group,
4112 	  NULL,
4113 	  NULL
4114 	},
4115 	{ "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
4116 	  wpas_dbus_getter_p2p_peergo,
4117 	  NULL,
4118 	  NULL
4119 	},
4120 	{ "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
4121 	  wpas_dbus_getter_persistent_groups,
4122 	  NULL,
4123 	  NULL
4124 	},
4125 #endif /* CONFIG_P2P */
4126 	{ "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
4127 	  wpas_dbus_getter_disconnect_reason,
4128 	  NULL,
4129 	  NULL
4130 	},
4131 	{ "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
4132 	  wpas_dbus_getter_auth_status_code,
4133 	  NULL,
4134 	  NULL
4135 	},
4136 	{ "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
4137 	  wpas_dbus_getter_assoc_status_code,
4138 	  NULL,
4139 	  NULL
4140 	},
4141 	{
4142 	  "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
4143 	  wpas_dbus_getter_roam_time,
4144 	  NULL,
4145 	  NULL
4146 	},
4147 	{
4148 	  "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
4149 	  wpas_dbus_getter_roam_complete,
4150 	  NULL,
4151 	  NULL
4152 	},
4153 	{
4154 	  "ScanInProgress6GHz", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
4155 	  wpas_dbus_getter_scan_in_progress_6ghz,
4156 	  NULL,
4157 	  NULL
4158 	},
4159 	{
4160 	  "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
4161 	  wpas_dbus_getter_session_length,
4162 	  NULL,
4163 	  NULL
4164 	},
4165 	{
4166 	  "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
4167 	  wpas_dbus_getter_bss_tm_status,
4168 	  NULL,
4169 	  NULL
4170 	},
4171 #ifdef CONFIG_MESH
4172 	{ "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay",
4173 	  wpas_dbus_getter_mesh_peers,
4174 	  NULL,
4175 	  NULL
4176 	},
4177 	{ "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay",
4178 	  wpas_dbus_getter_mesh_group,
4179 	  NULL,
4180 	  NULL
4181 	},
4182 #endif /* CONFIG_MESH */
4183 	{ "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
4184 	  wpas_dbus_getter_stas,
4185 	  NULL,
4186 	  NULL
4187 	},
4188 	{ "MACAddressRandomizationMask", WPAS_DBUS_NEW_IFACE_INTERFACE,
4189 	  "a{say}",
4190 	  wpas_dbus_getter_mac_address_randomization_mask,
4191 	  wpas_dbus_setter_mac_address_randomization_mask,
4192 	  NULL
4193 	},
4194 	{ "MACAddress", WPAS_DBUS_NEW_IFACE_INTERFACE, "ay",
4195 	  wpas_dbus_getter_mac_address,
4196 	  NULL,
4197 	  NULL,
4198 	},
4199 	{ "SignalChange", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
4200 	  wpas_dbus_getter_signal_change,
4201 	  NULL,
4202 	  NULL
4203 	},
4204 	{ NULL, NULL, NULL, NULL, NULL, NULL }
4205 };
4206 
4207 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
4208 	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4209 	  {
4210 		  { "success", "b", ARG_OUT },
4211 		  END_ARGS
4212 	  }
4213 	},
4214 	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4215 	  {
4216 		  { "path", "o", ARG_OUT },
4217 		  { "properties", "a{sv}", ARG_OUT },
4218 		  END_ARGS
4219 	  }
4220 	},
4221 	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4222 	  {
4223 		  { "path", "o", ARG_OUT },
4224 		  END_ARGS
4225 	  }
4226 	},
4227 	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4228 	  {
4229 		  { "name", "s", ARG_OUT },
4230 		  END_ARGS
4231 	  }
4232 	},
4233 	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4234 	  {
4235 		  { "name", "s", ARG_OUT },
4236 		  END_ARGS
4237 	  }
4238 	},
4239 	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4240 	  {
4241 		  { "path", "o", ARG_OUT },
4242 		  { "properties", "a{sv}", ARG_OUT },
4243 		  END_ARGS
4244 	  }
4245 	},
4246 	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4247 	  {
4248 		  { "path", "o", ARG_OUT },
4249 		  END_ARGS
4250 	  }
4251 	},
4252 	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
4253 	  {
4254 		  { "path", "o", ARG_OUT },
4255 		  END_ARGS
4256 	  }
4257 	},
4258 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4259 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
4260 	  {
4261 		  { "properties", "a{sv}", ARG_OUT },
4262 		  END_ARGS
4263 	  }
4264 	},
4265 #ifdef CONFIG_WPS
4266 	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
4267 	  {
4268 		  { "name", "s", ARG_OUT },
4269 		  { "args", "a{sv}", ARG_OUT },
4270 		  END_ARGS
4271 	  }
4272 	},
4273 	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
4274 	  {
4275 		  { "credentials", "a{sv}", ARG_OUT },
4276 		  END_ARGS
4277 	  }
4278 	},
4279 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4280 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
4281 	  {
4282 		  { "properties", "a{sv}", ARG_OUT },
4283 		  END_ARGS
4284 	  }
4285 	},
4286 #endif /* CONFIG_WPS */
4287 #ifdef CONFIG_P2P
4288 	{ "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4289 	  {
4290 		  { "path", "o", ARG_OUT },
4291 		  END_ARGS
4292 	  }
4293 	},
4294 	{ "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4295 	  {
4296 		  { "path", "o", ARG_OUT },
4297 		  { "properties", "a{sv}", ARG_OUT },
4298 		  END_ARGS
4299 	  }
4300 	},
4301 	{ "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4302 	  {
4303 		  { "path", "o", ARG_OUT },
4304 		  END_ARGS
4305 	  }
4306 	},
4307 	{ "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4308 	  {
4309 		  END_ARGS
4310 	  }
4311 	},
4312 	{ "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4313 	  {
4314 		  { "peer_object", "o", ARG_OUT },
4315 		  { "pin", "s", ARG_OUT },
4316 		  END_ARGS
4317 	  }
4318 	},
4319 	{ "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4320 	  {
4321 		  { "peer_object", "o", ARG_OUT },
4322 		  { "pin", "s", ARG_OUT },
4323 		  END_ARGS
4324 	  }
4325 	},
4326 	{ "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4327 	  {
4328 		  { "peer_object", "o", ARG_OUT },
4329 		  END_ARGS
4330 	  }
4331 	},
4332 	{ "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4333 	  {
4334 		  { "peer_object", "o", ARG_OUT },
4335 		  END_ARGS
4336 	  }
4337 	},
4338 	{ "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4339 	  {
4340 		  { "peer_object", "o", ARG_OUT },
4341 		  END_ARGS
4342 	  }
4343 	},
4344 	{ "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4345 	  {
4346 		  { "peer_object", "o", ARG_OUT },
4347 		  END_ARGS
4348 	  }
4349 	},
4350 	{ "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4351 	  {
4352 		  { "peer_object", "o", ARG_OUT },
4353 		  { "status", "i", ARG_OUT },
4354 		  END_ARGS
4355 	  }
4356 	},
4357 	{ "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4358 	  {
4359 		  { "properties", "a{sv}", ARG_OUT },
4360 		  END_ARGS
4361 	  }
4362 	},
4363 	{ "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4364 	  {
4365 		  { "reason", "s", ARG_OUT },
4366 		  END_ARGS
4367 	  }
4368 	},
4369 	{ "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4370 	  {
4371 		  { "properties", "a{sv}", ARG_OUT },
4372 		  END_ARGS
4373 	  }
4374 	},
4375 	{ "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4376 	  {
4377 		  { "properties", "a{sv}", ARG_OUT },
4378 		  END_ARGS
4379 	  }
4380 	},
4381 	{ "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4382 	  {
4383 		  { "path", "o", ARG_OUT },
4384 		  { "dev_passwd_id", "q", ARG_OUT },
4385 		  { "device_go_intent", "y", ARG_OUT },
4386 		  END_ARGS
4387 	  }
4388 	},
4389 	{ "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4390 	  {
4391 		  { "invite_result", "a{sv}", ARG_OUT },
4392 		  END_ARGS
4393 	  }
4394 	},
4395 	{ "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4396 	  {
4397 		  { "properties", "a{sv}", ARG_OUT },
4398 		  END_ARGS
4399 	  }
4400 	},
4401 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4402 	  {
4403 		  { "sd_request", "a{sv}", ARG_OUT },
4404 		  END_ARGS
4405 	  }
4406 	},
4407 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4408 	  {
4409 		  { "sd_response", "a{sv}", ARG_OUT },
4410 		  END_ARGS
4411 	  }
4412 	},
4413 	{ "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4414 	  {
4415 		  { "path", "o", ARG_OUT },
4416 		  { "properties", "a{sv}", ARG_OUT },
4417 		  END_ARGS
4418 	  }
4419 	},
4420 	{ "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4421 	  {
4422 		  { "path", "o", ARG_OUT },
4423 		  END_ARGS
4424 	  }
4425 	},
4426 	{ "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4427 	  {
4428 		  { "name", "s", ARG_OUT },
4429 		  { "args", "a{sv}", ARG_OUT },
4430 		  END_ARGS
4431 	  }
4432 	},
4433 	{ "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4434 	  {
4435 		  { "properties", "a{sv}", ARG_OUT },
4436 		  END_ARGS
4437 	  }
4438 	},
4439 	{ "BootstrappingRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4440 	  {
4441 		  { "path", "o", ARG_OUT },
4442 		  { "bootstrap_method", "q", ARG_OUT },
4443 		  END_ARGS
4444 	  }
4445 	},
4446 	{ "BootstrappingCompleted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4447 	  {
4448 		  { "path", "o", ARG_OUT },
4449 		  { "status", "i", ARG_OUT },
4450 		  END_ARGS
4451 	  }
4452 	},
4453 #endif /* CONFIG_P2P */
4454 #ifdef CONFIG_AP
4455 	{ "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4456 	  {
4457 		  { "args", "a{sv}", ARG_OUT },
4458 		  END_ARGS
4459 	  }
4460 	},
4461 #endif /* CONFIG_AP */
4462 	{ "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
4463 	  {
4464 		  { "certification", "a{sv}", ARG_OUT },
4465 		  END_ARGS
4466 	  }
4467 	},
4468 	{ "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
4469 	  {
4470 		  { "status", "s", ARG_OUT },
4471 		  { "parameter", "s", ARG_OUT },
4472 		  END_ARGS
4473 	  }
4474 	},
4475 	{ "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4476 	  {
4477 		  { "name", "s", ARG_OUT },
4478 		  END_ARGS
4479 	  }
4480 	},
4481 	{ "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4482 	  {
4483 		  { "name", "s", ARG_OUT },
4484 		  END_ARGS
4485 	  }
4486 	},
4487 	{ "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4488 	  {
4489 		  { "path", "o", ARG_OUT },
4490 		  { "properties", "a{sv}", ARG_OUT },
4491 		  END_ARGS
4492 	  }
4493 	},
4494 	{ "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4495 	  {
4496 		  { "path", "o", ARG_OUT },
4497 		  END_ARGS
4498 	  }
4499 	},
4500 	{ "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4501 	  {
4502 		  { "path", "o", ARG_OUT },
4503 		  { "field", "s", ARG_OUT },
4504 		  { "text", "s", ARG_OUT },
4505 		  END_ARGS
4506 	  }
4507 	},
4508 #ifdef CONFIG_MESH
4509 	{ "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH,
4510 	  {
4511 		  { "args", "a{sv}", ARG_OUT },
4512 		  END_ARGS
4513 	  }
4514 	},
4515 	{ "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH,
4516 	  {
4517 		  { "args", "a{sv}", ARG_OUT },
4518 		  END_ARGS
4519 	  }
4520 	},
4521 	{ "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH,
4522 	  {
4523 		  { "args", "a{sv}", ARG_OUT },
4524 		  END_ARGS
4525 	  }
4526 	},
4527 	{ "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH,
4528 	  {
4529 		  { "args", "a{sv}", ARG_OUT },
4530 		  END_ARGS
4531 	  }
4532 	},
4533 #endif /* CONFIG_MESH */
4534 #ifdef CONFIG_INTERWORKING
4535 	{ "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4536 	  {
4537 		  { "bss", "o", ARG_OUT },
4538 		  { "cred", "o", ARG_OUT },
4539 		  { "properties", "a{sv}", ARG_OUT },
4540 		  END_ARGS
4541 	  }
4542 	},
4543 	{ "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4544 	  {
4545 		  END_ARGS
4546 	  }
4547 	},
4548 	{"ANQPQueryDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
4549 	  {
4550 		  { "addr", "s", ARG_OUT },
4551 		  { "result", "s", ARG_OUT },
4552 		  END_ARGS
4553 	  }
4554 	},
4555 #endif /* CONFIG_INTERWORKING */
4556 #ifdef CONFIG_HS20
4557 	{ "HS20TermsAndConditions", WPAS_DBUS_NEW_IFACE_INTERFACE,
4558 	  {
4559 		  { "url", "s", ARG_OUT },
4560 		  END_ARGS
4561 	  }
4562 	},
4563 #endif /* CONFIG_HS20 */
4564 #ifdef CONFIG_NAN_USD
4565 	{ "NANDiscoveryResult", WPAS_DBUS_NEW_IFACE_INTERFACE,
4566 	  {
4567 		  { "args", "a{sv}", ARG_OUT },
4568 		  END_ARGS
4569 	  }
4570 	},
4571 	{ "NANReplied", WPAS_DBUS_NEW_IFACE_INTERFACE,
4572 	  {
4573 		  { "args", "a{sv}", ARG_OUT },
4574 		  END_ARGS
4575 	  }
4576 	},
4577 	{ "NANReceive", WPAS_DBUS_NEW_IFACE_INTERFACE,
4578 	  {
4579 		  { "args", "a{sv}", ARG_OUT },
4580 		  END_ARGS
4581 	  }
4582 	},
4583 	{ "NANPublishTerminated", WPAS_DBUS_NEW_IFACE_INTERFACE,
4584 	  {
4585 		  { "publish_id", "u", ARG_OUT },
4586 		  { "reason", "s", ARG_OUT },
4587 		  END_ARGS
4588 	  }
4589 	},
4590 	{ "NANSubscribeTerminated", WPAS_DBUS_NEW_IFACE_INTERFACE,
4591 	  {
4592 		  { "subscribe_id", "u", ARG_OUT },
4593 		  { "reason", "s", ARG_OUT },
4594 		  END_ARGS
4595 	  }
4596 	},
4597 #endif /* CONFIG_NAN_USD */
4598 	{ NULL, NULL, { END_ARGS } }
4599 };
4600 
4601 
wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv * priv)4602 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
4603 {
4604 	size_t all_size;
4605 	unsigned int i, j, count, num_const, num_globals;
4606 	const char *global_name;
4607 	static const char * const ignored_globals[] = {
4608 		"bss_expiration_age", "bss_expiration_scan_count",
4609 		"ap_scan", "country", "fast_reauth",
4610 		"pkcs11_engine_path", "pkcs11_module_path"
4611 	};
4612 
4613 	/* wpas_dbus_interface_properties terminates with a NULL element */
4614 	num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
4615 
4616 	num_globals = wpa_config_get_num_global_field_names();
4617 	priv->globals_start = num_const;
4618 
4619 	/* allocate enough for all properties + terminating NULL element */
4620 	all_size = (num_globals + num_const + 1) *
4621 		sizeof(wpas_dbus_interface_properties[0]);
4622 	priv->all_interface_properties = os_zalloc(all_size);
4623 	if (!priv->all_interface_properties) {
4624 		wpa_printf(MSG_ERROR,
4625 			   "dbus: Not enough memory for interface properties");
4626 		return -1;
4627 	}
4628 
4629 	/* Copy constant interface properties to the start of the array */
4630 	os_memcpy(priv->all_interface_properties,
4631 		  wpas_dbus_interface_properties,
4632 		  sizeof(wpas_dbus_interface_properties));
4633 
4634 	/* Dynamically construct interface global properties */
4635 	for (i = 0, count = num_const; i < num_globals; i++) {
4636 		struct wpa_dbus_property_desc *desc;
4637 		int no_var = 0;
4638 
4639 		/* ignore globals that are actually just methods */
4640 		global_name = wpa_config_get_global_field_name(i, &no_var);
4641 		if (no_var)
4642 			continue;
4643 		/* Ignore fields already explicitly exposed */
4644 		for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
4645 			if (os_strcmp(global_name, ignored_globals[j]) == 0)
4646 				break;
4647 		}
4648 		if (j < ARRAY_SIZE(ignored_globals))
4649 			continue;
4650 
4651 		desc = &priv->all_interface_properties[count++];
4652 		desc->dbus_property = uscore_to_dbus(global_name);
4653 		if (!desc->dbus_property) {
4654 			wpa_printf(MSG_ERROR,
4655 				   "dbus: Not enough memory for D-Bus property name");
4656 			goto error;
4657 		}
4658 		desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
4659 		desc->type = "s";
4660 		desc->getter = wpas_dbus_getter_iface_global;
4661 		desc->setter = wpas_dbus_setter_iface_global;
4662 		desc->data = global_name;
4663 	}
4664 
4665 	return 0;
4666 
4667 error:
4668 	wpa_dbus_ctrl_iface_props_deinit(priv);
4669 	return -1;
4670 }
4671 
4672 
4673 /**
4674  * wpas_dbus_register_interface - Register an interface with D-Bus
4675  * @wpa_s: wpa_supplicant interface structure
4676  * Returns: 0 on success, -1 on failure
4677  */
wpas_dbus_register_interface(struct wpa_supplicant * wpa_s)4678 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
4679 {
4680 	struct wpa_dbus_object_desc *obj_desc = NULL;
4681 	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
4682 	int next;
4683 
4684 	/* Do nothing if the control interface is not turned on */
4685 	if (ctrl_iface == NULL)
4686 		return 0;
4687 
4688 	/* Create and set the interface's object path */
4689 	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4690 	if (wpa_s->dbus_new_path == NULL)
4691 		return -1;
4692 	next = ctrl_iface->next_objid++;
4693 	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
4694 		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
4695 		    next);
4696 
4697 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4698 	if (!obj_desc) {
4699 		wpa_printf(MSG_ERROR,
4700 			   "Not enough memory to create object description");
4701 		goto err;
4702 	}
4703 
4704 	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
4705 			   ctrl_iface->all_interface_properties,
4706 			   wpas_dbus_interface_signals);
4707 
4708 	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
4709 		   wpa_s->dbus_new_path);
4710 	if (wpa_dbus_register_object_per_iface(ctrl_iface,
4711 					       wpa_s->dbus_new_path,
4712 					       wpa_s->ifname, obj_desc))
4713 		goto err;
4714 
4715 	wpas_dbus_signal_interface_added(wpa_s);
4716 
4717 	return 0;
4718 
4719 err:
4720 	os_free(wpa_s->dbus_new_path);
4721 	wpa_s->dbus_new_path = NULL;
4722 	free_dbus_object_desc(obj_desc);
4723 	return -1;
4724 }
4725 
4726 
4727 /**
4728  * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
4729  * @wpa_s: wpa_supplicant interface structure
4730  * Returns: 0 on success, -1 on failure
4731  */
wpas_dbus_unregister_interface(struct wpa_supplicant * wpa_s)4732 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
4733 {
4734 	struct wpas_dbus_priv *ctrl_iface;
4735 
4736 	/* Do nothing if the control interface is not turned on */
4737 	if (wpa_s == NULL || wpa_s->global == NULL)
4738 		return 0;
4739 	ctrl_iface = wpa_s->global->dbus;
4740 	if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
4741 		return 0;
4742 
4743 	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
4744 		   wpa_s->dbus_new_path);
4745 
4746 #ifdef CONFIG_AP
4747 	if (wpa_s->preq_notify_peer) {
4748 		wpas_dbus_unsubscribe_noc(ctrl_iface);
4749 		os_free(wpa_s->preq_notify_peer);
4750 		wpa_s->preq_notify_peer = NULL;
4751 	}
4752 #endif /* CONFIG_AP */
4753 
4754 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
4755 						 wpa_s->dbus_new_path))
4756 		return -1;
4757 
4758 	wpas_dbus_signal_interface_removed(wpa_s);
4759 
4760 	os_free(wpa_s->dbus_new_path);
4761 	wpa_s->dbus_new_path = NULL;
4762 
4763 	return 0;
4764 }
4765 
4766 #ifdef CONFIG_P2P
4767 
4768 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
4769 	{ "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4770 	  wpas_dbus_getter_p2p_peer_device_name,
4771 	  NULL,
4772 	  NULL
4773 	},
4774 	{ "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4775 	  wpas_dbus_getter_p2p_peer_manufacturer,
4776 	  NULL,
4777 	  NULL
4778 	},
4779 	{ "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4780 	  wpas_dbus_getter_p2p_peer_modelname,
4781 	  NULL,
4782 	  NULL
4783 	},
4784 	{ "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4785 	  wpas_dbus_getter_p2p_peer_modelnumber,
4786 	  NULL,
4787 	  NULL
4788 	},
4789 	{ "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4790 	  wpas_dbus_getter_p2p_peer_serialnumber,
4791 	  NULL,
4792 	  NULL
4793 	},
4794 	{ "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4795 	  wpas_dbus_getter_p2p_peer_primary_device_type,
4796 	  NULL,
4797 	  NULL
4798 	},
4799 	{ "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
4800 	  wpas_dbus_getter_p2p_peer_config_method,
4801 	  NULL,
4802 	  NULL
4803 	},
4804 	{ "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
4805 	  wpas_dbus_getter_p2p_peer_level,
4806 	  NULL,
4807 	  NULL
4808 	},
4809 	{ "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4810 	  wpas_dbus_getter_p2p_peer_device_capability,
4811 	  NULL,
4812 	  NULL
4813 	},
4814 	{ "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4815 	  wpas_dbus_getter_p2p_peer_group_capability,
4816 	  NULL,
4817 	  NULL
4818 	},
4819 	{ "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4820 	  wpas_dbus_getter_p2p_peer_secondary_device_types,
4821 	  NULL,
4822 	  NULL
4823 	},
4824 	{ "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4825 	  wpas_dbus_getter_p2p_peer_vendor_extension,
4826 	  NULL,
4827 	  NULL
4828 	},
4829 	{ "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4830 	  wpas_dbus_getter_p2p_peer_ies,
4831 	  NULL,
4832 	  NULL
4833 	},
4834 	{ "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4835 	  wpas_dbus_getter_p2p_peer_device_address,
4836 	  NULL,
4837 	  NULL
4838 	},
4839 	{ "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
4840 	  wpas_dbus_getter_p2p_peer_groups,
4841 	  NULL,
4842 	  NULL
4843 	},
4844 	{ "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4845 	  wpas_dbus_getter_p2p_peer_vsie,
4846 	  NULL,
4847 	  NULL
4848 	},
4849 	{ NULL, NULL, NULL, NULL, NULL, NULL }
4850 };
4851 
4852 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
4853 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4854 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
4855 	  {
4856 		  { "properties", "a{sv}", ARG_OUT },
4857 		  END_ARGS
4858 	  }
4859 	},
4860 	{ NULL, NULL, { END_ARGS } }
4861 };
4862 
4863 /**
4864  * wpas_dbus_signal_peer - Send a peer related event signal
4865  * @wpa_s: %wpa_supplicant network interface data
4866  * @dev: peer device object
4867  * @interface: name of the interface emitting this signal.
4868  *	In case of peer objects, it would be emitted by either
4869  *	the "interface object" or by "peer objects"
4870  * @sig_name: signal name - DeviceFound
4871  * @properties: Whether to add a second argument with object properties
4872  *
4873  * Notify listeners about event related with p2p peer device
4874  */
wpas_dbus_signal_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr,const char * interface,const char * sig_name,dbus_bool_t properties)4875 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
4876 				  const u8 *dev_addr, const char *interface,
4877 				  const char *sig_name, dbus_bool_t properties)
4878 {
4879 	struct wpas_dbus_priv *iface;
4880 	DBusMessage *msg;
4881 	DBusMessageIter iter;
4882 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
4883 
4884 	if (wpa_s->p2p_mgmt)
4885 		wpa_s = wpa_s->parent;
4886 
4887 	iface = wpa_s->global->dbus;
4888 
4889 	/* Do nothing if the control interface is not turned on */
4890 	if (iface == NULL || !wpa_s->dbus_new_path)
4891 		return;
4892 
4893 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4894 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4895 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
4896 
4897 	msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
4898 				      sig_name);
4899 	if (msg == NULL)
4900 		return;
4901 
4902 	dbus_message_iter_init_append(msg, &iter);
4903 	path = peer_obj_path;
4904 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
4905 					    &path) ||
4906 	    (properties && !wpa_dbus_get_object_properties(
4907 		    iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
4908 		    &iter)))
4909 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4910 	else
4911 		dbus_connection_send(iface->con, msg, NULL);
4912 
4913 	dbus_message_unref(msg);
4914 }
4915 
4916 
4917 /**
4918  * wpas_dbus_signal_peer_found - Send a peer found signal
4919  * @wpa_s: %wpa_supplicant network interface data
4920  * @dev_addr: Peer P2P Device Address
4921  *
4922  * Notify listeners about find a p2p peer device found
4923  */
wpas_dbus_signal_peer_device_found(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4924 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
4925 					const u8 *dev_addr)
4926 {
4927 	wpas_dbus_signal_peer(wpa_s, dev_addr,
4928 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4929 			      "DeviceFound", FALSE);
4930 
4931 	wpas_dbus_signal_peer(wpa_s, dev_addr,
4932 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4933 			      "DeviceFoundProperties", TRUE);
4934 }
4935 
4936 /**
4937  * wpas_dbus_signal_peer_lost - Send a peer lost signal
4938  * @wpa_s: %wpa_supplicant network interface data
4939  * @dev_addr: Peer P2P Device Address
4940  *
4941  * Notify listeners about lost a p2p peer device
4942  */
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4943 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
4944 				       const u8 *dev_addr)
4945 {
4946 	wpas_dbus_signal_peer(wpa_s, dev_addr,
4947 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4948 			      "DeviceLost", FALSE);
4949 }
4950 
4951 /**
4952  * wpas_dbus_register_peer - Register a discovered peer object with dbus
4953  * @wpa_s: wpa_supplicant interface structure
4954  * @dev_addr: P2P Device Address of the peer
4955  * Returns: 0 on success, -1 on failure
4956  *
4957  * Registers network representing object with dbus
4958  */
wpas_dbus_register_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4959 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
4960 {
4961 	struct wpas_dbus_priv *ctrl_iface;
4962 	struct wpa_dbus_object_desc *obj_desc;
4963 	struct peer_handler_args *arg;
4964 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4965 
4966 	/* Do nothing if the control interface is not turned on */
4967 	if (wpa_s == NULL || wpa_s->global == NULL)
4968 		return 0;
4969 
4970 	ctrl_iface = wpa_s->global->dbus;
4971 	if (ctrl_iface == NULL)
4972 		return 0;
4973 
4974 	wpa_s = wpa_s->parent->parent;
4975 	if (!wpa_s->dbus_new_path)
4976 		return 0;
4977 
4978 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4979 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4980 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
4981 
4982 	wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
4983 		   peer_obj_path);
4984 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4985 	if (!obj_desc) {
4986 		wpa_printf(MSG_ERROR,
4987 			   "Not enough memory to create object description");
4988 		goto err;
4989 	}
4990 
4991 	/* allocate memory for handlers arguments */
4992 	arg = os_zalloc(sizeof(struct peer_handler_args));
4993 	if (!arg) {
4994 		wpa_printf(MSG_ERROR,
4995 			   "Not enough memory to create arguments for method");
4996 		goto err;
4997 	}
4998 
4999 	arg->wpa_s = wpa_s;
5000 	os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
5001 
5002 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
5003 			   NULL,
5004 			   wpas_dbus_p2p_peer_properties,
5005 			   wpas_dbus_p2p_peer_signals);
5006 
5007 	if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
5008 					       wpa_s->ifname, obj_desc))
5009 		goto err;
5010 
5011 	return 0;
5012 
5013 err:
5014 	free_dbus_object_desc(obj_desc);
5015 	return -1;
5016 }
5017 
5018 /**
5019  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
5020  * @wpa_s: wpa_supplicant interface structure
5021  * @dev_addr: p2p device addr
5022  * Returns: 0 on success, -1 on failure
5023  *
5024  * Registers network representing object with dbus
5025  */
wpas_dbus_unregister_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)5026 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
5027 				  const u8 *dev_addr)
5028 {
5029 	struct wpas_dbus_priv *ctrl_iface;
5030 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5031 	int ret;
5032 
5033 	/* Do nothing if the control interface is not turned on */
5034 	if (wpa_s == NULL || wpa_s->global == NULL)
5035 		return 0;
5036 
5037 	wpa_s = wpa_s->parent->parent;
5038 	if (!wpa_s->dbus_new_path)
5039 		return 0;
5040 
5041 	ctrl_iface = wpa_s->global->dbus;
5042 	if (ctrl_iface == NULL)
5043 		return 0;
5044 
5045 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5046 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
5047 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
5048 
5049 	wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
5050 		   peer_obj_path);
5051 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
5052 
5053 	return ret;
5054 }
5055 
5056 
5057 /**
5058  * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
5059  * @wpa_s: %wpa_supplicant network interface data
5060  *
5061  * Notify listeners about P2P Find stopped
5062  */
wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant * wpa_s)5063 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
5064 {
5065 	struct wpas_dbus_priv *iface;
5066 	DBusMessage *msg;
5067 
5068 	iface = wpa_s->global->dbus;
5069 
5070 	/* Do nothing if the control interface is not turned on */
5071 	if (iface == NULL)
5072 		return;
5073 
5074 	if (wpa_s->p2p_mgmt)
5075 		wpa_s = wpa_s->parent;
5076 
5077 	if (!wpa_s->dbus_new_path)
5078 		return;
5079 
5080 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5081 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
5082 				      "FindStopped");
5083 	if (msg == NULL)
5084 		return;
5085 
5086 	dbus_connection_send(iface->con, msg, NULL);
5087 
5088 	dbus_message_unref(msg);
5089 }
5090 
5091 
5092 /**
5093  * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
5094  * @wpa_s: %wpa_supplicant network interface data
5095  * @dev_addr: P2P Device Address
5096  *
5097  * Notify listeners about peer Groups property changes.
5098  */
wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant * wpa_s,const u8 * dev_addr)5099 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
5100 					  const u8 *dev_addr)
5101 {
5102 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5103 
5104 	if (wpa_s->p2p_mgmt)
5105 		wpa_s = wpa_s->parent;
5106 
5107 	if (!wpa_s->dbus_new_path)
5108 		return;
5109 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5110 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
5111 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
5112 
5113 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
5114 				       WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
5115 }
5116 
5117 
5118 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
5119 	{ "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
5120 	  wpas_dbus_getter_p2p_group_members,
5121 	  NULL,
5122 	  NULL
5123 	},
5124 	{ "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
5125 	  wpas_dbus_getter_p2p_group,
5126 	  NULL,
5127 	  NULL
5128 	},
5129 	{ "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
5130 	  wpas_dbus_getter_p2p_role,
5131 	  NULL,
5132 	  NULL
5133 	},
5134 	{ "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
5135 	  wpas_dbus_getter_p2p_group_ssid,
5136 	  NULL,
5137 	  NULL
5138 	},
5139 	{ "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
5140 	  wpas_dbus_getter_p2p_group_bssid,
5141 	  NULL,
5142 	  NULL
5143 	},
5144 	{ "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
5145 	  wpas_dbus_getter_p2p_group_frequency,
5146 	  NULL,
5147 	  NULL
5148 	},
5149 	{ "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
5150 	  wpas_dbus_getter_p2p_group_passphrase,
5151 	  NULL,
5152 	  NULL
5153 	},
5154 	{ "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
5155 	  wpas_dbus_getter_p2p_group_psk,
5156 	  NULL,
5157 	  NULL
5158 	},
5159 	{ "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
5160 	  wpas_dbus_getter_p2p_group_vendor_ext,
5161 	  wpas_dbus_setter_p2p_group_vendor_ext,
5162 	  NULL
5163 	},
5164 	{ "GODeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
5165 	  wpas_dbus_getter_p2p_group_go_device_address,
5166 	  NULL,
5167 	  NULL
5168 	},
5169 	{ NULL, NULL, NULL, NULL, NULL, NULL }
5170 };
5171 
5172 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
5173 	{ "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
5174 	  {
5175 		  { "peer", "o", ARG_OUT },
5176 		  END_ARGS
5177 	  }
5178 	},
5179 	{ "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
5180 	  {
5181 		  { "peer", "o", ARG_OUT },
5182 		  END_ARGS
5183 	  }
5184 	},
5185 	{ NULL, NULL, { END_ARGS } }
5186 };
5187 
5188 /**
5189  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
5190  * @wpa_s: wpa_supplicant interface structure
5191  * @ssid: SSID struct
5192  * Returns: 0 on success, -1 on failure
5193  *
5194  * Registers p2p group representing object with dbus
5195  */
wpas_dbus_register_p2p_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)5196 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
5197 				  struct wpa_ssid *ssid)
5198 {
5199 	struct wpas_dbus_priv *ctrl_iface;
5200 	struct wpa_dbus_object_desc *obj_desc;
5201 	char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5202 
5203 	/* Do nothing if the control interface is not turned on */
5204 	if (wpa_s == NULL || wpa_s->global == NULL)
5205 		return;
5206 
5207 	ctrl_iface = wpa_s->global->dbus;
5208 	if (ctrl_iface == NULL)
5209 		return;
5210 
5211 	if (wpa_s->dbus_groupobj_path) {
5212 		wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
5213 			   __func__, wpa_s->dbus_groupobj_path);
5214 		return;
5215 	}
5216 
5217 	if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
5218 		return;
5219 
5220 	wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
5221 	if (wpa_s->dbus_groupobj_path == NULL)
5222 		return;
5223 
5224 	wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
5225 		   group_obj_path);
5226 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
5227 	if (!obj_desc) {
5228 		wpa_printf(MSG_ERROR,
5229 			   "Not enough memory to create object description");
5230 		goto err;
5231 	}
5232 
5233 	wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
5234 			   wpas_dbus_p2p_group_properties,
5235 			   wpas_dbus_p2p_group_signals);
5236 
5237 	if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
5238 					       wpa_s->ifname, obj_desc))
5239 		goto err;
5240 
5241 	return;
5242 
5243 err:
5244 	if (wpa_s->dbus_groupobj_path) {
5245 		os_free(wpa_s->dbus_groupobj_path);
5246 		wpa_s->dbus_groupobj_path = NULL;
5247 	}
5248 
5249 	free_dbus_object_desc(obj_desc);
5250 }
5251 
5252 /**
5253  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
5254  * @wpa_s: wpa_supplicant interface structure
5255  * @ssid: network name of the p2p group started
5256  */
wpas_dbus_unregister_p2p_group(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid)5257 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
5258 				    const struct wpa_ssid *ssid)
5259 {
5260 	struct wpas_dbus_priv *ctrl_iface;
5261 
5262 	/* Do nothing if the control interface is not turned on */
5263 	if (wpa_s == NULL || wpa_s->global == NULL)
5264 		return;
5265 
5266 	if (wpa_s->p2p_mgmt)
5267 		wpa_s = wpa_s->parent;
5268 
5269 	ctrl_iface = wpa_s->global->dbus;
5270 	if (ctrl_iface == NULL)
5271 		return;
5272 
5273 	if (!wpa_s->dbus_groupobj_path) {
5274 		wpa_printf(MSG_DEBUG,
5275 			   "%s: Group object has already unregistered",
5276 			   __func__);
5277 		return;
5278 	}
5279 
5280 	peer_groups_changed(wpa_s);
5281 
5282 	wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
5283 		   wpa_s->dbus_groupobj_path);
5284 
5285 	wpa_dbus_unregister_object_per_iface(ctrl_iface,
5286 					     wpa_s->dbus_groupobj_path);
5287 
5288 	os_free(wpa_s->dbus_groupobj_path);
5289 	wpa_s->dbus_groupobj_path = NULL;
5290 }
5291 
5292 static const struct wpa_dbus_property_desc
5293 	wpas_dbus_persistent_group_properties[] = {
5294 	{ "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
5295 	  wpas_dbus_getter_persistent_group_properties,
5296 	  wpas_dbus_setter_persistent_group_properties,
5297 	  NULL
5298 	},
5299 	{ NULL, NULL, NULL, NULL, NULL, NULL }
5300 };
5301 
5302 /* No signals intended for persistent group objects */
5303 
5304 /**
5305  * wpas_dbus_register_persistent_group - Register a configured(saved)
5306  *	persistent group with dbus
5307  * @wpa_s: wpa_supplicant interface structure
5308  * @ssid: persistent group (still represented as a network within wpa)
5309  *	  configuration data
5310  * Returns: 0 on success, -1 on failure
5311  *
5312  * Registers a persistent group representing object with dbus.
5313  */
wpas_dbus_register_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)5314 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
5315 					struct wpa_ssid *ssid)
5316 {
5317 	struct wpas_dbus_priv *ctrl_iface;
5318 	struct wpa_dbus_object_desc *obj_desc;
5319 	struct network_handler_args *arg;
5320 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5321 
5322 	/* Do nothing if the control interface is not turned on */
5323 	if (wpa_s == NULL || wpa_s->global == NULL)
5324 		return 0;
5325 	wpa_s = wpa_s->parent->parent;
5326 	if (!wpa_s->dbus_new_path)
5327 		return 0;
5328 
5329 	/* Make sure ssid is a persistent group */
5330 	if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
5331 		return -1; /* should we return w/o complaining? */
5332 
5333 	if (wpa_s->p2p_mgmt)
5334 		wpa_s = wpa_s->parent;
5335 
5336 	ctrl_iface = wpa_s->global->dbus;
5337 	if (ctrl_iface == NULL)
5338 		return 0;
5339 
5340 	/*
5341 	 * Intentionally not coming up with different numbering scheme
5342 	 * for persistent groups.
5343 	 */
5344 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5345 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
5346 		    wpa_s->dbus_new_path, ssid->id);
5347 
5348 	wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
5349 		   pgrp_obj_path);
5350 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
5351 	if (!obj_desc) {
5352 		wpa_printf(MSG_ERROR,
5353 			   "dbus: Not enough memory to create object description");
5354 		goto err;
5355 	}
5356 
5357 	/*
5358 	 * Reusing the same context structure as that for networks
5359 	 * since these are represented using same data structure.
5360 	 */
5361 	/* allocate memory for handlers arguments */
5362 	arg = os_zalloc(sizeof(struct network_handler_args));
5363 	if (!arg) {
5364 		wpa_printf(MSG_ERROR,
5365 			   "dbus: Not enough memory to create arguments for method");
5366 		goto err;
5367 	}
5368 
5369 	arg->wpa_s = wpa_s;
5370 	arg->ssid = ssid;
5371 
5372 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
5373 			   wpas_dbus_persistent_group_properties,
5374 			   NULL);
5375 
5376 	if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
5377 					       wpa_s->ifname, obj_desc))
5378 		goto err;
5379 
5380 	wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
5381 
5382 	return 0;
5383 
5384 err:
5385 	free_dbus_object_desc(obj_desc);
5386 	return -1;
5387 }
5388 
5389 
5390 /**
5391  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
5392  *	from dbus
5393  * @wpa_s: wpa_supplicant interface structure
5394  * @nid: network id
5395  * Returns: 0 on success, -1 on failure
5396  *
5397  * Unregisters persistent group representing object from dbus
5398  *
5399  * NOTE: There is a slight issue with the semantics here. While the
5400  * implementation simply means the persistent group is unloaded from memory,
5401  * it should not get interpreted as the group is actually being erased/removed
5402  * from persistent storage as well.
5403  */
wpas_dbus_unregister_persistent_group(struct wpa_supplicant * wpa_s,int nid)5404 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
5405 					  int nid)
5406 {
5407 	struct wpas_dbus_priv *ctrl_iface;
5408 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
5409 	int ret;
5410 
5411 	/* Do nothing if the control interface is not turned on */
5412 	if (wpa_s == NULL || wpa_s->global == NULL)
5413 		return 0;
5414 
5415 	wpa_s = wpa_s->parent->parent;
5416 
5417 	ctrl_iface = wpa_s->global->dbus;
5418 	if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
5419 		return 0;
5420 
5421 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
5422 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
5423 		    wpa_s->dbus_new_path, nid);
5424 
5425 	wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
5426 		   pgrp_obj_path);
5427 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
5428 
5429 	if (!ret)
5430 		wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
5431 
5432 	return ret;
5433 }
5434 
5435 #endif /* CONFIG_P2P */
5436 
5437 
5438 #ifdef CONFIG_HS20
5439 /**
5440  * wpas_dbus_signal_hs20_t_c_acceptance - Signals a terms and conditions was
5441  * received.
5442  *
5443  * @wpa_s: %wpa_supplicant network interface data
5444  * @url: URL of the terms and conditions acceptance page.
5445  */
wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant * wpa_s,const char * url)5446 void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
5447 					  const char *url)
5448 {
5449 	struct wpas_dbus_priv *iface;
5450 	DBusMessage *msg;
5451 
5452 	iface = wpa_s->global->dbus;
5453 
5454 	/* Do nothing if the control interface is not turned on */
5455 	if (!iface || !wpa_s->dbus_new_path)
5456 		return;
5457 
5458 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5459 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
5460 				      "HS20TermsAndConditions");
5461 	if (!msg)
5462 		return;
5463 
5464 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &url,
5465 				     DBUS_TYPE_INVALID))
5466 		dbus_connection_send(iface->con, msg, NULL);
5467 	else
5468 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5469 	dbus_message_unref(msg);
5470 }
5471 #endif /* CONFIG_HS20 */
5472 
5473 
5474 #ifdef CONFIG_NAN_USD
5475 
5476 /**
5477  * wpas_dbus_signal_nan_discovery_result - Send NANDiscoveryResult signal
5478  * @wpa_s: %wpa_supplicant network interface data
5479  * @srv_proto_type: Service Protocol Type
5480  * @subscribe_id: Subscribe ID of the session
5481  * @peer_publish_id: Publish ID of the sender
5482  * @peer_addr: MAC address of the peer device
5483  * @ssi: Service specific information payload
5484  * @ssi_len: Length of the SSI field
5485  *
5486  * This is used to indicate the NAN DE DiscoveryResult event.
5487  */
wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant * wpa_s,enum nan_service_protocol_type srv_proto_type,int subscribe_id,int peer_publish_id,const u8 * peer_addr,bool fsd,bool fsd_gas,const u8 * ssi,size_t ssi_len)5488 void wpas_dbus_signal_nan_discovery_result(struct wpa_supplicant *wpa_s,
5489 					   enum nan_service_protocol_type
5490 					   srv_proto_type,
5491 					   int subscribe_id,
5492 					   int peer_publish_id,
5493 					   const u8 *peer_addr,
5494 					   bool fsd, bool fsd_gas,
5495 					   const u8 *ssi, size_t ssi_len)
5496 {
5497 	struct wpas_dbus_priv *iface;
5498 	DBusMessage *msg;
5499 	DBusMessageIter iter, dict_iter;
5500 	char addr_str[20];
5501 
5502 	iface = wpa_s->global->dbus;
5503 	/* Do nothing if the interface is not turned on */
5504 	if (!iface || !wpa_s->dbus_new_path)
5505 		return;
5506 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5507 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
5508 				      "NANDiscoveryResult");
5509 	if (!msg)
5510 		return;
5511 
5512 	snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
5513 
5514 	dbus_message_iter_init_append(msg, &iter);
5515 
5516 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
5517 	    !wpa_dbus_dict_append_uint32(&dict_iter, "subscribe_id",
5518 					 subscribe_id) ||
5519 	    !wpa_dbus_dict_append_uint32(&dict_iter, "publish_id",
5520 					 peer_publish_id) ||
5521 	    !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
5522 	    !wpa_dbus_dict_append_bool(&dict_iter, "fsd", fsd) ||
5523 	    !wpa_dbus_dict_append_bool(&dict_iter, "fsd_gas", fsd_gas) ||
5524 	    !wpa_dbus_dict_append_uint32(&dict_iter, "srv_proto_type",
5525 					 srv_proto_type) ||
5526 	    (ssi &&
5527 	     !wpa_dbus_dict_append_byte_array(&dict_iter,
5528 					      "ssi",
5529 					      (const char *) ssi,
5530 					      ssi_len)) ||
5531 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
5532 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5533 	else
5534 		dbus_connection_send(iface->con, msg, NULL);
5535 	dbus_message_unref(msg);
5536 }
5537 
5538 
5539 /**
5540  * wpas_dbus_signal_nan_replied - Send NANReplied signal
5541  * @wpa_s: %wpa_supplicant network interface data
5542  * @srv_proto_type: Service Protocol Type
5543  * @publish_id: Publish id of the session
5544  * @peer_subscribe_id: Subscribe id of the sender
5545  * @peer_addr: MAC address of the peer device
5546  * @ssi: Service specific information payload
5547  * @ssi_len: Length of the SSI field
5548  *
5549  * This is used to indicate the NAN DE Replied event.
5550  */
wpas_dbus_signal_nan_replied(struct wpa_supplicant * wpa_s,enum nan_service_protocol_type srv_proto_type,int publish_id,int peer_subscribe_id,const u8 * peer_addr,const u8 * ssi,size_t ssi_len)5551 void wpas_dbus_signal_nan_replied(struct wpa_supplicant *wpa_s,
5552 				  enum nan_service_protocol_type srv_proto_type,
5553 				  int publish_id,
5554 				  int peer_subscribe_id,
5555 				  const u8 *peer_addr,
5556 				  const u8 *ssi, size_t ssi_len)
5557 {
5558 	struct wpas_dbus_priv *iface;
5559 	DBusMessage *msg;
5560 	DBusMessageIter iter, dict_iter;
5561 	char addr_str[20];
5562 
5563 	iface = wpa_s->global->dbus;
5564 	/* Do nothing if the interface is not turned on */
5565 	if (!iface || !wpa_s->dbus_new_path)
5566 		return;
5567 
5568 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5569 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
5570 				      "NANReplied");
5571 	if (!msg)
5572 		return;
5573 
5574 	snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
5575 
5576 	dbus_message_iter_init_append(msg, &iter);
5577 
5578 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
5579 	    !wpa_dbus_dict_append_uint32(&dict_iter, "publish_id",
5580 					 publish_id) ||
5581 	    !wpa_dbus_dict_append_uint32(&dict_iter, "subscribe_id",
5582 					 peer_subscribe_id) ||
5583 	    !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
5584 	    !wpa_dbus_dict_append_uint32(&dict_iter, "srv_proto_type",
5585 					 srv_proto_type) ||
5586 	    (ssi &&
5587 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "ssi",
5588 					      (const char *) ssi,
5589 					      ssi_len)) ||
5590 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
5591 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5592 	else
5593 		dbus_connection_send(iface->con, msg, NULL);
5594 	dbus_message_unref(msg);
5595 }
5596 
5597 
5598 /**
5599  * wpas_dbus_signal_nan_receive - Send NANReceive signal
5600  * @wpa_s: %wpa_supplicant network interface data
5601  * @id: The original publish_id or subscribe_id
5602  * @peer_id: Peer instance identifier
5603  * @peer_addr: Address of the sender
5604  * @ssi: Service specific information payload
5605  * @ssi_len: Length of the SSI
5606  *
5607  * This is used to indicate the NAN DE Receive event to notify reception of a
5608  * follow-up frame.
5609  */
wpas_dbus_signal_nan_receive(struct wpa_supplicant * wpa_s,int id,int peer_id,const u8 * peer_addr,const u8 * ssi,size_t ssi_len)5610 void wpas_dbus_signal_nan_receive(struct wpa_supplicant *wpa_s,
5611 				  int id, int peer_id, const u8 *peer_addr,
5612 				  const u8 *ssi, size_t ssi_len)
5613 {
5614 	struct wpas_dbus_priv *iface;
5615 	DBusMessage *msg;
5616 	DBusMessageIter iter, dict_iter;
5617 	char addr_str[20];
5618 
5619 	iface = wpa_s->global->dbus;
5620 	/* Do nothing if the interface is not turned on */
5621 	if (!iface || !wpa_s->dbus_new_path)
5622 		return;
5623 
5624 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5625 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
5626 				      "NANReceive");
5627 	if (!msg)
5628 		return;
5629 
5630 	snprintf(addr_str, sizeof(addr_str), MACSTR, MAC2STR(peer_addr));
5631 
5632 	dbus_message_iter_init_append(msg, &iter);
5633 
5634 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
5635 	    !wpa_dbus_dict_append_uint32(&dict_iter, "id", id) ||
5636 	    !wpa_dbus_dict_append_uint32(&dict_iter, "peer_id", peer_id) ||
5637 	    !wpa_dbus_dict_append_string(&dict_iter, "peer_addr", addr_str) ||
5638 	    (ssi &&
5639 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "ssi",
5640 					      (const char *) ssi,
5641 					      ssi_len)) ||
5642 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
5643 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5644 	else
5645 		dbus_connection_send(iface->con, msg, NULL);
5646 	dbus_message_unref(msg);
5647 }
5648 
5649 
5650 /**
5651  * wpas_dbus_signal_nan_publish_terminated - Send NANPublishTerminated signal
5652  * @wpa_s: %wpa_supplicant network interface data
5653  * @publish_id: The publish_id of the session
5654  * @reason: The reason of the termination
5655  *
5656  * This is used to indicate the NAN DE PublishTerminated event to notify when
5657  * the session has expired.
5658  */
wpas_dbus_signal_nan_publish_terminated(struct wpa_supplicant * wpa_s,int publish_id,const char * reason)5659 void wpas_dbus_signal_nan_publish_terminated(struct wpa_supplicant *wpa_s,
5660 					     int publish_id,
5661 					     const char *reason)
5662 {
5663 	struct wpas_dbus_priv *iface;
5664 	DBusMessage *msg;
5665 	dbus_uint32_t pub_id = publish_id;
5666 
5667 	iface = wpa_s->global->dbus;
5668 	/* Do nothing if the interface is not turned on */
5669 	if (!iface || !wpa_s->dbus_new_path)
5670 		return;
5671 
5672 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5673 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
5674 				      "NANPublishTerminated");
5675 	if (!msg)
5676 		return;
5677 
5678 	if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &pub_id,
5679 				      DBUS_TYPE_INVALID) ||
5680 	    !dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
5681 				      DBUS_TYPE_INVALID))
5682 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5683 	else
5684 		dbus_connection_send(iface->con, msg, NULL);
5685 	dbus_message_unref(msg);
5686 }
5687 
5688 
5689 /**
5690  * wpas_dbus_signal_nan_subscribe_terminated - Send NANSubscribeTerminated signal
5691  * @wpa_s: %wpa_supplicant network interface data
5692  * @subscribe_id: The subscribe_id of the session
5693  * @reason: The reason of the termination
5694  *
5695  * This is used to indicate the NAN DE SubscribeTerminated event to notify when
5696  * the session has expired.
5697  */
wpas_dbus_signal_nan_subscribe_terminated(struct wpa_supplicant * wpa_s,int subscribe_id,const char * reason)5698 void wpas_dbus_signal_nan_subscribe_terminated(struct wpa_supplicant *wpa_s,
5699 					       int subscribe_id,
5700 					       const char *reason)
5701 {
5702 	struct wpas_dbus_priv *iface;
5703 	DBusMessage *msg;
5704 	dbus_uint32_t sub_id = subscribe_id;
5705 
5706 	iface = wpa_s->global->dbus;
5707 	/* Do nothing if the interface is not turned on */
5708 	if (!iface || !wpa_s->dbus_new_path)
5709 		return;
5710 
5711 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
5712 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
5713 				      "NANSubscribeTerminated");
5714 	if (!msg)
5715 		return;
5716 
5717 	if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &sub_id,
5718 				      DBUS_TYPE_INVALID) ||
5719 	    !dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
5720 				      DBUS_TYPE_INVALID))
5721 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
5722 	else
5723 		dbus_connection_send(iface->con, msg, NULL);
5724 	dbus_message_unref(msg);
5725 }
5726 
5727 #endif /* CONFIG_NAN_USD */
5728