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