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 	if (cred->auth_type & WPS_AUTH_WPAPSK)
754 		auth_type[at_num++] = "wpa-psk";
755 	if (cred->auth_type & WPS_AUTH_WPA)
756 		auth_type[at_num++] = "wpa-eap";
757 	if (cred->auth_type & WPS_AUTH_WPA2)
758 		auth_type[at_num++] = "wpa2-eap";
759 	if (cred->auth_type & WPS_AUTH_WPA2PSK)
760 		auth_type[at_num++] = "wpa2-psk";
761 
762 	if (cred->encr_type & WPS_ENCR_NONE)
763 		encr_type[et_num++] = "none";
764 	if (cred->encr_type & WPS_ENCR_TKIP)
765 		encr_type[et_num++] = "tkip";
766 	if (cred->encr_type & WPS_ENCR_AES)
767 		encr_type[et_num++] = "aes";
768 
769 	if ((wpa_s->current_ssid &&
770 	     !wpa_dbus_dict_append_byte_array(
771 		     &dict_iter, "BSSID",
772 		     (const char *) wpa_s->current_ssid->bssid, ETH_ALEN)) ||
773 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
774 					     (const char *) cred->ssid,
775 					     cred->ssid_len) ||
776 	    !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
777 					       (const char **) auth_type,
778 					       at_num) ||
779 	    !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
780 					       (const char **) encr_type,
781 					       et_num) ||
782 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
783 					     (const char *) cred->key,
784 					     cred->key_len) ||
785 	    !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
786 					 cred->key_idx) ||
787 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
788 		goto nomem;
789 
790 	dbus_connection_send(iface->con, msg, NULL);
791 
792 nomem:
793 	dbus_message_unref(msg);
794 }
795 
796 #endif /* CONFIG_WPS */
797 
798 
799 #ifdef CONFIG_MESH
800 
wpas_dbus_signal_mesh_group_started(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)801 void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s,
802 					 struct wpa_ssid *ssid)
803 {
804 	struct wpas_dbus_priv *iface;
805 	DBusMessage *msg;
806 	DBusMessageIter iter, dict_iter;
807 
808 	iface = wpa_s->global->dbus;
809 
810 	/* Do nothing if the control interface is not turned on */
811 	if (!iface || !wpa_s->dbus_new_path)
812 		return;
813 
814 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
815 				      WPAS_DBUS_NEW_IFACE_MESH,
816 				      "MeshGroupStarted");
817 	if (!msg)
818 		return;
819 
820 	dbus_message_iter_init_append(msg, &iter);
821 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
822 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
823 					     (const char *) ssid->ssid,
824 					     ssid->ssid_len) ||
825 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
826 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
827 	else
828 		dbus_connection_send(iface->con, msg, NULL);
829 	dbus_message_unref(msg);
830 }
831 
832 
wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant * wpa_s,const u8 * meshid,u8 meshid_len,int reason)833 void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s,
834 					 const u8 *meshid, u8 meshid_len,
835 					 int reason)
836 {
837 	struct wpas_dbus_priv *iface;
838 	DBusMessage *msg;
839 	DBusMessageIter iter, dict_iter;
840 
841 	iface = wpa_s->global->dbus;
842 
843 	/* Do nothing if the control interface is not turned on */
844 	if (!iface || !wpa_s->dbus_new_path)
845 		return;
846 
847 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
848 				      WPAS_DBUS_NEW_IFACE_MESH,
849 				      "MeshGroupRemoved");
850 	if (!msg)
851 		return;
852 
853 	dbus_message_iter_init_append(msg, &iter);
854 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
855 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
856 					     (const char *) meshid,
857 					     meshid_len) ||
858 	    !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
859 					reason) ||
860 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
861 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
862 	else
863 		dbus_connection_send(iface->con, msg, NULL);
864 	dbus_message_unref(msg);
865 }
866 
867 
wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant * wpa_s,const u8 * peer_addr)868 void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s,
869 					  const u8 *peer_addr)
870 {
871 	struct wpas_dbus_priv *iface;
872 	DBusMessage *msg;
873 	DBusMessageIter iter, dict_iter;
874 
875 	iface = wpa_s->global->dbus;
876 
877 	/* Do nothing if the control interface is not turned on */
878 	if (!iface || !wpa_s->dbus_new_path)
879 		return;
880 
881 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
882 				      WPAS_DBUS_NEW_IFACE_MESH,
883 				      "MeshPeerConnected");
884 	if (!msg)
885 		return;
886 
887 	dbus_message_iter_init_append(msg, &iter);
888 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
889 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
890 					     (const char *) peer_addr,
891 					     ETH_ALEN) ||
892 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
893 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
894 	else
895 		dbus_connection_send(iface->con, msg, NULL);
896 	dbus_message_unref(msg);
897 }
898 
899 
wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * peer_addr,int reason)900 void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s,
901 					     const u8 *peer_addr, int reason)
902 {
903 	struct wpas_dbus_priv *iface;
904 	DBusMessage *msg;
905 	DBusMessageIter iter, dict_iter;
906 
907 	iface = wpa_s->global->dbus;
908 
909 	/* Do nothing if the control interface is not turned on */
910 	if (!iface || !wpa_s->dbus_new_path)
911 		return;
912 
913 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
914 				      WPAS_DBUS_NEW_IFACE_MESH,
915 				      "MeshPeerDisconnected");
916 	if (!msg)
917 		return;
918 
919 	dbus_message_iter_init_append(msg, &iter);
920 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
921 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress",
922 					     (const char *) peer_addr,
923 					     ETH_ALEN) ||
924 	    !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason",
925 					reason) ||
926 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
927 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
928 	else
929 		dbus_connection_send(iface->con, msg, NULL);
930 	dbus_message_unref(msg);
931 }
932 
933 #endif /* CONFIG_MESH */
934 
935 
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)936 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s,
937 				    int depth, const char *subject,
938 				    const char *altsubject[],
939 				    int num_altsubject,
940 				    const char *cert_hash,
941 				    const struct wpabuf *cert)
942 {
943 	struct wpas_dbus_priv *iface;
944 	DBusMessage *msg;
945 	DBusMessageIter iter, dict_iter;
946 
947 	iface = wpa_s->global->dbus;
948 
949 	/* Do nothing if the control interface is not turned on */
950 	if (iface == NULL || !wpa_s->dbus_new_path)
951 		return;
952 
953 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
954 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
955 				      "Certification");
956 	if (msg == NULL)
957 		return;
958 
959 	dbus_message_iter_init_append(msg, &iter);
960 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
961 	    !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) ||
962 	    !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) ||
963 	    (altsubject && num_altsubject &&
964 	     !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject",
965 						altsubject, num_altsubject)) ||
966 	    (cert_hash &&
967 	     !wpa_dbus_dict_append_string(&dict_iter, "cert_hash",
968 					  cert_hash)) ||
969 	    (cert &&
970 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "cert",
971 					      wpabuf_head(cert),
972 					      wpabuf_len(cert))) ||
973 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
974 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
975 	else
976 		dbus_connection_send(iface->con, msg, NULL);
977 	dbus_message_unref(msg);
978 }
979 
980 
wpas_dbus_signal_eap_status(struct wpa_supplicant * wpa_s,const char * status,const char * parameter)981 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s,
982 				 const char *status, const char *parameter)
983 {
984 	struct wpas_dbus_priv *iface;
985 	DBusMessage *msg;
986 	DBusMessageIter iter;
987 
988 	iface = wpa_s->global->dbus;
989 
990 	/* Do nothing if the control interface is not turned on */
991 	if (iface == NULL || !wpa_s->dbus_new_path)
992 		return;
993 
994 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
995 				      WPAS_DBUS_NEW_IFACE_INTERFACE,
996 				      "EAP");
997 	if (msg == NULL)
998 		return;
999 
1000 	dbus_message_iter_init_append(msg, &iter);
1001 
1002 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) ||
1003 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
1004 					    &parameter))
1005 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1006 	else
1007 		dbus_connection_send(iface->con, msg, NULL);
1008 	dbus_message_unref(msg);
1009 }
1010 
1011 
1012 /**
1013  * wpas_dbus_signal_sta - Send a station related event signal
1014  * @wpa_s: %wpa_supplicant network interface data
1015  * @sta: station mac address
1016  * @sig_name: signal name - StaAuthorized or StaDeauthorized
1017  *
1018  * Notify listeners about event related with station
1019  */
wpas_dbus_signal_sta(struct wpa_supplicant * wpa_s,const u8 * sta,const char * sig_name)1020 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s,
1021 				 const u8 *sta, const char *sig_name)
1022 {
1023 	struct wpas_dbus_priv *iface;
1024 	DBusMessage *msg;
1025 	char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX];
1026 	char *dev_mac;
1027 
1028 	os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta));
1029 	dev_mac = sta_mac;
1030 
1031 	iface = wpa_s->global->dbus;
1032 
1033 	/* Do nothing if the control interface is not turned on */
1034 	if (iface == NULL || !wpa_s->dbus_new_path)
1035 		return;
1036 
1037 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1038 				      WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1039 	if (msg == NULL)
1040 		return;
1041 
1042 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac,
1043 				     DBUS_TYPE_INVALID))
1044 		dbus_connection_send(iface->con, msg, NULL);
1045 	else
1046 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1047 	dbus_message_unref(msg);
1048 
1049 	wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'",
1050 		   sta_mac, sig_name);
1051 }
1052 
1053 
1054 /**
1055  * wpas_dbus_signal_sta_authorized - Send a STA authorized signal
1056  * @wpa_s: %wpa_supplicant network interface data
1057  * @sta: station mac address
1058  *
1059  * Notify listeners a new station has been authorized
1060  */
wpas_dbus_signal_sta_authorized(struct wpa_supplicant * wpa_s,const u8 * sta)1061 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s,
1062 				     const u8 *sta)
1063 {
1064 	wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized");
1065 }
1066 
1067 
1068 /**
1069  * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal
1070  * @wpa_s: %wpa_supplicant network interface data
1071  * @sta: station mac address
1072  *
1073  * Notify listeners a station has been deauthorized
1074  */
wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant * wpa_s,const u8 * sta)1075 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
1076 				       const u8 *sta)
1077 {
1078 	wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized");
1079 }
1080 
1081 
1082 /**
1083  * wpas_dbus_signal_station - Send an event signal related to a station object
1084  * @wpa_s: %wpa_supplicant network interface data
1085  * @station_obj_path: Station object path
1086  * @sig_name: signal name - StationAdded or StationRemoved
1087  * @properties: Whether to add second argument with object properties
1088  *
1089  * Notify listeners about event related with station.
1090  */
wpas_dbus_signal_station(struct wpa_supplicant * wpa_s,const char * station_obj_path,const char * sig_name,dbus_bool_t properties)1091 static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s,
1092 				     const char *station_obj_path,
1093 				     const char *sig_name,
1094 				     dbus_bool_t properties)
1095 {
1096 	struct wpas_dbus_priv *iface;
1097 	DBusMessage *msg;
1098 	DBusMessageIter iter;
1099 
1100 	iface = wpa_s->global->dbus;
1101 
1102 	/* Do nothing if the control interface is not turned on */
1103 	if (!iface || !wpa_s->dbus_new_path)
1104 		return;
1105 
1106 	wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name);
1107 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1108 				      WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
1109 	if (!msg)
1110 		return;
1111 
1112 	dbus_message_iter_init_append(msg, &iter);
1113 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1114 					    &station_obj_path) ||
1115 	    (properties &&
1116 	     !wpa_dbus_get_object_properties(iface, station_obj_path,
1117 					     WPAS_DBUS_NEW_IFACE_STA,
1118 					     &iter)))
1119 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1120 	else
1121 		dbus_connection_send(iface->con, msg, NULL);
1122 	dbus_message_unref(msg);
1123 }
1124 
1125 
1126 /**
1127  * wpas_dbus_signal_station_added - Send a Station added signal
1128  * @wpa_s: %wpa_supplicant network interface data
1129  * @station_obj_path: new Station object path
1130  *
1131  * Notify listeners about adding new Station
1132  */
wpas_dbus_signal_station_added(struct wpa_supplicant * wpa_s,const char * station_obj_path)1133 static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s,
1134 					   const char *station_obj_path)
1135 {
1136 	wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE);
1137 }
1138 
1139 
1140 /**
1141  * wpas_dbus_signal_station_removed - Send a Station removed signal
1142  * @wpa_s: %wpa_supplicant network interface data
1143  * @station_obj_path: Station object path
1144  *
1145  * Notify listeners about removing Station
1146  */
wpas_dbus_signal_station_removed(struct wpa_supplicant * wpa_s,const char * station_obj_path)1147 static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s,
1148 					     const char *station_obj_path)
1149 {
1150 	wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved",
1151 				 FALSE);
1152 }
1153 
1154 
1155 #ifdef CONFIG_P2P
1156 
1157 /**
1158  * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
1159  * @wpa_s: %wpa_supplicant network interface data
1160  * @role: role of this device (client or GO)
1161  * Sends signal with i/f name and role as string arguments
1162  */
wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant * wpa_s,const char * role)1163 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
1164 					const char *role)
1165 {
1166 	DBusMessage *msg;
1167 	DBusMessageIter iter, dict_iter;
1168 	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
1169 	struct wpa_supplicant *parent;
1170 
1171 	/* Do nothing if the control interface is not turned on */
1172 	if (iface == NULL)
1173 		return;
1174 
1175 	parent = wpa_s->parent;
1176 	if (parent->p2p_mgmt)
1177 		parent = parent->parent;
1178 
1179 	if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path ||
1180 	    !parent->dbus_new_path)
1181 		return;
1182 
1183 	msg = dbus_message_new_signal(parent->dbus_new_path,
1184 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1185 				      "GroupFinished");
1186 	if (msg == NULL)
1187 		return;
1188 
1189 	dbus_message_iter_init_append(msg, &iter);
1190 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1191 	    !wpa_dbus_dict_append_object_path(&dict_iter,
1192 					      "interface_object",
1193 					      wpa_s->dbus_new_path) ||
1194 	    !wpa_dbus_dict_append_string(&dict_iter, "role", role) ||
1195 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1196 					      wpa_s->dbus_groupobj_path) ||
1197 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1198 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1199 	else
1200 		dbus_connection_send(iface->con, msg, NULL);
1201 	dbus_message_unref(msg);
1202 }
1203 
1204 
1205 /**
1206  * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
1207  *
1208  * @dev_addr - who sent the request or responded to our request.
1209  * @request - Will be 1 if request, 0 for response.
1210  * @status - valid only in case of response
1211  * @config_methods - wps config methods
1212  * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
1213  *
1214  * Sends following provision discovery related events:
1215  *	ProvisionDiscoveryRequestDisplayPin
1216  *	ProvisionDiscoveryResponseDisplayPin
1217  *	ProvisionDiscoveryRequestEnterPin
1218  *	ProvisionDiscoveryResponseEnterPin
1219  *	ProvisionDiscoveryPBCRequest
1220  *	ProvisionDiscoveryPBCResponse
1221  *
1222  *	TODO::
1223  *	ProvisionDiscoveryFailure (timeout case)
1224  */
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)1225 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
1226 					      const u8 *dev_addr, int request,
1227 					      enum p2p_prov_disc_status status,
1228 					      u16 config_methods,
1229 					      unsigned int generated_pin)
1230 {
1231 	DBusMessage *msg;
1232 	DBusMessageIter iter;
1233 	struct wpas_dbus_priv *iface;
1234 	char *_signal;
1235 	int add_pin = 0;
1236 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1237 	int error_ret = 1;
1238 	char pin[9], *p_pin = NULL;
1239 
1240 	iface = wpa_s->global->dbus;
1241 
1242 	/* Do nothing if the control interface is not turned on */
1243 	if (iface == NULL)
1244 		return;
1245 
1246 	if (wpa_s->p2p_mgmt)
1247 		wpa_s = wpa_s->parent;
1248 	if (!wpa_s->dbus_new_path)
1249 		return;
1250 
1251 	if (request || !status) {
1252 		if (config_methods & WPS_CONFIG_DISPLAY)
1253 			_signal = request ?
1254 				 "ProvisionDiscoveryRequestDisplayPin" :
1255 				 "ProvisionDiscoveryResponseEnterPin";
1256 		else if (config_methods & WPS_CONFIG_KEYPAD)
1257 			_signal = request ?
1258 				 "ProvisionDiscoveryRequestEnterPin" :
1259 				 "ProvisionDiscoveryResponseDisplayPin";
1260 		else if (config_methods & WPS_CONFIG_PUSHBUTTON)
1261 			_signal = request ? "ProvisionDiscoveryPBCRequest" :
1262 				   "ProvisionDiscoveryPBCResponse";
1263 		else
1264 			return; /* Unknown or un-supported method */
1265 	} else {
1266 		/* Explicit check for failure response */
1267 		_signal = "ProvisionDiscoveryFailure";
1268 	}
1269 
1270 	add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
1271 		   (!request && !status &&
1272 			(config_methods & WPS_CONFIG_KEYPAD)));
1273 
1274 	if (add_pin) {
1275 		os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
1276 		p_pin = pin;
1277 	}
1278 
1279 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1280 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
1281 	if (msg == NULL)
1282 		return;
1283 
1284 	/* Check if this is a known peer */
1285 	if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
1286 		goto error;
1287 
1288 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1289 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1290 			COMPACT_MACSTR,
1291 			wpa_s->dbus_new_path, MAC2STR(dev_addr));
1292 
1293 	path = peer_obj_path;
1294 
1295 	dbus_message_iter_init_append(msg, &iter);
1296 
1297 	if (!dbus_message_iter_append_basic(&iter,
1298 					    DBUS_TYPE_OBJECT_PATH,
1299 					    &path))
1300 			goto error;
1301 
1302 	if (!request && status)
1303 		/* Attach status to ProvisionDiscoveryFailure */
1304 		error_ret = !dbus_message_iter_append_basic(&iter,
1305 						    DBUS_TYPE_INT32,
1306 						    &status);
1307 	else
1308 		error_ret = (add_pin &&
1309 				 !dbus_message_iter_append_basic(&iter,
1310 							DBUS_TYPE_STRING,
1311 							&p_pin));
1312 
1313 error:
1314 	if (!error_ret)
1315 		dbus_connection_send(iface->con, msg, NULL);
1316 	else
1317 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1318 
1319 	dbus_message_unref(msg);
1320 }
1321 
1322 
1323 /**
1324  * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX
1325  * @wpa_s: %wpa_supplicant network interface data
1326  * @src: Source address of the message triggering this notification
1327  * @dev_passwd_id: WPS Device Password Id
1328  * @go_intent: Peer's GO Intent value
1329  *
1330  * Sends signal to notify that a peer P2P Device is requesting group owner
1331  * negotiation with us.
1332  */
wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant * wpa_s,const u8 * src,u16 dev_passwd_id,u8 go_intent)1333 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
1334 				     const u8 *src, u16 dev_passwd_id,
1335 				     u8 go_intent)
1336 {
1337 	DBusMessage *msg;
1338 	DBusMessageIter iter;
1339 	struct wpas_dbus_priv *iface;
1340 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1341 
1342 	iface = wpa_s->global->dbus;
1343 
1344 	/* Do nothing if the control interface is not turned on */
1345 	if (iface == NULL)
1346 		return;
1347 
1348 	if (wpa_s->p2p_mgmt)
1349 		wpa_s = wpa_s->parent;
1350 	if (!wpa_s->dbus_new_path)
1351 		return;
1352 
1353 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1354 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1355 		    wpa_s->dbus_new_path, MAC2STR(src));
1356 	path = peer_obj_path;
1357 
1358 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1359 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1360 				      "GONegotiationRequest");
1361 	if (msg == NULL)
1362 		return;
1363 
1364 	dbus_message_iter_init_append(msg, &iter);
1365 
1366 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1367 					    &path) ||
1368 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
1369 					    &dev_passwd_id) ||
1370 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE,
1371 					    &go_intent))
1372 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1373 	else
1374 		dbus_connection_send(iface->con, msg, NULL);
1375 
1376 	dbus_message_unref(msg);
1377 }
1378 
1379 
wpas_dbus_get_group_obj_path(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid,char * group_obj_path)1380 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
1381 					const struct wpa_ssid *ssid,
1382 					char *group_obj_path)
1383 {
1384 	char group_name[3];
1385 
1386 	if (!wpa_s->dbus_new_path ||
1387 	    os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
1388 		return -1;
1389 
1390 	os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
1391 	group_name[2] = '\0';
1392 
1393 	os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1394 		    "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
1395 		    wpa_s->dbus_new_path, group_name);
1396 
1397 	return 0;
1398 }
1399 
1400 
1401 struct group_changed_data {
1402 	struct wpa_supplicant *wpa_s;
1403 	struct p2p_peer_info *info;
1404 };
1405 
1406 
match_group_where_peer_is_client(struct p2p_group * group,void * user_data)1407 static int match_group_where_peer_is_client(struct p2p_group *group,
1408 					    void *user_data)
1409 {
1410 	struct group_changed_data *data = user_data;
1411 	const struct p2p_group_config *cfg;
1412 	struct wpa_supplicant *wpa_s_go;
1413 
1414 	if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
1415 		return 1;
1416 
1417 	cfg = p2p_group_get_config(group);
1418 
1419 	wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
1420 					 cfg->ssid_len);
1421 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1422 		wpas_dbus_signal_peer_groups_changed(
1423 			data->wpa_s->p2pdev, data->info->p2p_device_addr);
1424 		return 0;
1425 	}
1426 
1427 	return 1;
1428 }
1429 
1430 
signal_peer_groups_changed(struct p2p_peer_info * info,void * user_data)1431 static void signal_peer_groups_changed(struct p2p_peer_info *info,
1432 				       void *user_data)
1433 {
1434 	struct group_changed_data *data = user_data;
1435 	struct wpa_supplicant *wpa_s_go;
1436 
1437 	wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
1438 					     info->p2p_device_addr);
1439 	if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
1440 		wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
1441 						     info->p2p_device_addr);
1442 		return;
1443 	}
1444 
1445 	data->info = info;
1446 	p2p_loop_on_all_groups(data->wpa_s->global->p2p,
1447 			       match_group_where_peer_is_client, data);
1448 	data->info = NULL;
1449 }
1450 
1451 
peer_groups_changed(struct wpa_supplicant * wpa_s)1452 static void peer_groups_changed(struct wpa_supplicant *wpa_s)
1453 {
1454 	struct group_changed_data data;
1455 
1456 	os_memset(&data, 0, sizeof(data));
1457 	data.wpa_s = wpa_s;
1458 
1459 	p2p_loop_on_known_peers(wpa_s->global->p2p,
1460 				signal_peer_groups_changed, &data);
1461 }
1462 
1463 
1464 /**
1465  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
1466  * started. Emitted when a group is successfully started
1467  * irrespective of the role (client/GO) of the current device
1468  *
1469  * @wpa_s: %wpa_supplicant network interface data
1470  * @client: this device is P2P client
1471  * @persistent: 0 - non persistent group, 1 - persistent group
1472  * @ip: When group role is client, it contains local IP address, netmask, and
1473  *	GO's IP address, if assigned; otherwise, NULL
1474  */
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant * wpa_s,int client,int persistent,const u8 * ip)1475 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
1476 					int client, int persistent,
1477 					const u8 *ip)
1478 {
1479 	DBusMessage *msg;
1480 	DBusMessageIter iter, dict_iter;
1481 	struct wpas_dbus_priv *iface;
1482 	struct wpa_supplicant *parent;
1483 
1484 	parent = wpa_s->parent;
1485 	if (parent->p2p_mgmt)
1486 		parent = parent->parent;
1487 
1488 	iface = parent->global->dbus;
1489 
1490 	/* Do nothing if the control interface is not turned on */
1491 	if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path)
1492 		return;
1493 
1494 	if (wpa_s->dbus_groupobj_path == NULL)
1495 		return;
1496 
1497 	/* New interface has been created for this group */
1498 	msg = dbus_message_new_signal(parent->dbus_new_path,
1499 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1500 				      "GroupStarted");
1501 	if (msg == NULL)
1502 		return;
1503 
1504 	dbus_message_iter_init_append(msg, &iter);
1505 	/*
1506 	 * In case the device supports creating a separate interface the
1507 	 * DBus client will need to know the object path for the interface
1508 	 * object this group was created on, so include it here.
1509 	 */
1510 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1511 	    !wpa_dbus_dict_append_object_path(&dict_iter,
1512 					      "interface_object",
1513 					      wpa_s->dbus_new_path) ||
1514 	    !wpa_dbus_dict_append_string(&dict_iter, "role",
1515 					 client ? "client" : "GO") ||
1516 	    !wpa_dbus_dict_append_bool(&dict_iter, "persistent", persistent) ||
1517 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1518 					      wpa_s->dbus_groupobj_path) ||
1519 	    (ip &&
1520 	     (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr",
1521 					       (char *) ip, 4) ||
1522 	      !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
1523 					       (char *) ip + 4, 4) ||
1524 	      !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
1525 					       (char *) ip + 8, 4))) ||
1526 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
1527 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1528 	} else {
1529 		dbus_connection_send(iface->con, msg, NULL);
1530 		if (client)
1531 			peer_groups_changed(wpa_s);
1532 	}
1533 	dbus_message_unref(msg);
1534 }
1535 
1536 
1537 /**
1538  * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal
1539  * @wpa_s: %wpa_supplicant network interface data
1540  * @res: Result of the GO Neg Request
1541  */
wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant * wpa_s,struct p2p_go_neg_results * res)1542 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
1543 				      struct p2p_go_neg_results *res)
1544 {
1545 	DBusMessage *msg;
1546 	DBusMessageIter iter, dict_iter;
1547 	DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
1548 	struct wpas_dbus_priv *iface;
1549 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1550 	dbus_int32_t freqs[P2P_MAX_CHANNELS];
1551 	dbus_int32_t *f_array = freqs;
1552 
1553 
1554 	iface = wpa_s->global->dbus;
1555 
1556 	if (wpa_s->p2p_mgmt)
1557 		wpa_s = wpa_s->parent;
1558 
1559 	os_memset(freqs, 0, sizeof(freqs));
1560 	/* Do nothing if the control interface is not turned on */
1561 	if (iface == NULL || !wpa_s->dbus_new_path)
1562 		return;
1563 
1564 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1565 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1566 		    wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
1567 	path = peer_obj_path;
1568 
1569 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1570 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1571 				      res->status ? "GONegotiationFailure" :
1572 						    "GONegotiationSuccess");
1573 	if (msg == NULL)
1574 		return;
1575 
1576 	dbus_message_iter_init_append(msg, &iter);
1577 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1578 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1579 					      path) ||
1580 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
1581 		goto err;
1582 
1583 	if (!res->status) {
1584 		int i = 0;
1585 		int freq_list_num = 0;
1586 
1587 		if ((res->role_go &&
1588 		     !wpa_dbus_dict_append_string(&dict_iter, "passphrase",
1589 						  res->passphrase)) ||
1590 		    !wpa_dbus_dict_append_string(&dict_iter, "role_go",
1591 						 res->role_go ? "GO" :
1592 						 "client") ||
1593 		    !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
1594 						res->freq) ||
1595 		    !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
1596 						     (const char *) res->ssid,
1597 						     res->ssid_len) ||
1598 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
1599 						     "peer_device_addr",
1600 						     (const char *)
1601 						     res->peer_device_addr,
1602 						     ETH_ALEN) ||
1603 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
1604 						     "peer_interface_addr",
1605 						     (const char *)
1606 						     res->peer_interface_addr,
1607 						     ETH_ALEN) ||
1608 		    !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
1609 						 p2p_wps_method_text(
1610 							 res->wps_method)))
1611 			goto err;
1612 
1613 		for (i = 0; i < P2P_MAX_CHANNELS; i++) {
1614 			if (res->freq_list[i]) {
1615 				freqs[i] = res->freq_list[i];
1616 				freq_list_num++;
1617 			}
1618 		}
1619 
1620 		if (!wpa_dbus_dict_begin_array(&dict_iter,
1621 					       "frequency_list",
1622 					       DBUS_TYPE_INT32_AS_STRING,
1623 					       &iter_dict_entry,
1624 					       &iter_dict_val,
1625 					       &iter_dict_array) ||
1626 		    !dbus_message_iter_append_fixed_array(&iter_dict_array,
1627 							  DBUS_TYPE_INT32,
1628 							  &f_array,
1629 							  freq_list_num) ||
1630 		    !wpa_dbus_dict_end_array(&dict_iter,
1631 					     &iter_dict_entry,
1632 					     &iter_dict_val,
1633 					     &iter_dict_array) ||
1634 		    !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
1635 						res->persistent_group) ||
1636 		    !wpa_dbus_dict_append_uint32(&dict_iter,
1637 						 "peer_config_timeout",
1638 						 res->peer_config_timeout))
1639 			goto err;
1640 	}
1641 
1642 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1643 		goto err;
1644 
1645 	dbus_connection_send(iface->con, msg, NULL);
1646 err:
1647 	dbus_message_unref(msg);
1648 }
1649 
1650 
1651 /**
1652  * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
1653  * @wpa_s: %wpa_supplicant network interface data
1654  * @status: Status of invitation process
1655  * @bssid: Basic Service Set Identifier
1656  */
wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant * wpa_s,int status,const u8 * bssid)1657 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1658 					    int status, const u8 *bssid)
1659 {
1660 	DBusMessage *msg;
1661 	DBusMessageIter iter, dict_iter;
1662 	struct wpas_dbus_priv *iface;
1663 
1664 	wpa_printf(MSG_DEBUG, "%s", __func__);
1665 
1666 	iface = wpa_s->global->dbus;
1667 	/* Do nothing if the control interface is not turned on */
1668 	if (iface == NULL)
1669 		return;
1670 
1671 	if (wpa_s->p2p_mgmt)
1672 		wpa_s = wpa_s->parent;
1673 	if (!wpa_s->dbus_new_path)
1674 		return;
1675 
1676 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1677 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1678 				      "InvitationResult");
1679 
1680 	if (msg == NULL)
1681 		return;
1682 
1683 	dbus_message_iter_init_append(msg, &iter);
1684 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1685 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", status) ||
1686 	    (bssid &&
1687 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1688 					      (const char *) bssid,
1689 					      ETH_ALEN)) ||
1690 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1691 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1692 	else
1693 		dbus_connection_send(iface->con, msg, NULL);
1694 	dbus_message_unref(msg);
1695 }
1696 
1697 
1698 /**
1699  *
1700  * Method to emit a signal for a peer joining the group.
1701  * The signal will carry path to the group member object
1702  * constructed using p2p i/f addr used for connecting.
1703  *
1704  * @wpa_s: %wpa_supplicant network interface data
1705  * @peer_addr: P2P Device Address of the peer joining the group
1706  */
wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1707 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1708 				      const u8 *peer_addr)
1709 {
1710 	struct wpas_dbus_priv *iface;
1711 	DBusMessage *msg;
1712 	DBusMessageIter iter;
1713 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1714 	struct wpa_supplicant *parent;
1715 
1716 	iface = wpa_s->global->dbus;
1717 
1718 	/* Do nothing if the control interface is not turned on */
1719 	if (iface == NULL)
1720 		return;
1721 
1722 	if (!wpa_s->dbus_groupobj_path)
1723 		return;
1724 
1725 	parent = wpa_s->parent;
1726 	if (parent->p2p_mgmt)
1727 		parent = parent->parent;
1728 	if (!parent->dbus_new_path)
1729 		return;
1730 
1731 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1732 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1733 			COMPACT_MACSTR,
1734 			parent->dbus_new_path, MAC2STR(peer_addr));
1735 
1736 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1737 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1738 				      "PeerJoined");
1739 	if (msg == NULL)
1740 		return;
1741 
1742 	dbus_message_iter_init_append(msg, &iter);
1743 	path = peer_obj_path;
1744 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1745 					    &path)) {
1746 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1747 	} else {
1748 		dbus_connection_send(iface->con, msg, NULL);
1749 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1750 	}
1751 	dbus_message_unref(msg);
1752 }
1753 
1754 
1755 /**
1756  *
1757  * Method to emit a signal for a peer disconnecting the group.
1758  * The signal will carry path to the group member object
1759  * constructed using the P2P Device Address of the peer.
1760  *
1761  * @wpa_s: %wpa_supplicant network interface data
1762  * @peer_addr: P2P Device Address of the peer joining the group
1763  */
wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1764 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1765 					    const u8 *peer_addr)
1766 {
1767 	struct wpas_dbus_priv *iface;
1768 	DBusMessage *msg;
1769 	DBusMessageIter iter;
1770 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1771 	struct wpa_supplicant *parent;
1772 
1773 	iface = wpa_s->global->dbus;
1774 
1775 	/* Do nothing if the control interface is not turned on */
1776 	if (iface == NULL)
1777 		return;
1778 
1779 	if (!wpa_s->dbus_groupobj_path)
1780 		return;
1781 
1782 	parent = wpa_s->parent;
1783 	if (parent->p2p_mgmt)
1784 		parent = parent->parent;
1785 	if (!parent->dbus_new_path)
1786 		return;
1787 
1788 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1789 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1790 			COMPACT_MACSTR,
1791 			parent->dbus_new_path, MAC2STR(peer_addr));
1792 
1793 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1794 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1795 				      "PeerDisconnected");
1796 	if (msg == NULL)
1797 		return;
1798 
1799 	dbus_message_iter_init_append(msg, &iter);
1800 	path = peer_obj_path;
1801 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1802 					    &path)) {
1803 		wpa_printf(MSG_ERROR,
1804 			   "dbus: Failed to construct PeerDisconnected signal");
1805 	} else {
1806 		dbus_connection_send(iface->con, msg, NULL);
1807 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1808 	}
1809 	dbus_message_unref(msg);
1810 }
1811 
1812 
1813 /**
1814  *
1815  * Method to emit a signal for a service discovery request.
1816  * The signal will carry station address, frequency, dialog token,
1817  * update indicator and it tlvs
1818  *
1819  * @wpa_s: %wpa_supplicant network interface data
1820  * @sa: station addr (p2p i/f) of the peer
1821  * @dialog_token: service discovery request dialog token
1822  * @update_indic: service discovery request update indicator
1823  * @tlvs: service discovery request genrated byte array of tlvs
1824  * @tlvs_len: service discovery request tlvs length
1825  */
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)1826 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
1827 				     int freq, const u8 *sa, u8 dialog_token,
1828 				     u16 update_indic, const u8 *tlvs,
1829 				     size_t tlvs_len)
1830 {
1831 	DBusMessage *msg;
1832 	DBusMessageIter iter, dict_iter;
1833 	struct wpas_dbus_priv *iface;
1834 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1835 
1836 	iface = wpa_s->global->dbus;
1837 
1838 	/* Do nothing if the control interface is not turned on */
1839 	if (iface == NULL)
1840 		return;
1841 
1842 	if (wpa_s->p2p_mgmt)
1843 		wpa_s = wpa_s->parent;
1844 	if (!wpa_s->dbus_new_path)
1845 		return;
1846 
1847 	/* Check if this is a known peer */
1848 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
1849 		return;
1850 
1851 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1852 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1853 				      "ServiceDiscoveryRequest");
1854 	if (msg == NULL)
1855 		return;
1856 
1857 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1858 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1859 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1860 
1861 	path = peer_obj_path;
1862 
1863 	dbus_message_iter_init_append(msg, &iter);
1864 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1865 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1866 					      path) ||
1867 	    !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
1868 	    !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
1869 					dialog_token) ||
1870 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1871 					 update_indic) ||
1872 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1873 					     (const char *) tlvs,
1874 					     tlvs_len) ||
1875 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1876 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1877 	else
1878 		dbus_connection_send(iface->con, msg, NULL);
1879 	dbus_message_unref(msg);
1880 }
1881 
1882 
1883 /**
1884  *
1885  * Method to emit a signal for a service discovery response.
1886  * The signal will carry station address, update indicator and it
1887  * tlvs
1888  *
1889  * @wpa_s: %wpa_supplicant network interface data
1890  * @sa: station addr (p2p i/f) of the peer
1891  * @update_indic: service discovery request update indicator
1892  * @tlvs: service discovery request genrated byte array of tlvs
1893  * @tlvs_len: service discovery request tlvs length
1894  */
wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant * wpa_s,const u8 * sa,u16 update_indic,const u8 * tlvs,size_t tlvs_len)1895 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
1896 				      const u8 *sa, u16 update_indic,
1897 				      const u8 *tlvs, size_t tlvs_len)
1898 {
1899 	DBusMessage *msg;
1900 	DBusMessageIter iter, dict_iter;
1901 	struct wpas_dbus_priv *iface;
1902 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1903 
1904 	iface = wpa_s->global->dbus;
1905 
1906 	/* Do nothing if the control interface is not turned on */
1907 	if (iface == NULL)
1908 		return;
1909 
1910 	if (wpa_s->p2p_mgmt)
1911 		wpa_s = wpa_s->parent;
1912 	if (!wpa_s->dbus_new_path)
1913 		return;
1914 
1915 	/* Check if this is a known peer */
1916 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
1917 		return;
1918 
1919 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1920 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1921 				      "ServiceDiscoveryResponse");
1922 	if (msg == NULL)
1923 		return;
1924 
1925 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1926 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1927 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1928 
1929 	path = peer_obj_path;
1930 
1931 	dbus_message_iter_init_append(msg, &iter);
1932 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1933 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1934 					      path) ||
1935 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1936 					 update_indic) ||
1937 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1938 					     (const char *) tlvs,
1939 					     tlvs_len) ||
1940 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1941 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1942 	else
1943 		dbus_connection_send(iface->con, msg, NULL);
1944 	dbus_message_unref(msg);
1945 }
1946 
1947 
1948 /**
1949  * wpas_dbus_signal_persistent_group - Send a persistent group related
1950  *	event signal
1951  * @wpa_s: %wpa_supplicant network interface data
1952  * @id: new persistent group id
1953  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
1954  * @properties: determines if add second argument with object properties
1955  *
1956  * Notify listeners about an event related to persistent groups.
1957  */
wpas_dbus_signal_persistent_group(struct wpa_supplicant * wpa_s,int id,const char * sig_name,dbus_bool_t properties)1958 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
1959 					      int id, const char *sig_name,
1960 					      dbus_bool_t properties)
1961 {
1962 	struct wpas_dbus_priv *iface;
1963 	DBusMessage *msg;
1964 	DBusMessageIter iter;
1965 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1966 
1967 	iface = wpa_s->global->dbus;
1968 
1969 	/* Do nothing if the control interface is not turned on */
1970 	if (iface == NULL)
1971 		return;
1972 
1973 	if (wpa_s->p2p_mgmt)
1974 		wpa_s = wpa_s->parent;
1975 	if (!wpa_s->dbus_new_path)
1976 		return;
1977 
1978 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1979 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
1980 		    wpa_s->dbus_new_path, id);
1981 
1982 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1983 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1984 				      sig_name);
1985 	if (msg == NULL)
1986 		return;
1987 
1988 	dbus_message_iter_init_append(msg, &iter);
1989 	path = pgrp_obj_path;
1990 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1991 					    &path) ||
1992 	    (properties &&
1993 	     !wpa_dbus_get_object_properties(
1994 		     iface, pgrp_obj_path,
1995 		     WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
1996 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1997 	else
1998 		dbus_connection_send(iface->con, msg, NULL);
1999 
2000 	dbus_message_unref(msg);
2001 }
2002 
2003 
2004 /**
2005  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
2006  *	added signal
2007  * @wpa_s: %wpa_supplicant network interface data
2008  * @id: new persistent group id
2009  *
2010  * Notify listeners about addition of a new persistent group.
2011  */
wpas_dbus_signal_persistent_group_added(struct wpa_supplicant * wpa_s,int id)2012 static void wpas_dbus_signal_persistent_group_added(
2013 	struct wpa_supplicant *wpa_s, int id)
2014 {
2015 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
2016 					  TRUE);
2017 }
2018 
2019 
2020 /**
2021  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
2022  *	removed signal
2023  * @wpa_s: %wpa_supplicant network interface data
2024  * @id: persistent group id
2025  *
2026  * Notify listeners about removal of a persistent group.
2027  */
wpas_dbus_signal_persistent_group_removed(struct wpa_supplicant * wpa_s,int id)2028 static void wpas_dbus_signal_persistent_group_removed(
2029 	struct wpa_supplicant *wpa_s, int id)
2030 {
2031 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
2032 					  FALSE);
2033 }
2034 
2035 
2036 /**
2037  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
2038  * @wpa_s: %wpa_supplicant network interface data
2039  * @fail: WPS failure information
2040  *
2041  * Sends Event dbus signal with name "fail" and dictionary containing
2042  * "msg" field with fail message number (int32) as arguments
2043  */
wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant * wpa_s,struct wps_event_fail * fail)2044 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
2045 				     struct wps_event_fail *fail)
2046 {
2047 
2048 	DBusMessage *msg;
2049 	DBusMessageIter iter, dict_iter;
2050 	struct wpas_dbus_priv *iface;
2051 	char *key = "fail";
2052 
2053 	iface = wpa_s->global->dbus;
2054 
2055 	/* Do nothing if the control interface is not turned on */
2056 	if (iface == NULL)
2057 		return;
2058 
2059 	if (wpa_s->p2p_mgmt)
2060 		wpa_s = wpa_s->parent;
2061 
2062 	if (!wpa_s->dbus_new_path)
2063 		return;
2064 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2065 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2066 				      "WpsFailed");
2067 	if (msg == NULL)
2068 		return;
2069 
2070 	dbus_message_iter_init_append(msg, &iter);
2071 
2072 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
2073 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2074 	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
2075 	    !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
2076 					fail->config_error) ||
2077 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
2078 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2079 	else
2080 		dbus_connection_send(iface->con, msg, NULL);
2081 
2082 	dbus_message_unref(msg);
2083 }
2084 
2085 
2086 /**
2087  * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event
2088  * @wpa_s: %wpa_supplicant network interface data
2089  * @reason: indicates the reason code for group formation failure
2090  *
2091  * Sends Event dbus signal and string reason code when available.
2092  */
wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant * wpa_s,const char * reason)2093 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
2094 						  const char *reason)
2095 {
2096 	DBusMessage *msg;
2097 	struct wpas_dbus_priv *iface;
2098 
2099 	iface = wpa_s->global->dbus;
2100 
2101 	/* Do nothing if the control interface is not turned on */
2102 	if (iface == NULL)
2103 		return;
2104 
2105 	if (wpa_s->p2p_mgmt)
2106 		wpa_s = wpa_s->parent;
2107 
2108 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2109 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2110 				      "GroupFormationFailure");
2111 	if (msg == NULL)
2112 		return;
2113 
2114 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
2115 				     DBUS_TYPE_INVALID))
2116 		dbus_connection_send(iface->con, msg, NULL);
2117 	else
2118 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
2119 
2120 	dbus_message_unref(msg);
2121 }
2122 
2123 
2124 /**
2125  * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal
2126  * @wpa_s: %wpa_supplicant network interface data
2127  * @sa: Source address of the Invitation Request
2128  * @dev_add: GO Device Address
2129  * @bssid: P2P Group BSSID or %NULL if not received
2130  * @id: Persistent group id or %0 if not persistent group
2131  * @op_freq: Operating frequency for the group
2132  */
2133 
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)2134 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
2135 					      const u8 *sa, const u8 *dev_addr,
2136 					      const u8 *bssid, int id,
2137 					      int op_freq)
2138 {
2139 	DBusMessage *msg;
2140 	DBusMessageIter iter, dict_iter;
2141 	struct wpas_dbus_priv *iface;
2142 
2143 	iface = wpa_s->global->dbus;
2144 
2145 	/* Do nothing if the control interface is not turned on */
2146 	if (iface == NULL)
2147 		return;
2148 
2149 	if (wpa_s->p2p_mgmt)
2150 		wpa_s = wpa_s->parent;
2151 
2152 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
2153 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2154 				      "InvitationReceived");
2155 	if (msg == NULL)
2156 		return;
2157 
2158 	dbus_message_iter_init_append(msg, &iter);
2159 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
2160 	    (sa &&
2161 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "sa",
2162 					      (const char *) sa, ETH_ALEN)) ||
2163 	    (dev_addr &&
2164 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr",
2165 					      (const char *) dev_addr,
2166 					      ETH_ALEN)) ||
2167 	    (bssid &&
2168 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
2169 					      (const char *) bssid,
2170 					      ETH_ALEN)) ||
2171 	    (id &&
2172 	     !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) ||
2173 	    !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) ||
2174 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
2175 		dbus_message_unref(msg);
2176 		return;
2177 	}
2178 
2179 	dbus_connection_send(iface->con, msg, NULL);
2180 	dbus_message_unref(msg);
2181 }
2182 
2183 
2184 #endif /* CONFIG_P2P */
2185 
2186 
2187 /**
2188  * wpas_dbus_signal_prop_changed - Signals change of property
2189  * @wpa_s: %wpa_supplicant network interface data
2190  * @property: indicates which property has changed
2191  *
2192  * Sends PropertyChanged signals with path, interface and arguments
2193  * depending on which property has changed.
2194  */
wpas_dbus_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_prop property)2195 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
2196 				   enum wpas_dbus_prop property)
2197 {
2198 	char *prop;
2199 	dbus_bool_t flush;
2200 
2201 	if (wpa_s->dbus_new_path == NULL)
2202 		return; /* Skip signal since D-Bus setup is not yet ready */
2203 
2204 	flush = FALSE;
2205 	switch (property) {
2206 	case WPAS_DBUS_PROP_AP_SCAN:
2207 		prop = "ApScan";
2208 		break;
2209 	case WPAS_DBUS_PROP_SCANNING:
2210 		prop = "Scanning";
2211 		break;
2212 	case WPAS_DBUS_PROP_STATE:
2213 		prop = "State";
2214 		break;
2215 	case WPAS_DBUS_PROP_CURRENT_BSS:
2216 		prop = "CurrentBSS";
2217 		break;
2218 	case WPAS_DBUS_PROP_CURRENT_NETWORK:
2219 		prop = "CurrentNetwork";
2220 		break;
2221 	case WPAS_DBUS_PROP_BSSS:
2222 		prop = "BSSs";
2223 		break;
2224 	case WPAS_DBUS_PROP_STATIONS:
2225 		prop = "Stations";
2226 		break;
2227 	case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
2228 		prop = "CurrentAuthMode";
2229 		break;
2230 	case WPAS_DBUS_PROP_DISCONNECT_REASON:
2231 		prop = "DisconnectReason";
2232 		flush = TRUE;
2233 		break;
2234 	case WPAS_DBUS_PROP_AUTH_STATUS_CODE:
2235 		prop = "AuthStatusCode";
2236 		flush = TRUE;
2237 		break;
2238 	case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
2239 		prop = "AssocStatusCode";
2240 		flush = TRUE;
2241 		break;
2242 	case WPAS_DBUS_PROP_ROAM_TIME:
2243 		prop = "RoamTime";
2244 		break;
2245 	case WPAS_DBUS_PROP_ROAM_COMPLETE:
2246 		prop = "RoamComplete";
2247 		break;
2248 	case WPAS_DBUS_PROP_SESSION_LENGTH:
2249 		prop = "SessionLength";
2250 		break;
2251 	case WPAS_DBUS_PROP_BSS_TM_STATUS:
2252 		prop = "BSSTMStatus";
2253 		break;
2254 	default:
2255 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2256 			   __func__, property);
2257 		return;
2258 	}
2259 
2260 	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
2261 				       wpa_s->dbus_new_path,
2262 				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
2263 	if (flush) {
2264 		wpa_dbus_flush_object_changed_properties(
2265 			wpa_s->global->dbus->con, wpa_s->dbus_new_path);
2266 	}
2267 }
2268 
2269 
2270 /**
2271  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
2272  * @wpa_s: %wpa_supplicant network interface data
2273  * @property: indicates which property has changed
2274  * @id: unique BSS identifier
2275  *
2276  * Sends PropertyChanged signals with path, interface, and arguments depending
2277  * on which property has changed.
2278  */
wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,unsigned int id)2279 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
2280 				       enum wpas_dbus_bss_prop property,
2281 				       unsigned int id)
2282 {
2283 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
2284 	char *prop;
2285 
2286 	if (!wpa_s->dbus_new_path)
2287 		return;
2288 
2289 	switch (property) {
2290 	case WPAS_DBUS_BSS_PROP_SIGNAL:
2291 		prop = "Signal";
2292 		break;
2293 	case WPAS_DBUS_BSS_PROP_FREQ:
2294 		prop = "Frequency";
2295 		break;
2296 	case WPAS_DBUS_BSS_PROP_MODE:
2297 		prop = "Mode";
2298 		break;
2299 	case WPAS_DBUS_BSS_PROP_PRIVACY:
2300 		prop = "Privacy";
2301 		break;
2302 	case WPAS_DBUS_BSS_PROP_RATES:
2303 		prop = "Rates";
2304 		break;
2305 	case WPAS_DBUS_BSS_PROP_WPA:
2306 		prop = "WPA";
2307 		break;
2308 	case WPAS_DBUS_BSS_PROP_RSN:
2309 		prop = "RSN";
2310 		break;
2311 	case WPAS_DBUS_BSS_PROP_WPS:
2312 		prop = "WPS";
2313 		break;
2314 	case WPAS_DBUS_BSS_PROP_IES:
2315 		prop = "IEs";
2316 		break;
2317 	case WPAS_DBUS_BSS_PROP_AGE:
2318 		prop = "Age";
2319 		break;
2320 	default:
2321 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2322 			   __func__, property);
2323 		return;
2324 	}
2325 
2326 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2327 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2328 		    wpa_s->dbus_new_path, id);
2329 
2330 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2331 				       WPAS_DBUS_NEW_IFACE_BSS, prop);
2332 }
2333 
2334 
2335 /**
2336  * wpas_dbus_sta_signal_prop_changed - Signals change of STA property
2337  * @wpa_s: %wpa_supplicant network interface data
2338  * @property: indicates which property has changed
2339  * @address: unique BSS identifier
2340  *
2341  * Sends PropertyChanged signals with path, interface, and arguments depending
2342  * on which property has changed.
2343  */
wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,u8 address[ETH_ALEN])2344 void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s,
2345 				       enum wpas_dbus_bss_prop property,
2346 				       u8 address[ETH_ALEN])
2347 {
2348 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
2349 	char *prop;
2350 
2351 	switch (property) {
2352 	case WPAS_DBUS_STA_PROP_ADDRESS:
2353 		prop = "Address";
2354 		break;
2355 	default:
2356 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2357 			   __func__, property);
2358 		return;
2359 	}
2360 
2361 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2362 		    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
2363 		    wpa_s->dbus_new_path, MAC2STR(address));
2364 
2365 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2366 				       WPAS_DBUS_NEW_IFACE_STA, prop);
2367 }
2368 
2369 
2370 /**
2371  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
2372  * @global: wpa_global structure
2373  *
2374  * Sends PropertyChanged signals informing that debug level has changed.
2375  */
wpas_dbus_signal_debug_level_changed(struct wpa_global * global)2376 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
2377 {
2378 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2379 				       WPAS_DBUS_NEW_INTERFACE,
2380 				       "DebugLevel");
2381 }
2382 
2383 
2384 /**
2385  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
2386  * @global: wpa_global structure
2387  *
2388  * Sends PropertyChanged signals informing that debug timestamp has changed.
2389  */
wpas_dbus_signal_debug_timestamp_changed(struct wpa_global * global)2390 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
2391 {
2392 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2393 				       WPAS_DBUS_NEW_INTERFACE,
2394 				       "DebugTimestamp");
2395 }
2396 
2397 
2398 /**
2399  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
2400  * @global: wpa_global structure
2401  *
2402  * Sends PropertyChanged signals informing that debug show_keys has changed.
2403  */
wpas_dbus_signal_debug_show_keys_changed(struct wpa_global * global)2404 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
2405 {
2406 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2407 				       WPAS_DBUS_NEW_INTERFACE,
2408 				       "DebugShowKeys");
2409 }
2410 
2411 
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)2412 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
2413 			       void *priv,
2414 			       WPADBusArgumentFreeFunction priv_free,
2415 			       const struct wpa_dbus_method_desc *methods,
2416 			       const struct wpa_dbus_property_desc *properties,
2417 			       const struct wpa_dbus_signal_desc *signals)
2418 {
2419 	int n;
2420 
2421 	obj_desc->user_data = priv;
2422 	obj_desc->user_data_free_func = priv_free;
2423 	obj_desc->methods = methods;
2424 	obj_desc->properties = properties;
2425 	obj_desc->signals = signals;
2426 
2427 	for (n = 0; properties && properties->dbus_property; properties++)
2428 		n++;
2429 
2430 	obj_desc->prop_changed_flags = os_zalloc(n);
2431 	if (!obj_desc->prop_changed_flags)
2432 		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
2433 			   __func__);
2434 }
2435 
2436 
2437 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
2438 	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
2439 	  (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
2440 	  {
2441 		  { "args", "a{sv}", ARG_IN },
2442 		  { "path", "o", ARG_OUT },
2443 		  END_ARGS
2444 	  }
2445 	},
2446 	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
2447 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
2448 	  {
2449 		  { "path", "o", ARG_IN },
2450 		  END_ARGS
2451 	  }
2452 	},
2453 	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
2454 	  (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
2455 	  {
2456 		  { "ifname", "s", ARG_IN },
2457 		  { "path", "o", ARG_OUT },
2458 		  END_ARGS
2459 	  }
2460 	},
2461 	{ "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
2462 	  (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
2463 	  {
2464 		END_ARGS
2465 	  }
2466 	},
2467 	{ NULL, NULL, NULL, { END_ARGS } }
2468 };
2469 
2470 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
2471 	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
2472 	  wpas_dbus_getter_debug_level,
2473 	  wpas_dbus_setter_debug_level,
2474 	  NULL
2475 	},
2476 	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
2477 	  wpas_dbus_getter_debug_timestamp,
2478 	  wpas_dbus_setter_debug_timestamp,
2479 	  NULL
2480 	},
2481 	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
2482 	  wpas_dbus_getter_debug_show_keys,
2483 	  wpas_dbus_setter_debug_show_keys,
2484 	  NULL
2485 	},
2486 	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
2487 	  wpas_dbus_getter_interfaces,
2488 	  NULL,
2489 	  NULL
2490 	},
2491 	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
2492 	  wpas_dbus_getter_eap_methods,
2493 	  NULL,
2494 	  NULL
2495 	},
2496 	{ "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
2497 	  wpas_dbus_getter_global_capabilities,
2498 	  NULL,
2499 	  NULL
2500 	},
2501 #ifdef CONFIG_WIFI_DISPLAY
2502 	{ "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
2503 	  wpas_dbus_getter_global_wfd_ies,
2504 	  wpas_dbus_setter_global_wfd_ies,
2505 	  NULL
2506 	},
2507 #endif /* CONFIG_WIFI_DISPLAY */
2508 	{ NULL, NULL, NULL, NULL, NULL, NULL }
2509 };
2510 
2511 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2512 	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2513 	  {
2514 		  { "path", "o", ARG_OUT },
2515 		  { "properties", "a{sv}", ARG_OUT },
2516 		  END_ARGS
2517 	  }
2518 	},
2519 	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2520 	  {
2521 		  { "path", "o", ARG_OUT },
2522 		  END_ARGS
2523 	  }
2524 	},
2525 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2526 	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2527 	  {
2528 		  { "properties", "a{sv}", ARG_OUT },
2529 		  END_ARGS
2530 	  }
2531 	},
2532 	{ NULL, NULL, { END_ARGS } }
2533 };
2534 
2535 
uscore_to_dbus(const char * uscore)2536 static char * uscore_to_dbus(const char *uscore)
2537 {
2538 	const char *p = uscore;
2539 	char *str, *s;
2540 	dbus_bool_t last_was_uscore = TRUE;
2541 
2542 	s = str = os_zalloc(os_strlen(uscore) + 1);
2543 	if (!str)
2544 		return NULL;
2545 	while (p && *p) {
2546 		if (*p == '_') {
2547 			last_was_uscore = TRUE;
2548 		} else {
2549 			*s++ = last_was_uscore ? toupper(*p) : *p;
2550 			last_was_uscore = FALSE;
2551 		}
2552 		p++;
2553 	}
2554 
2555 	return str;
2556 }
2557 
2558 
2559 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
2560 
2561 
wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv * priv)2562 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
2563 {
2564 	int idx = priv->globals_start;
2565 
2566 	/* Free all allocated property values */
2567 	while (priv->all_interface_properties[idx].dbus_property)
2568 		os_free((char *)
2569 			priv->all_interface_properties[idx++].dbus_property);
2570 	os_free((char *) priv->all_interface_properties);
2571 }
2572 
2573 
2574 /**
2575  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2576  * @global: Pointer to global data from wpa_supplicant_init()
2577  * Returns: 0 on success or -1 on failure
2578  *
2579  * Initialize the dbus control interface for wpa_supplicant and start
2580  * receiving commands from external programs over the bus.
2581  */
wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv * priv)2582 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2583 {
2584 	struct wpa_dbus_object_desc *obj_desc;
2585 	int ret;
2586 
2587 	ret = wpa_dbus_ctrl_iface_props_init(priv);
2588 	if (ret < 0) {
2589 		wpa_printf(MSG_ERROR,
2590 			   "dbus: Not enough memory to init interface properties");
2591 		return -1;
2592 	}
2593 
2594 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2595 	if (!obj_desc) {
2596 		wpa_printf(MSG_ERROR,
2597 			   "Not enough memory to create object description");
2598 		goto error;
2599 	}
2600 
2601 	wpas_dbus_register(obj_desc, priv->global, NULL,
2602 			   wpas_dbus_global_methods,
2603 			   wpas_dbus_global_properties,
2604 			   wpas_dbus_global_signals);
2605 
2606 	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2607 		   WPAS_DBUS_NEW_PATH);
2608 	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2609 				       WPAS_DBUS_NEW_SERVICE,
2610 				       obj_desc);
2611 	if (ret < 0) {
2612 		free_dbus_object_desc(obj_desc);
2613 		goto error;
2614 	}
2615 
2616 	priv->dbus_new_initialized = 1;
2617 	return 0;
2618 
2619 error:
2620 	wpa_dbus_ctrl_iface_props_deinit(priv);
2621 	return -1;
2622 }
2623 
2624 
2625 /**
2626  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2627  * wpa_supplicant
2628  * @priv: Pointer to dbus private data from wpas_dbus_init()
2629  *
2630  * Deinitialize the dbus control interface that was initialized with
2631  * wpas_dbus_ctrl_iface_init().
2632  */
wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv * priv)2633 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
2634 {
2635 	if (!priv->dbus_new_initialized)
2636 		return;
2637 	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2638 		   WPAS_DBUS_NEW_PATH);
2639 	dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
2640 	wpa_dbus_ctrl_iface_props_deinit(priv);
2641 }
2642 
2643 
wpa_dbus_free(void * ptr)2644 static void wpa_dbus_free(void *ptr)
2645 {
2646 	os_free(ptr);
2647 }
2648 
2649 
2650 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2651 	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2652 	  wpas_dbus_getter_network_properties,
2653 	  wpas_dbus_setter_network_properties,
2654 	  NULL
2655 	},
2656 	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2657 	  wpas_dbus_getter_enabled,
2658 	  wpas_dbus_setter_enabled,
2659 	  NULL
2660 	},
2661 	{ NULL, NULL, NULL, NULL, NULL, NULL }
2662 };
2663 
2664 
2665 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2666 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2667 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2668 	  {
2669 		  { "properties", "a{sv}", ARG_OUT },
2670 		  END_ARGS
2671 	  }
2672 	},
2673 	{ NULL, NULL, { END_ARGS } }
2674 };
2675 
2676 
2677 /**
2678  * wpas_dbus_register_network - Register a configured network with dbus
2679  * @wpa_s: wpa_supplicant interface structure
2680  * @ssid: network configuration data
2681  * Returns: 0 on success, -1 on failure
2682  *
2683  * Registers network representing object with dbus
2684  */
wpas_dbus_register_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2685 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2686 			       struct wpa_ssid *ssid)
2687 {
2688 	struct wpas_dbus_priv *ctrl_iface;
2689 	struct wpa_dbus_object_desc *obj_desc;
2690 	struct network_handler_args *arg;
2691 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2692 
2693 #ifdef CONFIG_P2P
2694 	/*
2695 	 * If it is a persistent group register it as such.
2696 	 * This is to handle cases where an interface is being initialized
2697 	 * with a list of networks read from config.
2698 	 */
2699 	if (network_is_persistent_group(ssid))
2700 		return wpas_dbus_register_persistent_group(wpa_s, ssid);
2701 #endif /* CONFIG_P2P */
2702 
2703 	/* Do nothing if the control interface is not turned on */
2704 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2705 		return 0;
2706 	ctrl_iface = wpa_s->global->dbus;
2707 	if (ctrl_iface == NULL)
2708 		return 0;
2709 
2710 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2711 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2712 		    wpa_s->dbus_new_path, ssid->id);
2713 
2714 	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2715 		   net_obj_path);
2716 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2717 	if (!obj_desc) {
2718 		wpa_printf(MSG_ERROR,
2719 			   "Not enough memory to create object description");
2720 		goto err;
2721 	}
2722 
2723 	/* allocate memory for handlers arguments */
2724 	arg = os_zalloc(sizeof(struct network_handler_args));
2725 	if (!arg) {
2726 		wpa_printf(MSG_ERROR,
2727 			   "Not enough memory to create arguments for method");
2728 		goto err;
2729 	}
2730 
2731 	arg->wpa_s = wpa_s;
2732 	arg->ssid = ssid;
2733 
2734 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2735 			   wpas_dbus_network_properties,
2736 			   wpas_dbus_network_signals);
2737 
2738 	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2739 					       wpa_s->ifname, obj_desc))
2740 		goto err;
2741 
2742 	wpas_dbus_signal_network_added(wpa_s, ssid->id);
2743 
2744 	return 0;
2745 
2746 err:
2747 	free_dbus_object_desc(obj_desc);
2748 	return -1;
2749 }
2750 
2751 
2752 /**
2753  * wpas_dbus_unregister_network - Unregister a configured network from dbus
2754  * @wpa_s: wpa_supplicant interface structure
2755  * @nid: network id
2756  * Returns: 0 on success, -1 on failure
2757  *
2758  * Unregisters network representing object from dbus
2759  */
wpas_dbus_unregister_network(struct wpa_supplicant * wpa_s,int nid)2760 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2761 {
2762 	struct wpas_dbus_priv *ctrl_iface;
2763 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2764 	int ret;
2765 #ifdef CONFIG_P2P
2766 	struct wpa_ssid *ssid;
2767 
2768 	ssid = wpa_config_get_network(wpa_s->conf, nid);
2769 
2770 	/* If it is a persistent group unregister it as such */
2771 	if (ssid && network_is_persistent_group(ssid))
2772 		return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2773 #endif /* CONFIG_P2P */
2774 
2775 	/* Do nothing if the control interface is not turned on */
2776 	if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2777 		return 0;
2778 	ctrl_iface = wpa_s->global->dbus;
2779 	if (ctrl_iface == NULL)
2780 		return 0;
2781 
2782 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2783 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2784 		    wpa_s->dbus_new_path, nid);
2785 
2786 	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2787 		   net_obj_path);
2788 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2789 
2790 	if (!ret)
2791 		wpas_dbus_signal_network_removed(wpa_s, nid);
2792 
2793 	return ret;
2794 }
2795 
2796 
2797 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2798 	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2799 	  wpas_dbus_getter_bss_ssid,
2800 	  NULL,
2801 	  NULL
2802 	},
2803 	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2804 	  wpas_dbus_getter_bss_bssid,
2805 	  NULL,
2806 	  NULL
2807 	},
2808 	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2809 	  wpas_dbus_getter_bss_privacy,
2810 	  NULL,
2811 	  NULL
2812 	},
2813 	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2814 	  wpas_dbus_getter_bss_mode,
2815 	  NULL,
2816 	  NULL
2817 	},
2818 	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2819 	  wpas_dbus_getter_bss_signal,
2820 	  NULL,
2821 	  NULL
2822 	},
2823 	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2824 	  wpas_dbus_getter_bss_frequency,
2825 	  NULL,
2826 	  NULL
2827 	},
2828 	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2829 	  wpas_dbus_getter_bss_rates,
2830 	  NULL,
2831 	  NULL
2832 	},
2833 	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2834 	  wpas_dbus_getter_bss_wpa,
2835 	  NULL,
2836 	  NULL
2837 	},
2838 	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2839 	  wpas_dbus_getter_bss_rsn,
2840 	  NULL,
2841 	  NULL
2842 	},
2843 	{ "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2844 	  wpas_dbus_getter_bss_wps,
2845 	  NULL,
2846 	  NULL
2847 	},
2848 	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2849 	  wpas_dbus_getter_bss_ies,
2850 	  NULL,
2851 	  NULL
2852 	},
2853 	{ "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
2854 	  wpas_dbus_getter_bss_age,
2855 	  NULL,
2856 	  NULL
2857 	},
2858 	{
2859 	  "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2860 	  wpas_dbus_getter_roam_time,
2861 	  NULL,
2862 	  NULL
2863 	},
2864 	{
2865 	  "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2866 	  wpas_dbus_getter_roam_complete,
2867 	  NULL,
2868 	  NULL
2869 	},
2870 	{
2871 	  "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2872 	  wpas_dbus_getter_session_length,
2873 	  NULL,
2874 	  NULL
2875 	},
2876 	{
2877 	  "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2878 	  wpas_dbus_getter_bss_tm_status,
2879 	  NULL,
2880 	  NULL
2881 	},
2882 	{ NULL, NULL, NULL, NULL, NULL, NULL }
2883 };
2884 
2885 
2886 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2887 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2888 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2889 	  {
2890 		  { "properties", "a{sv}", ARG_OUT },
2891 		  END_ARGS
2892 	  }
2893 	},
2894 	{ NULL, NULL, { END_ARGS } }
2895 };
2896 
2897 
2898 /**
2899  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2900  * @wpa_s: wpa_supplicant interface structure
2901  * @bssid: scanned network bssid
2902  * @id: unique BSS identifier
2903  * Returns: 0 on success, -1 on failure
2904  *
2905  * Unregisters BSS representing object from dbus
2906  */
wpas_dbus_unregister_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)2907 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2908 			     u8 bssid[ETH_ALEN], unsigned int id)
2909 {
2910 	struct wpas_dbus_priv *ctrl_iface;
2911 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2912 
2913 	/* Do nothing if the control interface is not turned on */
2914 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2915 		return 0;
2916 	ctrl_iface = wpa_s->global->dbus;
2917 	if (ctrl_iface == NULL)
2918 		return 0;
2919 
2920 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2921 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2922 		    wpa_s->dbus_new_path, id);
2923 
2924 	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2925 		   bss_obj_path);
2926 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2927 		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2928 			   bss_obj_path);
2929 		return -1;
2930 	}
2931 
2932 	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
2933 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2934 
2935 	return 0;
2936 }
2937 
2938 
2939 /**
2940  * wpas_dbus_register_bss - Register a scanned BSS with dbus
2941  * @wpa_s: wpa_supplicant interface structure
2942  * @bssid: scanned network bssid
2943  * @id: unique BSS identifier
2944  * Returns: 0 on success, -1 on failure
2945  *
2946  * Registers BSS representing object with dbus
2947  */
wpas_dbus_register_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)2948 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
2949 			   u8 bssid[ETH_ALEN], unsigned int id)
2950 {
2951 	struct wpas_dbus_priv *ctrl_iface;
2952 	struct wpa_dbus_object_desc *obj_desc;
2953 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2954 	struct bss_handler_args *arg;
2955 
2956 	/* Do nothing if the control interface is not turned on */
2957 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2958 		return 0;
2959 	ctrl_iface = wpa_s->global->dbus;
2960 	if (ctrl_iface == NULL)
2961 		return 0;
2962 
2963 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2964 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2965 		    wpa_s->dbus_new_path, id);
2966 
2967 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2968 	if (!obj_desc) {
2969 		wpa_printf(MSG_ERROR,
2970 			   "Not enough memory to create object description");
2971 		goto err;
2972 	}
2973 
2974 	arg = os_zalloc(sizeof(struct bss_handler_args));
2975 	if (!arg) {
2976 		wpa_printf(MSG_ERROR,
2977 			   "Not enough memory to create arguments for handler");
2978 		goto err;
2979 	}
2980 	arg->wpa_s = wpa_s;
2981 	arg->id = id;
2982 
2983 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2984 			   wpas_dbus_bss_properties,
2985 			   wpas_dbus_bss_signals);
2986 
2987 	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
2988 		   bss_obj_path);
2989 	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
2990 					       wpa_s->ifname, obj_desc)) {
2991 		wpa_printf(MSG_ERROR,
2992 			   "Cannot register BSSID dbus object %s.",
2993 			   bss_obj_path);
2994 		goto err;
2995 	}
2996 
2997 	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
2998 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2999 
3000 	return 0;
3001 
3002 err:
3003 	free_dbus_object_desc(obj_desc);
3004 	return -1;
3005 }
3006 
3007 
3008 static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = {
3009 	{ "Address", WPAS_DBUS_NEW_IFACE_STA, "ay",
3010 	  wpas_dbus_getter_sta_address,
3011 	  NULL, NULL
3012 	},
3013 	{ "AID", WPAS_DBUS_NEW_IFACE_STA, "q",
3014 	  wpas_dbus_getter_sta_aid,
3015 	  NULL, NULL
3016 	},
3017 	{ "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q",
3018 	  wpas_dbus_getter_sta_caps,
3019 	  NULL, NULL
3020 	},
3021 	{ "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3022 	  wpas_dbus_getter_sta_rx_packets,
3023 	  NULL, NULL
3024 	},
3025 	{ "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t",
3026 	  wpas_dbus_getter_sta_tx_packets,
3027 	  NULL, NULL
3028 	},
3029 	{ "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3030 	  wpas_dbus_getter_sta_rx_bytes,
3031 	  NULL, NULL
3032 	},
3033 	{ "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t",
3034 	  wpas_dbus_getter_sta_tx_bytes,
3035 	  NULL, NULL
3036 	},
3037 	{ NULL, NULL, NULL, NULL, NULL, NULL }
3038 };
3039 
3040 
3041 static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = {
3042 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3043 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA,
3044 	  {
3045 		  { "properties", "a{sv}", ARG_OUT },
3046 		  END_ARGS
3047 	  }
3048 	},
3049 	{ NULL, NULL, { END_ARGS } }
3050 };
3051 
3052 
3053 /**
3054  * wpas_dbus_unregister_sta - Unregister a connected station from dbus
3055  * @wpa_s: wpa_supplicant interface structure
3056  * @sta: station MAC address
3057  * Returns: 0 on success, -1 on failure
3058  *
3059  * Unregisters STA representing object from dbus.
3060  */
wpas_dbus_unregister_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3061 int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3062 {
3063 	struct wpas_dbus_priv *ctrl_iface;
3064 	char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3065 
3066 	/* Do nothing if the control interface is not turned on */
3067 	if (!wpa_s || !wpa_s->global)
3068 		return 0;
3069 	ctrl_iface = wpa_s->global->dbus;
3070 	if (!ctrl_iface)
3071 		return 0;
3072 
3073 	os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3074 		    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3075 		    wpa_s->dbus_new_path, MAC2STR(sta));
3076 
3077 	wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
3078 		   station_obj_path);
3079 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3080 						 station_obj_path)) {
3081 		wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
3082 			   station_obj_path);
3083 		return -1;
3084 	}
3085 
3086 	wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
3087 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3088 
3089 	return 0;
3090 }
3091 
3092 
3093 /**
3094  * wpas_dbus_register_sta - Register a connected station with dbus
3095  * @wpa_s: wpa_supplicant interface structure
3096  * @sta: station MAC address
3097  * Returns: 0 on success, -1 on failure
3098  *
3099  * Registers STA representing object with dbus.
3100  */
wpas_dbus_register_sta(struct wpa_supplicant * wpa_s,const u8 * sta)3101 int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta)
3102 {
3103 	struct wpas_dbus_priv *ctrl_iface;
3104 	struct wpa_dbus_object_desc *obj_desc;
3105 	char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3106 	struct sta_handler_args *arg;
3107 
3108 	/* Do nothing if the control interface is not turned on */
3109 	if (!wpa_s || !wpa_s->global)
3110 		return 0;
3111 	ctrl_iface = wpa_s->global->dbus;
3112 	if (!ctrl_iface)
3113 		return 0;
3114 
3115 	os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3116 		    "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
3117 		    wpa_s->dbus_new_path, MAC2STR(sta));
3118 
3119 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3120 	if (!obj_desc) {
3121 		wpa_printf(MSG_ERROR,
3122 			   "Not enough memory to create object description");
3123 		goto err;
3124 	}
3125 
3126 	arg = os_zalloc(sizeof(struct sta_handler_args));
3127 	if (!arg) {
3128 		wpa_printf(MSG_ERROR,
3129 			   "Not enough memory to create arguments for handler");
3130 		goto err;
3131 	}
3132 	arg->wpa_s = wpa_s;
3133 	arg->sta = sta;
3134 
3135 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3136 			   wpas_dbus_sta_properties, wpas_dbus_sta_signals);
3137 
3138 	wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
3139 		   station_obj_path);
3140 	if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
3141 					       wpa_s->ifname, obj_desc)) {
3142 		wpa_printf(MSG_ERROR,
3143 			   "Cannot register STA dbus object %s",
3144 			   station_obj_path);
3145 		goto err;
3146 	}
3147 
3148 	wpas_dbus_signal_station_added(wpa_s, station_obj_path);
3149 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
3150 
3151 	return 0;
3152 
3153 err:
3154 	free_dbus_object_desc(obj_desc);
3155 	return -1;
3156 }
3157 
3158 
3159 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
3160 	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3161 	  (WPADBusMethodHandler) wpas_dbus_handler_scan,
3162 	  {
3163 		  { "args", "a{sv}", ARG_IN },
3164 		  END_ARGS
3165 	  }
3166 	},
3167 	{ "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
3168 	  (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
3169 	  {
3170 		  { "args", "a{sv}", ARG_OUT },
3171 		  END_ARGS
3172 	  }
3173 	},
3174 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3175 	  (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
3176 	  {
3177 		  END_ARGS
3178 	  }
3179 	},
3180 	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3181 	  (WPADBusMethodHandler) wpas_dbus_handler_add_network,
3182 	  {
3183 		  { "args", "a{sv}", ARG_IN },
3184 		  { "path", "o", ARG_OUT },
3185 		  END_ARGS
3186 	  }
3187 	},
3188 	{ "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
3189 	  (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
3190 	  {
3191 		  END_ARGS
3192 	  }
3193 	},
3194 	{ "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
3195 	  (WPADBusMethodHandler) wpas_dbus_handler_reattach,
3196 	  {
3197 		  END_ARGS
3198 	  }
3199 	},
3200 	{ "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
3201 	  (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
3202 	  {
3203 		  END_ARGS
3204 	  }
3205 	},
3206 	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3207 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
3208 	  {
3209 		  { "path", "o", ARG_IN },
3210 		  END_ARGS
3211 	  }
3212 	},
3213 	{ "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
3214 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
3215 	  {
3216 		  END_ARGS
3217 	  }
3218 	},
3219 	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
3220 	  (WPADBusMethodHandler) wpas_dbus_handler_select_network,
3221 	  {
3222 		  { "path", "o", ARG_IN },
3223 		  END_ARGS
3224 	  }
3225 	},
3226 	{ "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
3227 	  (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
3228 	  {
3229 		  { "path", "o", ARG_IN },
3230 		  { "field", "s", ARG_IN },
3231 		  { "value", "s", ARG_IN },
3232 		  END_ARGS
3233 	  }
3234 	},
3235 #ifndef CONFIG_NO_CONFIG_BLOBS
3236 	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3237 	  (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
3238 	  {
3239 		  { "name", "s", ARG_IN },
3240 		  { "data", "ay", ARG_IN },
3241 		  END_ARGS
3242 	  }
3243 	},
3244 	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3245 	  (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
3246 	  {
3247 		  { "name", "s", ARG_IN },
3248 		  { "data", "ay", ARG_OUT },
3249 		  END_ARGS
3250 	  }
3251 	},
3252 	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
3253 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
3254 	  {
3255 		  { "name", "s", ARG_IN },
3256 		  END_ARGS
3257 	  }
3258 	},
3259 #endif /* CONFIG_NO_CONFIG_BLOBS */
3260 	{ "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
3261 	  (WPADBusMethodHandler)
3262 	  wpas_dbus_handler_set_pkcs11_engine_and_module_path,
3263 	  {
3264 		  { "pkcs11_engine_path", "s", ARG_IN },
3265 		  { "pkcs11_module_path", "s", ARG_IN },
3266 		  END_ARGS
3267 	  }
3268 	},
3269 #ifdef CONFIG_WPS
3270 	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
3271 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
3272 	  {
3273 		  { "args", "a{sv}", ARG_IN },
3274 		  { "output", "a{sv}", ARG_OUT },
3275 		  END_ARGS
3276 	  }
3277 	},
3278 	{ "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
3279 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
3280 	  {
3281 		  END_ARGS
3282 	  }
3283 	},
3284 #endif /* CONFIG_WPS */
3285 #ifdef CONFIG_P2P
3286 	{ "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3287 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
3288 	  {
3289 		  { "args", "a{sv}", ARG_IN },
3290 		  END_ARGS
3291 	  }
3292 	},
3293 	{ "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3294 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
3295 	  {
3296 		  END_ARGS
3297 	  }
3298 	},
3299 	{ "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3300 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
3301 	  {
3302 		  { "timeout", "i", ARG_IN },
3303 		  END_ARGS
3304 	  }
3305 	},
3306 	{ "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3307 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
3308 	  {
3309 		  { "args", "a{sv}", ARG_IN },
3310 		  END_ARGS
3311 	  }
3312 	},
3313 	{ "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3314 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
3315 	  {
3316 		  { "args", "a{sv}", ARG_IN },
3317 		  END_ARGS
3318 	  }
3319 	},
3320 	{ "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3321 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
3322 	  {
3323 		  { "peer", "o", ARG_IN },
3324 		  { "config_method", "s", ARG_IN },
3325 		  END_ARGS
3326 	  }
3327 	},
3328 	{ "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3329 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
3330 	  {
3331 		  { "args", "a{sv}", ARG_IN },
3332 		  { "generated_pin", "s", ARG_OUT },
3333 		  END_ARGS
3334 	  }
3335 	},
3336 	{ "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3337 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
3338 	  {
3339 		  { "args", "a{sv}", ARG_IN },
3340 		  END_ARGS
3341 	  }
3342 	},
3343 	{ "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3344 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
3345 	  {
3346 		  END_ARGS
3347 	  }
3348 	},
3349 	{ "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3350 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
3351 	  {
3352 		  { "args", "a{sv}", ARG_IN },
3353 		  END_ARGS
3354 	  }
3355 	},
3356 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3357 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
3358 	  {
3359 		  END_ARGS
3360 	  }
3361 	},
3362 	{ "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3363 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
3364 	  {
3365 		  { "peer", "o", ARG_IN },
3366 		  END_ARGS
3367 	  }
3368 	},
3369 	{ "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3370 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
3371 	  {
3372 		  { "args", "a{sv}", ARG_IN },
3373 		  END_ARGS
3374 	  }
3375 	},
3376 	{ "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3377 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
3378 	  {
3379 		  END_ARGS
3380 	  }
3381 	},
3382 	{ "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3383 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
3384 	  {
3385 		  { "args", "a{sv}", ARG_IN },
3386 		  END_ARGS
3387 	  }
3388 	},
3389 	{ "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3390 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
3391 	  {
3392 		  { "args", "a{sv}", ARG_IN },
3393 		  END_ARGS
3394 	  }
3395 	},
3396 	{ "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3397 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
3398 	  {
3399 		  END_ARGS
3400 	  }
3401 	},
3402 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3403 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
3404 	  {
3405 		  { "args", "a{sv}", ARG_IN },
3406 		  { "ref", "t", ARG_OUT },
3407 		  END_ARGS
3408 	  }
3409 	},
3410 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3411 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
3412 	  {
3413 		  { "args", "a{sv}", ARG_IN },
3414 		  END_ARGS
3415 	  }
3416 	},
3417 	{ "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3418 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
3419 	  {
3420 		  { "args", "t", ARG_IN },
3421 		  END_ARGS
3422 	  }
3423 	},
3424 	{ "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3425 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
3426 	  {
3427 		  END_ARGS
3428 	  }
3429 	},
3430 	{ "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3431 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
3432 	  {
3433 		  { "arg", "i", ARG_IN },
3434 		  END_ARGS
3435 	  }
3436 	},
3437 	{ "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3438 	  (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
3439 	  {
3440 		  { "args", "a{sv}", ARG_IN },
3441 		  { "path", "o", ARG_OUT },
3442 		  END_ARGS
3443 	  }
3444 	},
3445 	{ "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3446 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
3447 	  {
3448 		  { "path", "o", ARG_IN },
3449 		  END_ARGS
3450 	  }
3451 	},
3452 	{ "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3453 	  (WPADBusMethodHandler)
3454 	  wpas_dbus_handler_remove_all_persistent_groups,
3455 	  {
3456 		  END_ARGS
3457 	  }
3458 	},
3459 #endif /* CONFIG_P2P */
3460 	{ "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
3461 	  (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
3462 	  {
3463 		  { "age", "u", ARG_IN },
3464 		  END_ARGS
3465 	  }
3466 	},
3467 #ifdef CONFIG_AP
3468 	{ "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3469 	  (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
3470 	  {
3471 		  END_ARGS
3472 	  }
3473 	},
3474 	{ "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3475 	  (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
3476 	  {
3477 		  END_ARGS
3478 	  }
3479 	},
3480 #endif /* CONFIG_AP */
3481 	{ "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
3482 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
3483 	  {
3484 		  END_ARGS
3485 	  }
3486 	},
3487 	{ "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
3488 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
3489 	  {
3490 		  END_ARGS
3491 	  }
3492 	},
3493 #ifdef CONFIG_AUTOSCAN
3494 	{ "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3495 	  (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
3496 	  {
3497 		  { "arg", "s", ARG_IN },
3498 		  END_ARGS
3499 	  }
3500 	},
3501 #endif /* CONFIG_AUTOSCAN */
3502 #ifdef CONFIG_TDLS
3503 	{ "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
3504 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
3505 	  {
3506 		  { "peer_address", "s", ARG_IN },
3507 		  END_ARGS
3508 	  }
3509 	},
3510 	{ "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
3511 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
3512 	  {
3513 		  { "peer_address", "s", ARG_IN },
3514 		  END_ARGS
3515 	  }
3516 	},
3517 	{ "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
3518 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
3519 	  {
3520 		  { "peer_address", "s", ARG_IN },
3521 		  { "status", "s", ARG_OUT },
3522 		  END_ARGS
3523 	  }
3524 	},
3525 	{ "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
3526 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
3527 	  {
3528 		  { "peer_address", "s", ARG_IN },
3529 		  END_ARGS
3530 	  }
3531 	},
3532 	{ "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3533 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch,
3534 	  {
3535 		  { "args", "a{sv}", ARG_IN },
3536 		  END_ARGS
3537 	  }
3538 	},
3539 	{ "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE,
3540 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch,
3541 	  {
3542 		  { "peer_address", "s", ARG_IN },
3543 		  END_ARGS
3544 	  }
3545 	},
3546 #endif /* CONFIG_TDLS */
3547 	{ "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
3548 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
3549 	  {
3550 		  { "frame_id", "i", ARG_IN },
3551 		  { "ielems", "ay", ARG_IN },
3552 		  END_ARGS
3553 	  }
3554 	},
3555 	{ "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3556 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
3557 	  {
3558 		  { "frame_id", "i", ARG_IN },
3559 		  { "ielems", "ay", ARG_OUT },
3560 		  END_ARGS
3561 	  }
3562 	},
3563 	{ "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
3564 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
3565 	  {
3566 		  { "frame_id", "i", ARG_IN },
3567 		  { "ielems", "ay", ARG_IN },
3568 		  END_ARGS
3569 	  }
3570 	},
3571 #ifndef CONFIG_NO_CONFIG_WRITE
3572 	{ "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
3573 	  (WPADBusMethodHandler) wpas_dbus_handler_save_config,
3574 	  {
3575 		  END_ARGS
3576 	  }
3577 	},
3578 #endif /* CONFIG_NO_CONFIG_WRITE */
3579 	{ "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3580 	  (WPADBusMethodHandler) wpas_dbus_handler_abort_scan,
3581 	  {
3582 		  END_ARGS
3583 	  }
3584 	},
3585 	{ NULL, NULL, NULL, { END_ARGS } }
3586 };
3587 
3588 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
3589 	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
3590 	  wpas_dbus_getter_capabilities,
3591 	  NULL,
3592 	  NULL
3593 	},
3594 	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3595 	  wpas_dbus_getter_state,
3596 	  NULL,
3597 	  NULL
3598 	},
3599 	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3600 	  wpas_dbus_getter_scanning,
3601 	  NULL,
3602 	  NULL
3603 	},
3604 	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3605 	  wpas_dbus_getter_ap_scan,
3606 	  wpas_dbus_setter_ap_scan,
3607 	  NULL
3608 	},
3609 	{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3610 	  wpas_dbus_getter_bss_expire_age,
3611 	  wpas_dbus_setter_bss_expire_age,
3612 	  NULL
3613 	},
3614 	{ "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3615 	  wpas_dbus_getter_bss_expire_count,
3616 	  wpas_dbus_setter_bss_expire_count,
3617 	  NULL
3618 	},
3619 	{ "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3620 	  wpas_dbus_getter_country,
3621 	  wpas_dbus_setter_country,
3622 	  NULL
3623 	},
3624 	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3625 	  wpas_dbus_getter_ifname,
3626 	  NULL,
3627 	  NULL
3628 	},
3629 	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3630 	  wpas_dbus_getter_driver,
3631 	  NULL,
3632 	  NULL
3633 	},
3634 	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3635 	  wpas_dbus_getter_bridge_ifname,
3636 	  NULL,
3637 	  NULL
3638 	},
3639 	{ "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3640 	  wpas_dbus_getter_config_file,
3641 	  NULL,
3642 	  NULL
3643 	},
3644 	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3645 	  wpas_dbus_getter_current_bss,
3646 	  NULL,
3647 	  NULL
3648 	},
3649 	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3650 	  wpas_dbus_getter_current_network,
3651 	  NULL,
3652 	  NULL
3653 	},
3654 	{ "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3655 	  wpas_dbus_getter_current_auth_mode,
3656 	  NULL,
3657 	  NULL
3658 	},
3659 	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
3660 	  wpas_dbus_getter_blobs,
3661 	  NULL,
3662 	  NULL
3663 	},
3664 	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3665 	  wpas_dbus_getter_bsss,
3666 	  NULL,
3667 	  NULL
3668 	},
3669 	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3670 	  wpas_dbus_getter_networks,
3671 	  NULL,
3672 	  NULL
3673 	},
3674 	{ "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3675 	  wpas_dbus_getter_fast_reauth,
3676 	  wpas_dbus_setter_fast_reauth,
3677 	  NULL
3678 	},
3679 	{ "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3680 	  wpas_dbus_getter_scan_interval,
3681 	  wpas_dbus_setter_scan_interval,
3682 	  NULL
3683 	},
3684 	{ "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3685 	  wpas_dbus_getter_pkcs11_engine_path,
3686 	  NULL,
3687 	  NULL
3688 	},
3689 	{ "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3690 	  wpas_dbus_getter_pkcs11_module_path,
3691 	  NULL,
3692 	  NULL
3693 	},
3694 #ifdef CONFIG_WPS
3695 	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
3696 	  wpas_dbus_getter_process_credentials,
3697 	  wpas_dbus_setter_process_credentials,
3698 	  NULL
3699 	},
3700 	{ "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
3701 	  wpas_dbus_getter_config_methods,
3702 	  wpas_dbus_setter_config_methods,
3703 	  NULL
3704 	},
3705 	{
3706 	  "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3707 	  wpas_dbus_getter_wps_device_name,
3708 	  wpas_dbus_setter_wps_device_name,
3709 	  NULL
3710 	},
3711 	{
3712 	  "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
3713 	  wpas_dbus_getter_wps_manufacturer,
3714 	  wpas_dbus_setter_wps_manufacturer,
3715 	  NULL
3716 	},
3717 	{
3718 	  "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3719 	  wpas_dbus_getter_wps_device_model_name,
3720 	  wpas_dbus_setter_wps_device_model_name,
3721 	  NULL
3722 	},
3723 	{
3724 	  "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3725 	  wpas_dbus_getter_wps_device_model_number,
3726 	  wpas_dbus_setter_wps_device_model_number,
3727 	  NULL
3728 	},
3729 	{
3730 	  "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3731 	  wpas_dbus_getter_wps_device_serial_number,
3732 	  wpas_dbus_setter_wps_device_serial_number,
3733 	  NULL
3734 	},
3735 	{
3736 	  "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
3737 	  wpas_dbus_getter_wps_device_device_type,
3738 	  wpas_dbus_setter_wps_device_device_type,
3739 	  NULL
3740 	},
3741 #endif /* CONFIG_WPS */
3742 #ifdef CONFIG_P2P
3743 	{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
3744 	  wpas_dbus_getter_p2p_device_config,
3745 	  wpas_dbus_setter_p2p_device_config,
3746 	  NULL
3747 	},
3748 	{ "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3749 	  wpas_dbus_getter_p2p_peers,
3750 	  NULL,
3751 	  NULL
3752 	},
3753 	{ "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
3754 	  wpas_dbus_getter_p2p_role,
3755 	  NULL,
3756 	  NULL
3757 	},
3758 	{ "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3759 	  wpas_dbus_getter_p2p_group,
3760 	  NULL,
3761 	  NULL
3762 	},
3763 	{ "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3764 	  wpas_dbus_getter_p2p_peergo,
3765 	  NULL,
3766 	  NULL
3767 	},
3768 	{ "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3769 	  wpas_dbus_getter_persistent_groups,
3770 	  NULL,
3771 	  NULL
3772 	},
3773 #endif /* CONFIG_P2P */
3774 	{ "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3775 	  wpas_dbus_getter_disconnect_reason,
3776 	  NULL,
3777 	  NULL
3778 	},
3779 	{ "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3780 	  wpas_dbus_getter_auth_status_code,
3781 	  NULL,
3782 	  NULL
3783 	},
3784 	{ "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3785 	  wpas_dbus_getter_assoc_status_code,
3786 	  NULL,
3787 	  NULL
3788 	},
3789 #ifdef CONFIG_MESH
3790 	{ "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay",
3791 	  wpas_dbus_getter_mesh_peers,
3792 	  NULL,
3793 	  NULL
3794 	},
3795 	{ "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay",
3796 	  wpas_dbus_getter_mesh_group,
3797 	  NULL,
3798 	  NULL
3799 	},
3800 #endif /* CONFIG_MESH */
3801 	{ "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3802 	  wpas_dbus_getter_stas,
3803 	  NULL,
3804 	  NULL
3805 	},
3806 	{ NULL, NULL, NULL, NULL, NULL, NULL }
3807 };
3808 
3809 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
3810 	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
3811 	  {
3812 		  { "success", "b", ARG_OUT },
3813 		  END_ARGS
3814 	  }
3815 	},
3816 	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3817 	  {
3818 		  { "path", "o", ARG_OUT },
3819 		  { "properties", "a{sv}", ARG_OUT },
3820 		  END_ARGS
3821 	  }
3822 	},
3823 	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3824 	  {
3825 		  { "path", "o", ARG_OUT },
3826 		  END_ARGS
3827 	  }
3828 	},
3829 	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3830 	  {
3831 		  { "name", "s", ARG_OUT },
3832 		  END_ARGS
3833 	  }
3834 	},
3835 	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3836 	  {
3837 		  { "name", "s", ARG_OUT },
3838 		  END_ARGS
3839 	  }
3840 	},
3841 	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3842 	  {
3843 		  { "path", "o", ARG_OUT },
3844 		  { "properties", "a{sv}", ARG_OUT },
3845 		  END_ARGS
3846 	  }
3847 	},
3848 	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3849 	  {
3850 		  { "path", "o", ARG_OUT },
3851 		  END_ARGS
3852 	  }
3853 	},
3854 	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
3855 	  {
3856 		  { "path", "o", ARG_OUT },
3857 		  END_ARGS
3858 	  }
3859 	},
3860 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3861 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
3862 	  {
3863 		  { "properties", "a{sv}", ARG_OUT },
3864 		  END_ARGS
3865 	  }
3866 	},
3867 #ifdef CONFIG_WPS
3868 	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
3869 	  {
3870 		  { "name", "s", ARG_OUT },
3871 		  { "args", "a{sv}", ARG_OUT },
3872 		  END_ARGS
3873 	  }
3874 	},
3875 	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
3876 	  {
3877 		  { "credentials", "a{sv}", ARG_OUT },
3878 		  END_ARGS
3879 	  }
3880 	},
3881 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3882 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
3883 	  {
3884 		  { "properties", "a{sv}", ARG_OUT },
3885 		  END_ARGS
3886 	  }
3887 	},
3888 #endif /* CONFIG_WPS */
3889 #ifdef CONFIG_P2P
3890 	{ "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3891 	  {
3892 		  { "path", "o", ARG_OUT },
3893 		  END_ARGS
3894 	  }
3895 	},
3896 	{ "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3897 	  {
3898 		  { "path", "o", ARG_OUT },
3899 		  { "properties", "a{sv}", ARG_OUT },
3900 		  END_ARGS
3901 	  }
3902 	},
3903 	{ "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3904 	  {
3905 		  { "path", "o", ARG_OUT },
3906 		  END_ARGS
3907 	  }
3908 	},
3909 	{ "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3910 	  {
3911 		  END_ARGS
3912 	  }
3913 	},
3914 	{ "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3915 	  {
3916 		  { "peer_object", "o", ARG_OUT },
3917 		  { "pin", "s", ARG_OUT },
3918 		  END_ARGS
3919 	  }
3920 	},
3921 	{ "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3922 	  {
3923 		  { "peer_object", "o", ARG_OUT },
3924 		  { "pin", "s", ARG_OUT },
3925 		  END_ARGS
3926 	  }
3927 	},
3928 	{ "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3929 	  {
3930 		  { "peer_object", "o", ARG_OUT },
3931 		  END_ARGS
3932 	  }
3933 	},
3934 	{ "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3935 	  {
3936 		  { "peer_object", "o", ARG_OUT },
3937 		  END_ARGS
3938 	  }
3939 	},
3940 	{ "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3941 	  {
3942 		  { "peer_object", "o", ARG_OUT },
3943 		  END_ARGS
3944 	  }
3945 	},
3946 	{ "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3947 	  {
3948 		  { "peer_object", "o", ARG_OUT },
3949 		  END_ARGS
3950 	  }
3951 	},
3952 	{ "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3953 	  {
3954 		  { "peer_object", "o", ARG_OUT },
3955 		  { "status", "i", ARG_OUT },
3956 		  END_ARGS
3957 	  }
3958 	},
3959 	{ "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3960 	  {
3961 		  { "properties", "a{sv}", ARG_OUT },
3962 		  END_ARGS
3963 	  }
3964 	},
3965 	{ "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3966 	  {
3967 		  { "reason", "s", ARG_OUT },
3968 		  END_ARGS
3969 	  }
3970 	},
3971 	{ "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3972 	  {
3973 		  { "properties", "a{sv}", ARG_OUT },
3974 		  END_ARGS
3975 	  }
3976 	},
3977 	{ "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3978 	  {
3979 		  { "properties", "a{sv}", ARG_OUT },
3980 		  END_ARGS
3981 	  }
3982 	},
3983 	{ "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3984 	  {
3985 		  { "path", "o", ARG_OUT },
3986 		  { "dev_passwd_id", "q", ARG_OUT },
3987 		  { "device_go_intent", "y", ARG_OUT },
3988 		  END_ARGS
3989 	  }
3990 	},
3991 	{ "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3992 	  {
3993 		  { "invite_result", "a{sv}", ARG_OUT },
3994 		  END_ARGS
3995 	  }
3996 	},
3997 	{ "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3998 	  {
3999 		  { "properties", "a{sv}", ARG_OUT },
4000 		  END_ARGS
4001 	  }
4002 	},
4003 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4004 	  {
4005 		  { "sd_request", "a{sv}", ARG_OUT },
4006 		  END_ARGS
4007 	  }
4008 	},
4009 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4010 	  {
4011 		  { "sd_response", "a{sv}", ARG_OUT },
4012 		  END_ARGS
4013 	  }
4014 	},
4015 	{ "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4016 	  {
4017 		  { "path", "o", ARG_OUT },
4018 		  { "properties", "a{sv}", ARG_OUT },
4019 		  END_ARGS
4020 	  }
4021 	},
4022 	{ "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4023 	  {
4024 		  { "path", "o", ARG_OUT },
4025 		  END_ARGS
4026 	  }
4027 	},
4028 	{ "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4029 	  {
4030 		  { "name", "s", ARG_OUT },
4031 		  { "args", "a{sv}", ARG_OUT },
4032 		  END_ARGS
4033 	  }
4034 	},
4035 	{ "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4036 	  {
4037 		  { "properties", "a{sv}", ARG_OUT },
4038 		  END_ARGS
4039 	  }
4040 	},
4041 #endif /* CONFIG_P2P */
4042 #ifdef CONFIG_AP
4043 	{ "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4044 	  {
4045 		  { "args", "a{sv}", ARG_OUT },
4046 		  END_ARGS
4047 	  }
4048 	},
4049 #endif /* CONFIG_AP */
4050 	{ "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
4051 	  {
4052 		  { "certification", "a{sv}", ARG_OUT },
4053 		  END_ARGS
4054 	  }
4055 	},
4056 	{ "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
4057 	  {
4058 		  { "status", "s", ARG_OUT },
4059 		  { "parameter", "s", ARG_OUT },
4060 		  END_ARGS
4061 	  }
4062 	},
4063 	{ "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4064 	  {
4065 		  { "name", "s", ARG_OUT },
4066 		  END_ARGS
4067 	  }
4068 	},
4069 	{ "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
4070 	  {
4071 		  { "name", "s", ARG_OUT },
4072 		  END_ARGS
4073 	  }
4074 	},
4075 	{ "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
4076 	  {
4077 		  { "path", "o", ARG_OUT },
4078 		  { "properties", "a{sv}", ARG_OUT },
4079 		  END_ARGS
4080 	  }
4081 	},
4082 	{ "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
4083 	  {
4084 		  { "path", "o", ARG_OUT },
4085 		  END_ARGS
4086 	  }
4087 	},
4088 	{ "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
4089 	  {
4090 		  { "path", "o", ARG_OUT },
4091 		  { "field", "s", ARG_OUT },
4092 		  { "text", "s", ARG_OUT },
4093 		  END_ARGS
4094 	  }
4095 	},
4096 #ifdef CONFIG_MESH
4097 	{ "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH,
4098 	  {
4099 		  { "args", "a{sv}", ARG_OUT },
4100 		  END_ARGS
4101 	  }
4102 	},
4103 	{ "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH,
4104 	  {
4105 		  { "args", "a{sv}", ARG_OUT },
4106 		  END_ARGS
4107 	  }
4108 	},
4109 	{ "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH,
4110 	  {
4111 		  { "args", "a{sv}", ARG_OUT },
4112 		  END_ARGS
4113 	  }
4114 	},
4115 	{ "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH,
4116 	  {
4117 		  { "args", "a{sv}", ARG_OUT },
4118 		  END_ARGS
4119 	  }
4120 	},
4121 #endif /* CONFIG_MESH */
4122 	{ NULL, NULL, { END_ARGS } }
4123 };
4124 
4125 
wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv * priv)4126 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
4127 {
4128 	size_t all_size;
4129 	unsigned int i, j, count, num_const, num_globals;
4130 	const char *global_name;
4131 	static const char * const ignored_globals[] = {
4132 		"bss_expiration_age", "bss_expiration_scan_count",
4133 		"ap_scan", "country", "fast_reauth",
4134 		"pkcs11_engine_path", "pkcs11_module_path"
4135 	};
4136 
4137 	/* wpas_dbus_interface_properties terminates with a NULL element */
4138 	num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
4139 
4140 	num_globals = wpa_config_get_num_global_field_names();
4141 	priv->globals_start = num_const;
4142 
4143 	/* allocate enough for all properties + terminating NULL element */
4144 	all_size = (num_globals + num_const + 1) *
4145 		sizeof(wpas_dbus_interface_properties[0]);
4146 	priv->all_interface_properties = os_zalloc(all_size);
4147 	if (!priv->all_interface_properties) {
4148 		wpa_printf(MSG_ERROR,
4149 			   "dbus: Not enough memory for interface properties");
4150 		return -1;
4151 	}
4152 
4153 	/* Copy constant interface properties to the start of the array */
4154 	os_memcpy(priv->all_interface_properties,
4155 		  wpas_dbus_interface_properties,
4156 		  sizeof(wpas_dbus_interface_properties));
4157 
4158 	/* Dynamically construct interface global properties */
4159 	for (i = 0, count = num_const; i < num_globals; i++) {
4160 		struct wpa_dbus_property_desc *desc;
4161 		int no_var = 0;
4162 
4163 		/* ignore globals that are actually just methods */
4164 		global_name = wpa_config_get_global_field_name(i, &no_var);
4165 		if (no_var)
4166 			continue;
4167 		/* Ignore fields already explicitly exposed */
4168 		for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
4169 			if (os_strcmp(global_name, ignored_globals[j]) == 0)
4170 				break;
4171 		}
4172 		if (j < ARRAY_SIZE(ignored_globals))
4173 			continue;
4174 
4175 		desc = &priv->all_interface_properties[count++];
4176 		desc->dbus_property = uscore_to_dbus(global_name);
4177 		if (!desc->dbus_property) {
4178 			wpa_printf(MSG_ERROR,
4179 				   "dbus: Not enough memory for D-Bus property name");
4180 			goto error;
4181 		}
4182 		desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
4183 		desc->type = "s";
4184 		desc->getter = wpas_dbus_getter_iface_global;
4185 		desc->setter = wpas_dbus_setter_iface_global;
4186 		desc->data = global_name;
4187 	}
4188 
4189 	return 0;
4190 
4191 error:
4192 	wpa_dbus_ctrl_iface_props_deinit(priv);
4193 	return -1;
4194 }
4195 
4196 
4197 /**
4198  * wpas_dbus_register_interface - Register an interface with D-Bus
4199  * @wpa_s: wpa_supplicant interface structure
4200  * Returns: 0 on success, -1 on failure
4201  */
wpas_dbus_register_interface(struct wpa_supplicant * wpa_s)4202 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
4203 {
4204 	struct wpa_dbus_object_desc *obj_desc = NULL;
4205 	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
4206 	int next;
4207 
4208 	/* Do nothing if the control interface is not turned on */
4209 	if (ctrl_iface == NULL)
4210 		return 0;
4211 
4212 	/* Create and set the interface's object path */
4213 	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
4214 	if (wpa_s->dbus_new_path == NULL)
4215 		return -1;
4216 	next = ctrl_iface->next_objid++;
4217 	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
4218 		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
4219 		    next);
4220 
4221 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4222 	if (!obj_desc) {
4223 		wpa_printf(MSG_ERROR,
4224 			   "Not enough memory to create object description");
4225 		goto err;
4226 	}
4227 
4228 	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
4229 			   ctrl_iface->all_interface_properties,
4230 			   wpas_dbus_interface_signals);
4231 
4232 	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
4233 		   wpa_s->dbus_new_path);
4234 	if (wpa_dbus_register_object_per_iface(ctrl_iface,
4235 					       wpa_s->dbus_new_path,
4236 					       wpa_s->ifname, obj_desc))
4237 		goto err;
4238 
4239 	wpas_dbus_signal_interface_added(wpa_s);
4240 
4241 	return 0;
4242 
4243 err:
4244 	os_free(wpa_s->dbus_new_path);
4245 	wpa_s->dbus_new_path = NULL;
4246 	free_dbus_object_desc(obj_desc);
4247 	return -1;
4248 }
4249 
4250 
4251 /**
4252  * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
4253  * @wpa_s: wpa_supplicant interface structure
4254  * Returns: 0 on success, -1 on failure
4255  */
wpas_dbus_unregister_interface(struct wpa_supplicant * wpa_s)4256 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
4257 {
4258 	struct wpas_dbus_priv *ctrl_iface;
4259 
4260 	/* Do nothing if the control interface is not turned on */
4261 	if (wpa_s == NULL || wpa_s->global == NULL)
4262 		return 0;
4263 	ctrl_iface = wpa_s->global->dbus;
4264 	if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
4265 		return 0;
4266 
4267 	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
4268 		   wpa_s->dbus_new_path);
4269 
4270 #ifdef CONFIG_AP
4271 	if (wpa_s->preq_notify_peer) {
4272 		wpas_dbus_unsubscribe_noc(ctrl_iface);
4273 		os_free(wpa_s->preq_notify_peer);
4274 		wpa_s->preq_notify_peer = NULL;
4275 	}
4276 #endif /* CONFIG_AP */
4277 
4278 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
4279 						 wpa_s->dbus_new_path))
4280 		return -1;
4281 
4282 	wpas_dbus_signal_interface_removed(wpa_s);
4283 
4284 	os_free(wpa_s->dbus_new_path);
4285 	wpa_s->dbus_new_path = NULL;
4286 
4287 	return 0;
4288 }
4289 
4290 #ifdef CONFIG_P2P
4291 
4292 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
4293 	{ "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4294 	  wpas_dbus_getter_p2p_peer_device_name,
4295 	  NULL,
4296 	  NULL
4297 	},
4298 	{ "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4299 	  wpas_dbus_getter_p2p_peer_manufacturer,
4300 	  NULL,
4301 	  NULL
4302 	},
4303 	{ "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4304 	  wpas_dbus_getter_p2p_peer_modelname,
4305 	  NULL,
4306 	  NULL
4307 	},
4308 	{ "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4309 	  wpas_dbus_getter_p2p_peer_modelnumber,
4310 	  NULL,
4311 	  NULL
4312 	},
4313 	{ "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
4314 	  wpas_dbus_getter_p2p_peer_serialnumber,
4315 	  NULL,
4316 	  NULL
4317 	},
4318 	{ "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4319 	  wpas_dbus_getter_p2p_peer_primary_device_type,
4320 	  NULL,
4321 	  NULL
4322 	},
4323 	{ "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
4324 	  wpas_dbus_getter_p2p_peer_config_method,
4325 	  NULL,
4326 	  NULL
4327 	},
4328 	{ "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
4329 	  wpas_dbus_getter_p2p_peer_level,
4330 	  NULL,
4331 	  NULL
4332 	},
4333 	{ "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4334 	  wpas_dbus_getter_p2p_peer_device_capability,
4335 	  NULL,
4336 	  NULL
4337 	},
4338 	{ "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
4339 	  wpas_dbus_getter_p2p_peer_group_capability,
4340 	  NULL,
4341 	  NULL
4342 	},
4343 	{ "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4344 	  wpas_dbus_getter_p2p_peer_secondary_device_types,
4345 	  NULL,
4346 	  NULL
4347 	},
4348 	{ "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
4349 	  wpas_dbus_getter_p2p_peer_vendor_extension,
4350 	  NULL,
4351 	  NULL
4352 	},
4353 	{ "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4354 	  wpas_dbus_getter_p2p_peer_ies,
4355 	  NULL,
4356 	  NULL
4357 	},
4358 	{ "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4359 	  wpas_dbus_getter_p2p_peer_device_address,
4360 	  NULL,
4361 	  NULL
4362 	},
4363 	{ "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
4364 	  wpas_dbus_getter_p2p_peer_groups,
4365 	  NULL,
4366 	  NULL
4367 	},
4368 	{ "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
4369 	  wpas_dbus_getter_p2p_peer_vsie,
4370 	  NULL,
4371 	  NULL
4372 	},
4373 	{ NULL, NULL, NULL, NULL, NULL, NULL }
4374 };
4375 
4376 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
4377 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
4378 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
4379 	  {
4380 		  { "properties", "a{sv}", ARG_OUT },
4381 		  END_ARGS
4382 	  }
4383 	},
4384 	{ NULL, NULL, { END_ARGS } }
4385 };
4386 
4387 /**
4388  * wpas_dbus_signal_peer - Send a peer related event signal
4389  * @wpa_s: %wpa_supplicant network interface data
4390  * @dev: peer device object
4391  * @interface: name of the interface emitting this signal.
4392  *	In case of peer objects, it would be emitted by either
4393  *	the "interface object" or by "peer objects"
4394  * @sig_name: signal name - DeviceFound
4395  * @properties: Whether to add a second argument with object properties
4396  *
4397  * Notify listeners about event related with p2p peer device
4398  */
wpas_dbus_signal_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr,const char * interface,const char * sig_name,dbus_bool_t properties)4399 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
4400 				  const u8 *dev_addr, const char *interface,
4401 				  const char *sig_name, dbus_bool_t properties)
4402 {
4403 	struct wpas_dbus_priv *iface;
4404 	DBusMessage *msg;
4405 	DBusMessageIter iter;
4406 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
4407 
4408 	if (wpa_s->p2p_mgmt)
4409 		wpa_s = wpa_s->parent;
4410 
4411 	iface = wpa_s->global->dbus;
4412 
4413 	/* Do nothing if the control interface is not turned on */
4414 	if (iface == NULL || !wpa_s->dbus_new_path)
4415 		return;
4416 
4417 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4418 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4419 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
4420 
4421 	msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
4422 				      sig_name);
4423 	if (msg == NULL)
4424 		return;
4425 
4426 	dbus_message_iter_init_append(msg, &iter);
4427 	path = peer_obj_path;
4428 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
4429 					    &path) ||
4430 	    (properties && !wpa_dbus_get_object_properties(
4431 		    iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
4432 		    &iter)))
4433 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
4434 	else
4435 		dbus_connection_send(iface->con, msg, NULL);
4436 
4437 	dbus_message_unref(msg);
4438 }
4439 
4440 
4441 /**
4442  * wpas_dbus_signal_peer_found - Send a peer found signal
4443  * @wpa_s: %wpa_supplicant network interface data
4444  * @dev_addr: Peer P2P Device Address
4445  *
4446  * Notify listeners about find a p2p peer device found
4447  */
wpas_dbus_signal_peer_device_found(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4448 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
4449 					const u8 *dev_addr)
4450 {
4451 	wpas_dbus_signal_peer(wpa_s, dev_addr,
4452 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4453 			      "DeviceFound", FALSE);
4454 
4455 	wpas_dbus_signal_peer(wpa_s, dev_addr,
4456 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4457 			      "DeviceFoundProperties", TRUE);
4458 }
4459 
4460 /**
4461  * wpas_dbus_signal_peer_lost - Send a peer lost signal
4462  * @wpa_s: %wpa_supplicant network interface data
4463  * @dev_addr: Peer P2P Device Address
4464  *
4465  * Notify listeners about lost a p2p peer device
4466  */
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4467 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
4468 				       const u8 *dev_addr)
4469 {
4470 	wpas_dbus_signal_peer(wpa_s, dev_addr,
4471 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4472 			      "DeviceLost", FALSE);
4473 }
4474 
4475 /**
4476  * wpas_dbus_register_peer - Register a discovered peer object with dbus
4477  * @wpa_s: wpa_supplicant interface structure
4478  * @dev_addr: P2P Device Address of the peer
4479  * Returns: 0 on success, -1 on failure
4480  *
4481  * Registers network representing object with dbus
4482  */
wpas_dbus_register_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4483 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
4484 {
4485 	struct wpas_dbus_priv *ctrl_iface;
4486 	struct wpa_dbus_object_desc *obj_desc;
4487 	struct peer_handler_args *arg;
4488 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4489 
4490 	/* Do nothing if the control interface is not turned on */
4491 	if (wpa_s == NULL || wpa_s->global == NULL)
4492 		return 0;
4493 
4494 	ctrl_iface = wpa_s->global->dbus;
4495 	if (ctrl_iface == NULL)
4496 		return 0;
4497 
4498 	wpa_s = wpa_s->parent->parent;
4499 	if (!wpa_s->dbus_new_path)
4500 		return 0;
4501 
4502 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4503 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4504 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
4505 
4506 	wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
4507 		   peer_obj_path);
4508 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4509 	if (!obj_desc) {
4510 		wpa_printf(MSG_ERROR,
4511 			   "Not enough memory to create object description");
4512 		goto err;
4513 	}
4514 
4515 	/* allocate memory for handlers arguments */
4516 	arg = os_zalloc(sizeof(struct peer_handler_args));
4517 	if (!arg) {
4518 		wpa_printf(MSG_ERROR,
4519 			   "Not enough memory to create arguments for method");
4520 		goto err;
4521 	}
4522 
4523 	arg->wpa_s = wpa_s;
4524 	os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
4525 
4526 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
4527 			   NULL,
4528 			   wpas_dbus_p2p_peer_properties,
4529 			   wpas_dbus_p2p_peer_signals);
4530 
4531 	if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
4532 					       wpa_s->ifname, obj_desc))
4533 		goto err;
4534 
4535 	return 0;
4536 
4537 err:
4538 	free_dbus_object_desc(obj_desc);
4539 	return -1;
4540 }
4541 
4542 /**
4543  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
4544  * @wpa_s: wpa_supplicant interface structure
4545  * @dev_addr: p2p device addr
4546  * Returns: 0 on success, -1 on failure
4547  *
4548  * Registers network representing object with dbus
4549  */
wpas_dbus_unregister_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4550 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
4551 				  const u8 *dev_addr)
4552 {
4553 	struct wpas_dbus_priv *ctrl_iface;
4554 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4555 	int ret;
4556 
4557 	/* Do nothing if the control interface is not turned on */
4558 	if (wpa_s == NULL || wpa_s->global == NULL)
4559 		return 0;
4560 
4561 	wpa_s = wpa_s->parent->parent;
4562 	if (!wpa_s->dbus_new_path)
4563 		return 0;
4564 
4565 	ctrl_iface = wpa_s->global->dbus;
4566 	if (ctrl_iface == NULL)
4567 		return 0;
4568 
4569 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4570 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4571 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
4572 
4573 	wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
4574 		   peer_obj_path);
4575 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
4576 
4577 	return ret;
4578 }
4579 
4580 
4581 /**
4582  * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
4583  * @wpa_s: %wpa_supplicant network interface data
4584  *
4585  * Notify listeners about P2P Find stopped
4586  */
wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant * wpa_s)4587 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
4588 {
4589 	struct wpas_dbus_priv *iface;
4590 	DBusMessage *msg;
4591 
4592 	iface = wpa_s->global->dbus;
4593 
4594 	/* Do nothing if the control interface is not turned on */
4595 	if (iface == NULL)
4596 		return;
4597 
4598 	if (wpa_s->p2p_mgmt)
4599 		wpa_s = wpa_s->parent;
4600 
4601 	if (!wpa_s->dbus_new_path)
4602 		return;
4603 
4604 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4605 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4606 				      "FindStopped");
4607 	if (msg == NULL)
4608 		return;
4609 
4610 	dbus_connection_send(iface->con, msg, NULL);
4611 
4612 	dbus_message_unref(msg);
4613 }
4614 
4615 
4616 /**
4617  * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
4618  * @wpa_s: %wpa_supplicant network interface data
4619  * @dev_addr: P2P Device Address
4620  *
4621  * Notify listeners about peer Groups property changes.
4622  */
wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4623 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
4624 					  const u8 *dev_addr)
4625 {
4626 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4627 
4628 	if (wpa_s->p2p_mgmt)
4629 		wpa_s = wpa_s->parent;
4630 
4631 	if (!wpa_s->dbus_new_path)
4632 		return;
4633 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4634 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4635 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
4636 
4637 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
4638 				       WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
4639 }
4640 
4641 
4642 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
4643 	{ "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
4644 	  wpas_dbus_getter_p2p_group_members,
4645 	  NULL,
4646 	  NULL
4647 	},
4648 	{ "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
4649 	  wpas_dbus_getter_p2p_group,
4650 	  NULL,
4651 	  NULL
4652 	},
4653 	{ "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4654 	  wpas_dbus_getter_p2p_role,
4655 	  NULL,
4656 	  NULL
4657 	},
4658 	{ "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4659 	  wpas_dbus_getter_p2p_group_ssid,
4660 	  NULL,
4661 	  NULL
4662 	},
4663 	{ "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4664 	  wpas_dbus_getter_p2p_group_bssid,
4665 	  NULL,
4666 	  NULL
4667 	},
4668 	{ "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
4669 	  wpas_dbus_getter_p2p_group_frequency,
4670 	  NULL,
4671 	  NULL
4672 	},
4673 	{ "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4674 	  wpas_dbus_getter_p2p_group_passphrase,
4675 	  NULL,
4676 	  NULL
4677 	},
4678 	{ "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4679 	  wpas_dbus_getter_p2p_group_psk,
4680 	  NULL,
4681 	  NULL
4682 	},
4683 	{ "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
4684 	  wpas_dbus_getter_p2p_group_vendor_ext,
4685 	  wpas_dbus_setter_p2p_group_vendor_ext,
4686 	  NULL
4687 	},
4688 	{ NULL, NULL, NULL, NULL, NULL, NULL }
4689 };
4690 
4691 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
4692 	{ "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4693 	  {
4694 		  { "peer", "o", ARG_OUT },
4695 		  END_ARGS
4696 	  }
4697 	},
4698 	{ "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4699 	  {
4700 		  { "peer", "o", ARG_OUT },
4701 		  END_ARGS
4702 	  }
4703 	},
4704 	{ NULL, NULL, { END_ARGS } }
4705 };
4706 
4707 /**
4708  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
4709  * @wpa_s: wpa_supplicant interface structure
4710  * @ssid: SSID struct
4711  * Returns: 0 on success, -1 on failure
4712  *
4713  * Registers p2p group representing object with dbus
4714  */
wpas_dbus_register_p2p_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)4715 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
4716 				  struct wpa_ssid *ssid)
4717 {
4718 	struct wpas_dbus_priv *ctrl_iface;
4719 	struct wpa_dbus_object_desc *obj_desc;
4720 	char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4721 
4722 	/* Do nothing if the control interface is not turned on */
4723 	if (wpa_s == NULL || wpa_s->global == NULL)
4724 		return;
4725 
4726 	ctrl_iface = wpa_s->global->dbus;
4727 	if (ctrl_iface == NULL)
4728 		return;
4729 
4730 	if (wpa_s->dbus_groupobj_path) {
4731 		wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
4732 			   __func__, wpa_s->dbus_groupobj_path);
4733 		return;
4734 	}
4735 
4736 	if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
4737 		return;
4738 
4739 	wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
4740 	if (wpa_s->dbus_groupobj_path == NULL)
4741 		return;
4742 
4743 	wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
4744 		   group_obj_path);
4745 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4746 	if (!obj_desc) {
4747 		wpa_printf(MSG_ERROR,
4748 			   "Not enough memory to create object description");
4749 		goto err;
4750 	}
4751 
4752 	wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
4753 			   wpas_dbus_p2p_group_properties,
4754 			   wpas_dbus_p2p_group_signals);
4755 
4756 	if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
4757 					       wpa_s->ifname, obj_desc))
4758 		goto err;
4759 
4760 	return;
4761 
4762 err:
4763 	if (wpa_s->dbus_groupobj_path) {
4764 		os_free(wpa_s->dbus_groupobj_path);
4765 		wpa_s->dbus_groupobj_path = NULL;
4766 	}
4767 
4768 	free_dbus_object_desc(obj_desc);
4769 }
4770 
4771 /**
4772  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
4773  * @wpa_s: wpa_supplicant interface structure
4774  * @ssid: network name of the p2p group started
4775  */
wpas_dbus_unregister_p2p_group(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid)4776 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
4777 				    const struct wpa_ssid *ssid)
4778 {
4779 	struct wpas_dbus_priv *ctrl_iface;
4780 
4781 	/* Do nothing if the control interface is not turned on */
4782 	if (wpa_s == NULL || wpa_s->global == NULL)
4783 		return;
4784 
4785 	if (wpa_s->p2p_mgmt)
4786 		wpa_s = wpa_s->parent;
4787 
4788 	ctrl_iface = wpa_s->global->dbus;
4789 	if (ctrl_iface == NULL)
4790 		return;
4791 
4792 	if (!wpa_s->dbus_groupobj_path) {
4793 		wpa_printf(MSG_DEBUG,
4794 			   "%s: Group object '%s' already unregistered",
4795 			   __func__, wpa_s->dbus_groupobj_path);
4796 		return;
4797 	}
4798 
4799 	peer_groups_changed(wpa_s);
4800 
4801 	wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
4802 		   wpa_s->dbus_groupobj_path);
4803 
4804 	wpa_dbus_unregister_object_per_iface(ctrl_iface,
4805 					     wpa_s->dbus_groupobj_path);
4806 
4807 	os_free(wpa_s->dbus_groupobj_path);
4808 	wpa_s->dbus_groupobj_path = NULL;
4809 }
4810 
4811 static const struct wpa_dbus_property_desc
4812 	wpas_dbus_persistent_group_properties[] = {
4813 	{ "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
4814 	  wpas_dbus_getter_persistent_group_properties,
4815 	  wpas_dbus_setter_persistent_group_properties,
4816 	  NULL
4817 	},
4818 	{ NULL, NULL, NULL, NULL, NULL, NULL }
4819 };
4820 
4821 /* No signals intended for persistent group objects */
4822 
4823 /**
4824  * wpas_dbus_register_persistent_group - Register a configured(saved)
4825  *	persistent group with dbus
4826  * @wpa_s: wpa_supplicant interface structure
4827  * @ssid: persistent group (still represented as a network within wpa)
4828  *	  configuration data
4829  * Returns: 0 on success, -1 on failure
4830  *
4831  * Registers a persistent group representing object with dbus.
4832  */
wpas_dbus_register_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)4833 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
4834 					struct wpa_ssid *ssid)
4835 {
4836 	struct wpas_dbus_priv *ctrl_iface;
4837 	struct wpa_dbus_object_desc *obj_desc;
4838 	struct network_handler_args *arg;
4839 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4840 
4841 	/* Do nothing if the control interface is not turned on */
4842 	if (wpa_s == NULL || wpa_s->global == NULL)
4843 		return 0;
4844 	wpa_s = wpa_s->parent->parent;
4845 	if (!wpa_s->dbus_new_path)
4846 		return 0;
4847 
4848 	/* Make sure ssid is a persistent group */
4849 	if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
4850 		return -1; /* should we return w/o complaining? */
4851 
4852 	if (wpa_s->p2p_mgmt)
4853 		wpa_s = wpa_s->parent;
4854 
4855 	ctrl_iface = wpa_s->global->dbus;
4856 	if (ctrl_iface == NULL)
4857 		return 0;
4858 
4859 	/*
4860 	 * Intentionally not coming up with different numbering scheme
4861 	 * for persistent groups.
4862 	 */
4863 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4864 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
4865 		    wpa_s->dbus_new_path, ssid->id);
4866 
4867 	wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
4868 		   pgrp_obj_path);
4869 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4870 	if (!obj_desc) {
4871 		wpa_printf(MSG_ERROR,
4872 			   "dbus: Not enough memory to create object description");
4873 		goto err;
4874 	}
4875 
4876 	/*
4877 	 * Reusing the same context structure as that for networks
4878 	 * since these are represented using same data structure.
4879 	 */
4880 	/* allocate memory for handlers arguments */
4881 	arg = os_zalloc(sizeof(struct network_handler_args));
4882 	if (!arg) {
4883 		wpa_printf(MSG_ERROR,
4884 			   "dbus: Not enough memory to create arguments for method");
4885 		goto err;
4886 	}
4887 
4888 	arg->wpa_s = wpa_s;
4889 	arg->ssid = ssid;
4890 
4891 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
4892 			   wpas_dbus_persistent_group_properties,
4893 			   NULL);
4894 
4895 	if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
4896 					       wpa_s->ifname, obj_desc))
4897 		goto err;
4898 
4899 	wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
4900 
4901 	return 0;
4902 
4903 err:
4904 	free_dbus_object_desc(obj_desc);
4905 	return -1;
4906 }
4907 
4908 
4909 /**
4910  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
4911  *	from dbus
4912  * @wpa_s: wpa_supplicant interface structure
4913  * @nid: network id
4914  * Returns: 0 on success, -1 on failure
4915  *
4916  * Unregisters persistent group representing object from dbus
4917  *
4918  * NOTE: There is a slight issue with the semantics here. While the
4919  * implementation simply means the persistent group is unloaded from memory,
4920  * it should not get interpreted as the group is actually being erased/removed
4921  * from persistent storage as well.
4922  */
wpas_dbus_unregister_persistent_group(struct wpa_supplicant * wpa_s,int nid)4923 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
4924 					  int nid)
4925 {
4926 	struct wpas_dbus_priv *ctrl_iface;
4927 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4928 	int ret;
4929 
4930 	/* Do nothing if the control interface is not turned on */
4931 	if (wpa_s == NULL || wpa_s->global == NULL)
4932 		return 0;
4933 
4934 	wpa_s = wpa_s->parent->parent;
4935 
4936 	ctrl_iface = wpa_s->global->dbus;
4937 	if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
4938 		return 0;
4939 
4940 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4941 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
4942 		    wpa_s->dbus_new_path, nid);
4943 
4944 	wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
4945 		   pgrp_obj_path);
4946 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
4947 
4948 	if (!ret)
4949 		wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
4950 
4951 	return ret;
4952 }
4953 
4954 #endif /* CONFIG_P2P */
4955