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