• 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  * @client: this device is P2P client
1258  * @persistent: 0 - non persistent group, 1 - persistent group
1259  * @ip: When group role is client, it contains local IP address, netmask, and
1260  *	GO's IP address, if assigned; otherwise, NULL
1261  */
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant * wpa_s,int client,int persistent,const u8 * ip)1262 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
1263 					int client, int persistent,
1264 					const u8 *ip)
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_bool(&dict_iter, "persistent", persistent) ||
1304 	    !wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1305 					      wpa_s->dbus_groupobj_path) ||
1306 	    (ip &&
1307 	     (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr",
1308 					       (char *) ip, 4) ||
1309 	      !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask",
1310 					       (char *) ip + 4, 4) ||
1311 	      !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo",
1312 					       (char *) ip + 8, 4))) ||
1313 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
1314 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1315 	} else {
1316 		dbus_connection_send(iface->con, msg, NULL);
1317 		if (client)
1318 			peer_groups_changed(wpa_s);
1319 	}
1320 	dbus_message_unref(msg);
1321 }
1322 
1323 
1324 /**
1325  * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal
1326  * @wpa_s: %wpa_supplicant network interface data
1327  * @res: Result of the GO Neg Request
1328  */
wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant * wpa_s,struct p2p_go_neg_results * res)1329 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
1330 				      struct p2p_go_neg_results *res)
1331 {
1332 	DBusMessage *msg;
1333 	DBusMessageIter iter, dict_iter;
1334 	DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
1335 	struct wpas_dbus_priv *iface;
1336 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1337 	dbus_int32_t freqs[P2P_MAX_CHANNELS];
1338 	dbus_int32_t *f_array = freqs;
1339 
1340 
1341 	iface = wpa_s->global->dbus;
1342 
1343 	if (wpa_s->p2p_mgmt)
1344 		wpa_s = wpa_s->parent;
1345 
1346 	os_memset(freqs, 0, sizeof(freqs));
1347 	/* Do nothing if the control interface is not turned on */
1348 	if (iface == NULL || !wpa_s->dbus_new_path)
1349 		return;
1350 
1351 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1352 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1353 		    wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
1354 	path = peer_obj_path;
1355 
1356 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1357 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1358 				      res->status ? "GONegotiationFailure" :
1359 						    "GONegotiationSuccess");
1360 	if (msg == NULL)
1361 		return;
1362 
1363 	dbus_message_iter_init_append(msg, &iter);
1364 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1365 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1366 					      path) ||
1367 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
1368 		goto err;
1369 
1370 	if (!res->status) {
1371 		int i = 0;
1372 		int freq_list_num = 0;
1373 
1374 		if ((res->role_go &&
1375 		     !wpa_dbus_dict_append_string(&dict_iter, "passphrase",
1376 						  res->passphrase)) ||
1377 		    !wpa_dbus_dict_append_string(&dict_iter, "role_go",
1378 						 res->role_go ? "GO" :
1379 						 "client") ||
1380 		    !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
1381 						res->freq) ||
1382 		    !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
1383 						     (const char *) res->ssid,
1384 						     res->ssid_len) ||
1385 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
1386 						     "peer_device_addr",
1387 						     (const char *)
1388 						     res->peer_device_addr,
1389 						     ETH_ALEN) ||
1390 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
1391 						     "peer_interface_addr",
1392 						     (const char *)
1393 						     res->peer_interface_addr,
1394 						     ETH_ALEN) ||
1395 		    !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
1396 						 p2p_wps_method_text(
1397 							 res->wps_method)))
1398 			goto err;
1399 
1400 		for (i = 0; i < P2P_MAX_CHANNELS; i++) {
1401 			if (res->freq_list[i]) {
1402 				freqs[i] = res->freq_list[i];
1403 				freq_list_num++;
1404 			}
1405 		}
1406 
1407 		if (!wpa_dbus_dict_begin_array(&dict_iter,
1408 					       "frequency_list",
1409 					       DBUS_TYPE_INT32_AS_STRING,
1410 					       &iter_dict_entry,
1411 					       &iter_dict_val,
1412 					       &iter_dict_array) ||
1413 		    !dbus_message_iter_append_fixed_array(&iter_dict_array,
1414 							  DBUS_TYPE_INT32,
1415 							  &f_array,
1416 							  freq_list_num) ||
1417 		    !wpa_dbus_dict_end_array(&dict_iter,
1418 					     &iter_dict_entry,
1419 					     &iter_dict_val,
1420 					     &iter_dict_array) ||
1421 		    !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
1422 						res->persistent_group) ||
1423 		    !wpa_dbus_dict_append_uint32(&dict_iter,
1424 						 "peer_config_timeout",
1425 						 res->peer_config_timeout))
1426 			goto err;
1427 	}
1428 
1429 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1430 		goto err;
1431 
1432 	dbus_connection_send(iface->con, msg, NULL);
1433 err:
1434 	dbus_message_unref(msg);
1435 }
1436 
1437 
1438 /**
1439  * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal
1440  * @wpa_s: %wpa_supplicant network interface data
1441  * @status: Status of invitation process
1442  * @bssid: Basic Service Set Identifier
1443  */
wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant * wpa_s,int status,const u8 * bssid)1444 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1445 					    int status, const u8 *bssid)
1446 {
1447 	DBusMessage *msg;
1448 	DBusMessageIter iter, dict_iter;
1449 	struct wpas_dbus_priv *iface;
1450 
1451 	wpa_printf(MSG_DEBUG, "%s", __func__);
1452 
1453 	iface = wpa_s->global->dbus;
1454 	/* Do nothing if the control interface is not turned on */
1455 	if (iface == NULL)
1456 		return;
1457 
1458 	if (wpa_s->p2p_mgmt)
1459 		wpa_s = wpa_s->parent;
1460 	if (!wpa_s->dbus_new_path)
1461 		return;
1462 
1463 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1464 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1465 				      "InvitationResult");
1466 
1467 	if (msg == NULL)
1468 		return;
1469 
1470 	dbus_message_iter_init_append(msg, &iter);
1471 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1472 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", status) ||
1473 	    (bssid &&
1474 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1475 					      (const char *) bssid,
1476 					      ETH_ALEN)) ||
1477 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1478 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1479 	else
1480 		dbus_connection_send(iface->con, msg, NULL);
1481 	dbus_message_unref(msg);
1482 }
1483 
1484 
1485 /**
1486  *
1487  * Method to emit a signal for a peer joining the group.
1488  * The signal will carry path to the group member object
1489  * constructed using p2p i/f addr used for connecting.
1490  *
1491  * @wpa_s: %wpa_supplicant network interface data
1492  * @peer_addr: P2P Device Address of the peer joining the group
1493  */
wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1494 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1495 				      const u8 *peer_addr)
1496 {
1497 	struct wpas_dbus_priv *iface;
1498 	DBusMessage *msg;
1499 	DBusMessageIter iter;
1500 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1501 	struct wpa_supplicant *parent;
1502 
1503 	iface = wpa_s->global->dbus;
1504 
1505 	/* Do nothing if the control interface is not turned on */
1506 	if (iface == NULL)
1507 		return;
1508 
1509 	if (!wpa_s->dbus_groupobj_path)
1510 		return;
1511 
1512 	parent = wpa_s->parent;
1513 	if (parent->p2p_mgmt)
1514 		parent = parent->parent;
1515 	if (!parent->dbus_new_path)
1516 		return;
1517 
1518 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1519 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1520 			COMPACT_MACSTR,
1521 			parent->dbus_new_path, MAC2STR(peer_addr));
1522 
1523 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1524 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1525 				      "PeerJoined");
1526 	if (msg == NULL)
1527 		return;
1528 
1529 	dbus_message_iter_init_append(msg, &iter);
1530 	path = peer_obj_path;
1531 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1532 					    &path)) {
1533 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1534 	} else {
1535 		dbus_connection_send(iface->con, msg, NULL);
1536 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1537 	}
1538 	dbus_message_unref(msg);
1539 }
1540 
1541 
1542 /**
1543  *
1544  * Method to emit a signal for a peer disconnecting the group.
1545  * The signal will carry path to the group member object
1546  * constructed using the P2P Device Address of the peer.
1547  *
1548  * @wpa_s: %wpa_supplicant network interface data
1549  * @peer_addr: P2P Device Address of the peer joining the group
1550  */
wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * peer_addr)1551 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1552 					    const u8 *peer_addr)
1553 {
1554 	struct wpas_dbus_priv *iface;
1555 	DBusMessage *msg;
1556 	DBusMessageIter iter;
1557 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1558 	struct wpa_supplicant *parent;
1559 
1560 	iface = wpa_s->global->dbus;
1561 
1562 	/* Do nothing if the control interface is not turned on */
1563 	if (iface == NULL)
1564 		return;
1565 
1566 	if (!wpa_s->dbus_groupobj_path)
1567 		return;
1568 
1569 	parent = wpa_s->parent;
1570 	if (parent->p2p_mgmt)
1571 		parent = parent->parent;
1572 	if (!parent->dbus_new_path)
1573 		return;
1574 
1575 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1576 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1577 			COMPACT_MACSTR,
1578 			parent->dbus_new_path, MAC2STR(peer_addr));
1579 
1580 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1581 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1582 				      "PeerDisconnected");
1583 	if (msg == NULL)
1584 		return;
1585 
1586 	dbus_message_iter_init_append(msg, &iter);
1587 	path = peer_obj_path;
1588 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1589 					    &path)) {
1590 		wpa_printf(MSG_ERROR,
1591 			   "dbus: Failed to construct PeerDisconnected signal");
1592 	} else {
1593 		dbus_connection_send(iface->con, msg, NULL);
1594 		wpas_dbus_signal_peer_groups_changed(parent, peer_addr);
1595 	}
1596 	dbus_message_unref(msg);
1597 }
1598 
1599 
1600 /**
1601  *
1602  * Method to emit a signal for a service discovery request.
1603  * The signal will carry station address, frequency, dialog token,
1604  * update indicator and it tlvs
1605  *
1606  * @wpa_s: %wpa_supplicant network interface data
1607  * @sa: station addr (p2p i/f) of the peer
1608  * @dialog_token: service discovery request dialog token
1609  * @update_indic: service discovery request update indicator
1610  * @tlvs: service discovery request genrated byte array of tlvs
1611  * @tlvs_len: service discovery request tlvs length
1612  */
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)1613 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
1614 				     int freq, const u8 *sa, u8 dialog_token,
1615 				     u16 update_indic, const u8 *tlvs,
1616 				     size_t tlvs_len)
1617 {
1618 	DBusMessage *msg;
1619 	DBusMessageIter iter, dict_iter;
1620 	struct wpas_dbus_priv *iface;
1621 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1622 
1623 	iface = wpa_s->global->dbus;
1624 
1625 	/* Do nothing if the control interface is not turned on */
1626 	if (iface == NULL)
1627 		return;
1628 
1629 	if (wpa_s->p2p_mgmt)
1630 		wpa_s = wpa_s->parent;
1631 	if (!wpa_s->dbus_new_path)
1632 		return;
1633 
1634 	/* Check if this is a known peer */
1635 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
1636 		return;
1637 
1638 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1639 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1640 				      "ServiceDiscoveryRequest");
1641 	if (msg == NULL)
1642 		return;
1643 
1644 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1645 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1646 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1647 
1648 	path = peer_obj_path;
1649 
1650 	dbus_message_iter_init_append(msg, &iter);
1651 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1652 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1653 					      path) ||
1654 	    !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
1655 	    !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
1656 					dialog_token) ||
1657 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1658 					 update_indic) ||
1659 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1660 					     (const char *) tlvs,
1661 					     tlvs_len) ||
1662 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1663 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1664 	else
1665 		dbus_connection_send(iface->con, msg, NULL);
1666 	dbus_message_unref(msg);
1667 }
1668 
1669 
1670 /**
1671  *
1672  * Method to emit a signal for a service discovery response.
1673  * The signal will carry station address, update indicator and it
1674  * tlvs
1675  *
1676  * @wpa_s: %wpa_supplicant network interface data
1677  * @sa: station addr (p2p i/f) of the peer
1678  * @update_indic: service discovery request update indicator
1679  * @tlvs: service discovery request genrated byte array of tlvs
1680  * @tlvs_len: service discovery request tlvs length
1681  */
wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant * wpa_s,const u8 * sa,u16 update_indic,const u8 * tlvs,size_t tlvs_len)1682 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
1683 				      const u8 *sa, u16 update_indic,
1684 				      const u8 *tlvs, size_t tlvs_len)
1685 {
1686 	DBusMessage *msg;
1687 	DBusMessageIter iter, dict_iter;
1688 	struct wpas_dbus_priv *iface;
1689 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1690 
1691 	iface = wpa_s->global->dbus;
1692 
1693 	/* Do nothing if the control interface is not turned on */
1694 	if (iface == NULL)
1695 		return;
1696 
1697 	if (wpa_s->p2p_mgmt)
1698 		wpa_s = wpa_s->parent;
1699 	if (!wpa_s->dbus_new_path)
1700 		return;
1701 
1702 	/* Check if this is a known peer */
1703 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
1704 		return;
1705 
1706 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1707 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1708 				      "ServiceDiscoveryResponse");
1709 	if (msg == NULL)
1710 		return;
1711 
1712 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1713 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1714 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1715 
1716 	path = peer_obj_path;
1717 
1718 	dbus_message_iter_init_append(msg, &iter);
1719 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1720 	    !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1721 					      path) ||
1722 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1723 					 update_indic) ||
1724 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1725 					     (const char *) tlvs,
1726 					     tlvs_len) ||
1727 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1728 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1729 	else
1730 		dbus_connection_send(iface->con, msg, NULL);
1731 	dbus_message_unref(msg);
1732 }
1733 
1734 
1735 /**
1736  * wpas_dbus_signal_persistent_group - Send a persistent group related
1737  *	event signal
1738  * @wpa_s: %wpa_supplicant network interface data
1739  * @id: new persistent group id
1740  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
1741  * @properties: determines if add second argument with object properties
1742  *
1743  * Notify listeners about an event related to persistent groups.
1744  */
wpas_dbus_signal_persistent_group(struct wpa_supplicant * wpa_s,int id,const char * sig_name,int properties)1745 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
1746 					      int id, const char *sig_name,
1747 					      int properties)
1748 {
1749 	struct wpas_dbus_priv *iface;
1750 	DBusMessage *msg;
1751 	DBusMessageIter iter;
1752 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1753 
1754 	iface = wpa_s->global->dbus;
1755 
1756 	/* Do nothing if the control interface is not turned on */
1757 	if (iface == NULL)
1758 		return;
1759 
1760 	if (wpa_s->p2p_mgmt)
1761 		wpa_s = wpa_s->parent;
1762 	if (!wpa_s->dbus_new_path)
1763 		return;
1764 
1765 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1766 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
1767 		    wpa_s->dbus_new_path, id);
1768 
1769 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1770 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1771 				      sig_name);
1772 	if (msg == NULL)
1773 		return;
1774 
1775 	dbus_message_iter_init_append(msg, &iter);
1776 	path = pgrp_obj_path;
1777 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1778 					    &path) ||
1779 	    (properties &&
1780 	     !wpa_dbus_get_object_properties(
1781 		     iface, pgrp_obj_path,
1782 		     WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter)))
1783 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1784 	else
1785 		dbus_connection_send(iface->con, msg, NULL);
1786 
1787 	dbus_message_unref(msg);
1788 }
1789 
1790 
1791 /**
1792  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
1793  *	added signal
1794  * @wpa_s: %wpa_supplicant network interface data
1795  * @id: new persistent group id
1796  *
1797  * Notify listeners about addition of a new persistent group.
1798  */
wpas_dbus_signal_persistent_group_added(struct wpa_supplicant * wpa_s,int id)1799 static void wpas_dbus_signal_persistent_group_added(
1800 	struct wpa_supplicant *wpa_s, int id)
1801 {
1802 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
1803 					  TRUE);
1804 }
1805 
1806 
1807 /**
1808  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
1809  *	removed signal
1810  * @wpa_s: %wpa_supplicant network interface data
1811  * @id: persistent group id
1812  *
1813  * Notify listeners about removal of a persistent group.
1814  */
wpas_dbus_signal_persistent_group_removed(struct wpa_supplicant * wpa_s,int id)1815 static void wpas_dbus_signal_persistent_group_removed(
1816 	struct wpa_supplicant *wpa_s, int id)
1817 {
1818 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
1819 					  FALSE);
1820 }
1821 
1822 
1823 /**
1824  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
1825  * @wpa_s: %wpa_supplicant network interface data
1826  * @fail: WPS failure information
1827  *
1828  * Sends Event dbus signal with name "fail" and dictionary containing
1829  * "msg" field with fail message number (int32) as arguments
1830  */
wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant * wpa_s,struct wps_event_fail * fail)1831 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
1832 				     struct wps_event_fail *fail)
1833 {
1834 
1835 	DBusMessage *msg;
1836 	DBusMessageIter iter, dict_iter;
1837 	struct wpas_dbus_priv *iface;
1838 	char *key = "fail";
1839 
1840 	iface = wpa_s->global->dbus;
1841 
1842 	/* Do nothing if the control interface is not turned on */
1843 	if (iface == NULL)
1844 		return;
1845 
1846 	if (wpa_s->p2p_mgmt)
1847 		wpa_s = wpa_s->parent;
1848 
1849 	if (!wpa_s->dbus_new_path)
1850 		return;
1851 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1852 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1853 				      "WpsFailed");
1854 	if (msg == NULL)
1855 		return;
1856 
1857 	dbus_message_iter_init_append(msg, &iter);
1858 
1859 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
1860 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1861 	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
1862 	    !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
1863 					fail->config_error) ||
1864 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1865 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1866 	else
1867 		dbus_connection_send(iface->con, msg, NULL);
1868 
1869 	dbus_message_unref(msg);
1870 }
1871 
1872 
1873 /**
1874  * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event
1875  * @wpa_s: %wpa_supplicant network interface data
1876  * @reason: indicates the reason code for group formation failure
1877  *
1878  * Sends Event dbus signal and string reason code when available.
1879  */
wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant * wpa_s,const char * reason)1880 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
1881 						  const char *reason)
1882 {
1883 	DBusMessage *msg;
1884 	struct wpas_dbus_priv *iface;
1885 
1886 	iface = wpa_s->global->dbus;
1887 
1888 	/* Do nothing if the control interface is not turned on */
1889 	if (iface == NULL)
1890 		return;
1891 
1892 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1893 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1894 				      "GroupFormationFailure");
1895 	if (msg == NULL)
1896 		return;
1897 
1898 	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason,
1899 				     DBUS_TYPE_INVALID))
1900 		dbus_connection_send(iface->con, msg, NULL);
1901 	else
1902 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1903 
1904 	dbus_message_unref(msg);
1905 }
1906 
1907 
1908 /**
1909  * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal
1910  * @wpa_s: %wpa_supplicant network interface data
1911  * @sa: Source address of the Invitation Request
1912  * @dev_add: GO Device Address
1913  * @bssid: P2P Group BSSID or %NULL if not received
1914  * @id: Persistent group id or %0 if not persistent group
1915  * @op_freq: Operating frequency for the group
1916  */
1917 
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)1918 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s,
1919 					      const u8 *sa, const u8 *dev_addr,
1920 					      const u8 *bssid, int id,
1921 					      int op_freq)
1922 {
1923 	DBusMessage *msg;
1924 	DBusMessageIter iter, dict_iter;
1925 	struct wpas_dbus_priv *iface;
1926 
1927 	iface = wpa_s->global->dbus;
1928 
1929 	/* Do nothing if the control interface is not turned on */
1930 	if (iface == NULL)
1931 		return;
1932 
1933 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1934 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1935 				      "InvitationReceived");
1936 	if (msg == NULL)
1937 		return;
1938 
1939 	dbus_message_iter_init_append(msg, &iter);
1940 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1941 	    (sa &&
1942 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "sa",
1943 					      (const char *) sa, ETH_ALEN)) ||
1944 	    (dev_addr &&
1945 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr",
1946 					      (const char *) dev_addr,
1947 					      ETH_ALEN)) ||
1948 	    (bssid &&
1949 	     !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid",
1950 					      (const char *) bssid,
1951 					      ETH_ALEN)) ||
1952 	    (id &&
1953 	     !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) ||
1954 	    !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) ||
1955 	    !wpa_dbus_dict_close_write(&iter, &dict_iter)) {
1956 		dbus_message_unref(msg);
1957 		return;
1958 	}
1959 
1960 	dbus_connection_send(iface->con, msg, NULL);
1961 	dbus_message_unref(msg);
1962 }
1963 
1964 
1965 #endif /* CONFIG_P2P */
1966 
1967 
1968 /**
1969  * wpas_dbus_signal_prop_changed - Signals change of property
1970  * @wpa_s: %wpa_supplicant network interface data
1971  * @property: indicates which property has changed
1972  *
1973  * Sends PropertyChanged signals with path, interface and arguments
1974  * depending on which property has changed.
1975  */
wpas_dbus_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_prop property)1976 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
1977 				   enum wpas_dbus_prop property)
1978 {
1979 	char *prop;
1980 	dbus_bool_t flush;
1981 
1982 	if (wpa_s->dbus_new_path == NULL)
1983 		return; /* Skip signal since D-Bus setup is not yet ready */
1984 
1985 	flush = FALSE;
1986 	switch (property) {
1987 	case WPAS_DBUS_PROP_AP_SCAN:
1988 		prop = "ApScan";
1989 		break;
1990 #ifdef CONFIG_IEEE80211W
1991 	case WPAS_DBUS_PROP_PMF:
1992 		prop = "Pmf";
1993 		break;
1994 #endif /* CONFIG_IEEE80211W */
1995 	case WPAS_DBUS_PROP_SCANNING:
1996 		prop = "Scanning";
1997 		break;
1998 	case WPAS_DBUS_PROP_STATE:
1999 		prop = "State";
2000 		break;
2001 	case WPAS_DBUS_PROP_CURRENT_BSS:
2002 		prop = "CurrentBSS";
2003 		break;
2004 	case WPAS_DBUS_PROP_CURRENT_NETWORK:
2005 		prop = "CurrentNetwork";
2006 		break;
2007 	case WPAS_DBUS_PROP_BSSS:
2008 		prop = "BSSs";
2009 		break;
2010 	case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
2011 		prop = "CurrentAuthMode";
2012 		break;
2013 	case WPAS_DBUS_PROP_DISCONNECT_REASON:
2014 		prop = "DisconnectReason";
2015 		flush = TRUE;
2016 		break;
2017 	case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
2018 		prop = "AssocStatusCode";
2019 		flush = TRUE;
2020 		break;
2021 	default:
2022 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2023 			   __func__, property);
2024 		return;
2025 	}
2026 
2027 	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
2028 				       wpa_s->dbus_new_path,
2029 				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
2030 	if (flush) {
2031 		wpa_dbus_flush_object_changed_properties(
2032 			wpa_s->global->dbus->con, wpa_s->dbus_new_path);
2033 	}
2034 }
2035 
2036 
2037 /**
2038  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
2039  * @wpa_s: %wpa_supplicant network interface data
2040  * @property: indicates which property has changed
2041  * @id: unique BSS identifier
2042  *
2043  * Sends PropertyChanged signals with path, interface, and arguments depending
2044  * on which property has changed.
2045  */
wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,unsigned int id)2046 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
2047 				       enum wpas_dbus_bss_prop property,
2048 				       unsigned int id)
2049 {
2050 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
2051 	char *prop;
2052 
2053 	if (!wpa_s->dbus_new_path)
2054 		return;
2055 
2056 	switch (property) {
2057 	case WPAS_DBUS_BSS_PROP_SIGNAL:
2058 		prop = "Signal";
2059 		break;
2060 	case WPAS_DBUS_BSS_PROP_FREQ:
2061 		prop = "Frequency";
2062 		break;
2063 	case WPAS_DBUS_BSS_PROP_MODE:
2064 		prop = "Mode";
2065 		break;
2066 	case WPAS_DBUS_BSS_PROP_PRIVACY:
2067 		prop = "Privacy";
2068 		break;
2069 	case WPAS_DBUS_BSS_PROP_RATES:
2070 		prop = "Rates";
2071 		break;
2072 	case WPAS_DBUS_BSS_PROP_WPA:
2073 		prop = "WPA";
2074 		break;
2075 	case WPAS_DBUS_BSS_PROP_RSN:
2076 		prop = "RSN";
2077 		break;
2078 	case WPAS_DBUS_BSS_PROP_WPS:
2079 		prop = "WPS";
2080 		break;
2081 	case WPAS_DBUS_BSS_PROP_IES:
2082 		prop = "IEs";
2083 		break;
2084 	case WPAS_DBUS_BSS_PROP_AGE:
2085 		prop = "Age";
2086 		break;
2087 	default:
2088 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
2089 			   __func__, property);
2090 		return;
2091 	}
2092 
2093 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
2094 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2095 		    wpa_s->dbus_new_path, id);
2096 
2097 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
2098 				       WPAS_DBUS_NEW_IFACE_BSS, prop);
2099 }
2100 
2101 
2102 /**
2103  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
2104  * @global: wpa_global structure
2105  *
2106  * Sends PropertyChanged signals informing that debug level has changed.
2107  */
wpas_dbus_signal_debug_level_changed(struct wpa_global * global)2108 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
2109 {
2110 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2111 				       WPAS_DBUS_NEW_INTERFACE,
2112 				       "DebugLevel");
2113 }
2114 
2115 
2116 /**
2117  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
2118  * @global: wpa_global structure
2119  *
2120  * Sends PropertyChanged signals informing that debug timestamp has changed.
2121  */
wpas_dbus_signal_debug_timestamp_changed(struct wpa_global * global)2122 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
2123 {
2124 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2125 				       WPAS_DBUS_NEW_INTERFACE,
2126 				       "DebugTimestamp");
2127 }
2128 
2129 
2130 /**
2131  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
2132  * @global: wpa_global structure
2133  *
2134  * Sends PropertyChanged signals informing that debug show_keys has changed.
2135  */
wpas_dbus_signal_debug_show_keys_changed(struct wpa_global * global)2136 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
2137 {
2138 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
2139 				       WPAS_DBUS_NEW_INTERFACE,
2140 				       "DebugShowKeys");
2141 }
2142 
2143 
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)2144 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
2145 			       void *priv,
2146 			       WPADBusArgumentFreeFunction priv_free,
2147 			       const struct wpa_dbus_method_desc *methods,
2148 			       const struct wpa_dbus_property_desc *properties,
2149 			       const struct wpa_dbus_signal_desc *signals)
2150 {
2151 	int n;
2152 
2153 	obj_desc->user_data = priv;
2154 	obj_desc->user_data_free_func = priv_free;
2155 	obj_desc->methods = methods;
2156 	obj_desc->properties = properties;
2157 	obj_desc->signals = signals;
2158 
2159 	for (n = 0; properties && properties->dbus_property; properties++)
2160 		n++;
2161 
2162 	obj_desc->prop_changed_flags = os_zalloc(n);
2163 	if (!obj_desc->prop_changed_flags)
2164 		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
2165 			   __func__);
2166 }
2167 
2168 
2169 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
2170 	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
2171 	  (WPADBusMethodHandler) wpas_dbus_handler_create_interface,
2172 	  {
2173 		  { "args", "a{sv}", ARG_IN },
2174 		  { "path", "o", ARG_OUT },
2175 		  END_ARGS
2176 	  }
2177 	},
2178 	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
2179 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_interface,
2180 	  {
2181 		  { "path", "o", ARG_IN },
2182 		  END_ARGS
2183 	  }
2184 	},
2185 	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
2186 	  (WPADBusMethodHandler) wpas_dbus_handler_get_interface,
2187 	  {
2188 		  { "ifname", "s", ARG_IN },
2189 		  { "path", "o", ARG_OUT },
2190 		  END_ARGS
2191 	  }
2192 	},
2193 	{ "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
2194 	  (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
2195 	  {
2196 		END_ARGS
2197 	  }
2198 	},
2199 	{ NULL, NULL, NULL, { END_ARGS } }
2200 };
2201 
2202 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
2203 	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
2204 	  wpas_dbus_getter_debug_level,
2205 	  wpas_dbus_setter_debug_level,
2206 	  NULL
2207 	},
2208 	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
2209 	  wpas_dbus_getter_debug_timestamp,
2210 	  wpas_dbus_setter_debug_timestamp,
2211 	  NULL
2212 	},
2213 	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
2214 	  wpas_dbus_getter_debug_show_keys,
2215 	  wpas_dbus_setter_debug_show_keys,
2216 	  NULL
2217 	},
2218 	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
2219 	  wpas_dbus_getter_interfaces,
2220 	  NULL,
2221 	  NULL
2222 	},
2223 	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
2224 	  wpas_dbus_getter_eap_methods,
2225 	  NULL,
2226 	  NULL
2227 	},
2228 	{ "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
2229 	  wpas_dbus_getter_global_capabilities,
2230 	  NULL,
2231 	  NULL
2232 	},
2233 #ifdef CONFIG_WIFI_DISPLAY
2234 	{ "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
2235 	  wpas_dbus_getter_global_wfd_ies,
2236 	  wpas_dbus_setter_global_wfd_ies,
2237 	  NULL
2238 	},
2239 #endif /* CONFIG_WIFI_DISPLAY */
2240 	{ NULL, NULL, NULL, NULL, NULL, NULL }
2241 };
2242 
2243 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
2244 	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
2245 	  {
2246 		  { "path", "o", ARG_OUT },
2247 		  { "properties", "a{sv}", ARG_OUT },
2248 		  END_ARGS
2249 	  }
2250 	},
2251 	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
2252 	  {
2253 		  { "path", "o", ARG_OUT },
2254 		  END_ARGS
2255 	  }
2256 	},
2257 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2258 	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
2259 	  {
2260 		  { "properties", "a{sv}", ARG_OUT },
2261 		  END_ARGS
2262 	  }
2263 	},
2264 	{ NULL, NULL, { END_ARGS } }
2265 };
2266 
2267 
uscore_to_dbus(const char * uscore)2268 static char * uscore_to_dbus(const char *uscore)
2269 {
2270 	const char *p = uscore;
2271 	char *str, *s;
2272 	dbus_bool_t last_was_uscore = TRUE;
2273 
2274 	s = str = os_zalloc(os_strlen(uscore) + 1);
2275 	if (!str)
2276 		return NULL;
2277 	while (p && *p) {
2278 		if (*p == '_') {
2279 			last_was_uscore = TRUE;
2280 		} else {
2281 			*s++ = last_was_uscore ? toupper(*p) : *p;
2282 			last_was_uscore = FALSE;
2283 		}
2284 		p++;
2285 	}
2286 
2287 	return str;
2288 }
2289 
2290 
2291 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
2292 
2293 
wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv * priv)2294 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
2295 {
2296 	int idx = priv->globals_start;
2297 
2298 	/* Free all allocated property values */
2299 	while (priv->all_interface_properties[idx].dbus_property)
2300 		os_free((char *)
2301 			priv->all_interface_properties[idx++].dbus_property);
2302 	os_free((char *) priv->all_interface_properties);
2303 }
2304 
2305 
2306 /**
2307  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
2308  * @global: Pointer to global data from wpa_supplicant_init()
2309  * Returns: 0 on success or -1 on failure
2310  *
2311  * Initialize the dbus control interface for wpa_supplicant and start
2312  * receiving commands from external programs over the bus.
2313  */
wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv * priv)2314 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2315 {
2316 	struct wpa_dbus_object_desc *obj_desc;
2317 	int ret;
2318 
2319 	ret = wpa_dbus_ctrl_iface_props_init(priv);
2320 	if (ret < 0) {
2321 		wpa_printf(MSG_ERROR,
2322 			   "dbus: Not enough memory to init interface properties");
2323 		return -1;
2324 	}
2325 
2326 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2327 	if (!obj_desc) {
2328 		wpa_printf(MSG_ERROR,
2329 			   "Not enough memory to create object description");
2330 		goto error;
2331 	}
2332 
2333 	wpas_dbus_register(obj_desc, priv->global, NULL,
2334 			   wpas_dbus_global_methods,
2335 			   wpas_dbus_global_properties,
2336 			   wpas_dbus_global_signals);
2337 
2338 	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2339 		   WPAS_DBUS_NEW_PATH);
2340 	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2341 				       WPAS_DBUS_NEW_SERVICE,
2342 				       obj_desc);
2343 	if (ret < 0) {
2344 		free_dbus_object_desc(obj_desc);
2345 		goto error;
2346 	}
2347 
2348 	priv->dbus_new_initialized = 1;
2349 	return 0;
2350 
2351 error:
2352 	wpa_dbus_ctrl_iface_props_deinit(priv);
2353 	return -1;
2354 }
2355 
2356 
2357 /**
2358  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2359  * wpa_supplicant
2360  * @priv: Pointer to dbus private data from wpas_dbus_init()
2361  *
2362  * Deinitialize the dbus control interface that was initialized with
2363  * wpas_dbus_ctrl_iface_init().
2364  */
wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv * priv)2365 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
2366 {
2367 	if (!priv->dbus_new_initialized)
2368 		return;
2369 	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2370 		   WPAS_DBUS_NEW_PATH);
2371 	dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
2372 	wpa_dbus_ctrl_iface_props_deinit(priv);
2373 }
2374 
2375 
wpa_dbus_free(void * ptr)2376 static void wpa_dbus_free(void *ptr)
2377 {
2378 	os_free(ptr);
2379 }
2380 
2381 
2382 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2383 	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2384 	  wpas_dbus_getter_network_properties,
2385 	  wpas_dbus_setter_network_properties,
2386 	  NULL
2387 	},
2388 	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2389 	  wpas_dbus_getter_enabled,
2390 	  wpas_dbus_setter_enabled,
2391 	  NULL
2392 	},
2393 	{ NULL, NULL, NULL, NULL, NULL, NULL }
2394 };
2395 
2396 
2397 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2398 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2399 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2400 	  {
2401 		  { "properties", "a{sv}", ARG_OUT },
2402 		  END_ARGS
2403 	  }
2404 	},
2405 	{ NULL, NULL, { END_ARGS } }
2406 };
2407 
2408 
2409 /**
2410  * wpas_dbus_register_network - Register a configured network with dbus
2411  * @wpa_s: wpa_supplicant interface structure
2412  * @ssid: network configuration data
2413  * Returns: 0 on success, -1 on failure
2414  *
2415  * Registers network representing object with dbus
2416  */
wpas_dbus_register_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2417 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2418 			       struct wpa_ssid *ssid)
2419 {
2420 	struct wpas_dbus_priv *ctrl_iface;
2421 	struct wpa_dbus_object_desc *obj_desc;
2422 	struct network_handler_args *arg;
2423 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2424 
2425 #ifdef CONFIG_P2P
2426 	/*
2427 	 * If it is a persistent group register it as such.
2428 	 * This is to handle cases where an interface is being initialized
2429 	 * with a list of networks read from config.
2430 	 */
2431 	if (network_is_persistent_group(ssid))
2432 		return wpas_dbus_register_persistent_group(wpa_s, ssid);
2433 #endif /* CONFIG_P2P */
2434 
2435 	/* Do nothing if the control interface is not turned on */
2436 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2437 		return 0;
2438 	ctrl_iface = wpa_s->global->dbus;
2439 	if (ctrl_iface == NULL)
2440 		return 0;
2441 
2442 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2443 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2444 		    wpa_s->dbus_new_path, ssid->id);
2445 
2446 	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2447 		   net_obj_path);
2448 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2449 	if (!obj_desc) {
2450 		wpa_printf(MSG_ERROR,
2451 			   "Not enough memory to create object description");
2452 		goto err;
2453 	}
2454 
2455 	/* allocate memory for handlers arguments */
2456 	arg = os_zalloc(sizeof(struct network_handler_args));
2457 	if (!arg) {
2458 		wpa_printf(MSG_ERROR,
2459 			   "Not enough memory to create arguments for method");
2460 		goto err;
2461 	}
2462 
2463 	arg->wpa_s = wpa_s;
2464 	arg->ssid = ssid;
2465 
2466 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2467 			   wpas_dbus_network_properties,
2468 			   wpas_dbus_network_signals);
2469 
2470 	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2471 					       wpa_s->ifname, obj_desc))
2472 		goto err;
2473 
2474 	wpas_dbus_signal_network_added(wpa_s, ssid->id);
2475 
2476 	return 0;
2477 
2478 err:
2479 	free_dbus_object_desc(obj_desc);
2480 	return -1;
2481 }
2482 
2483 
2484 /**
2485  * wpas_dbus_unregister_network - Unregister a configured network from dbus
2486  * @wpa_s: wpa_supplicant interface structure
2487  * @nid: network id
2488  * Returns: 0 on success, -1 on failure
2489  *
2490  * Unregisters network representing object from dbus
2491  */
wpas_dbus_unregister_network(struct wpa_supplicant * wpa_s,int nid)2492 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2493 {
2494 	struct wpas_dbus_priv *ctrl_iface;
2495 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2496 	int ret;
2497 #ifdef CONFIG_P2P
2498 	struct wpa_ssid *ssid;
2499 
2500 	ssid = wpa_config_get_network(wpa_s->conf, nid);
2501 
2502 	/* If it is a persistent group unregister it as such */
2503 	if (ssid && network_is_persistent_group(ssid))
2504 		return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2505 #endif /* CONFIG_P2P */
2506 
2507 	/* Do nothing if the control interface is not turned on */
2508 	if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2509 		return 0;
2510 	ctrl_iface = wpa_s->global->dbus;
2511 	if (ctrl_iface == NULL)
2512 		return 0;
2513 
2514 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2515 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2516 		    wpa_s->dbus_new_path, nid);
2517 
2518 	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2519 		   net_obj_path);
2520 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2521 
2522 	if (!ret)
2523 		wpas_dbus_signal_network_removed(wpa_s, nid);
2524 
2525 	return ret;
2526 }
2527 
2528 
2529 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2530 	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2531 	  wpas_dbus_getter_bss_ssid,
2532 	  NULL,
2533 	  NULL
2534 	},
2535 	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2536 	  wpas_dbus_getter_bss_bssid,
2537 	  NULL,
2538 	  NULL
2539 	},
2540 	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2541 	  wpas_dbus_getter_bss_privacy,
2542 	  NULL,
2543 	  NULL
2544 	},
2545 	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2546 	  wpas_dbus_getter_bss_mode,
2547 	  NULL,
2548 	  NULL
2549 	},
2550 	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2551 	  wpas_dbus_getter_bss_signal,
2552 	  NULL,
2553 	  NULL
2554 	},
2555 	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2556 	  wpas_dbus_getter_bss_frequency,
2557 	  NULL,
2558 	  NULL
2559 	},
2560 	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2561 	  wpas_dbus_getter_bss_rates,
2562 	  NULL,
2563 	  NULL
2564 	},
2565 	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2566 	  wpas_dbus_getter_bss_wpa,
2567 	  NULL,
2568 	  NULL
2569 	},
2570 	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2571 	  wpas_dbus_getter_bss_rsn,
2572 	  NULL,
2573 	  NULL
2574 	},
2575 	{ "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2576 	  wpas_dbus_getter_bss_wps,
2577 	  NULL,
2578 	  NULL
2579 	},
2580 	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2581 	  wpas_dbus_getter_bss_ies,
2582 	  NULL,
2583 	  NULL
2584 	},
2585 	{ "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
2586 	  wpas_dbus_getter_bss_age,
2587 	  NULL,
2588 	  NULL
2589 	},
2590 	{ NULL, NULL, NULL, NULL, NULL, NULL }
2591 };
2592 
2593 
2594 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2595 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2596 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2597 	  {
2598 		  { "properties", "a{sv}", ARG_OUT },
2599 		  END_ARGS
2600 	  }
2601 	},
2602 	{ NULL, NULL, { END_ARGS } }
2603 };
2604 
2605 
2606 /**
2607  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2608  * @wpa_s: wpa_supplicant interface structure
2609  * @bssid: scanned network bssid
2610  * @id: unique BSS identifier
2611  * Returns: 0 on success, -1 on failure
2612  *
2613  * Unregisters BSS representing object from dbus
2614  */
wpas_dbus_unregister_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)2615 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2616 			     u8 bssid[ETH_ALEN], unsigned int id)
2617 {
2618 	struct wpas_dbus_priv *ctrl_iface;
2619 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2620 
2621 	/* Do nothing if the control interface is not turned on */
2622 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2623 		return 0;
2624 	ctrl_iface = wpa_s->global->dbus;
2625 	if (ctrl_iface == NULL)
2626 		return 0;
2627 
2628 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2629 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2630 		    wpa_s->dbus_new_path, id);
2631 
2632 	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2633 		   bss_obj_path);
2634 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2635 		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2636 			   bss_obj_path);
2637 		return -1;
2638 	}
2639 
2640 	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
2641 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2642 
2643 	return 0;
2644 }
2645 
2646 
2647 /**
2648  * wpas_dbus_register_bss - Register a scanned BSS with dbus
2649  * @wpa_s: wpa_supplicant interface structure
2650  * @bssid: scanned network bssid
2651  * @id: unique BSS identifier
2652  * Returns: 0 on success, -1 on failure
2653  *
2654  * Registers BSS representing object with dbus
2655  */
wpas_dbus_register_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)2656 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
2657 			   u8 bssid[ETH_ALEN], unsigned int id)
2658 {
2659 	struct wpas_dbus_priv *ctrl_iface;
2660 	struct wpa_dbus_object_desc *obj_desc;
2661 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2662 	struct bss_handler_args *arg;
2663 
2664 	/* Do nothing if the control interface is not turned on */
2665 	if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path)
2666 		return 0;
2667 	ctrl_iface = wpa_s->global->dbus;
2668 	if (ctrl_iface == NULL)
2669 		return 0;
2670 
2671 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2672 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2673 		    wpa_s->dbus_new_path, id);
2674 
2675 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2676 	if (!obj_desc) {
2677 		wpa_printf(MSG_ERROR,
2678 			   "Not enough memory to create object description");
2679 		goto err;
2680 	}
2681 
2682 	arg = os_zalloc(sizeof(struct bss_handler_args));
2683 	if (!arg) {
2684 		wpa_printf(MSG_ERROR,
2685 			   "Not enough memory to create arguments for handler");
2686 		goto err;
2687 	}
2688 	arg->wpa_s = wpa_s;
2689 	arg->id = id;
2690 
2691 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2692 			   wpas_dbus_bss_properties,
2693 			   wpas_dbus_bss_signals);
2694 
2695 	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
2696 		   bss_obj_path);
2697 	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
2698 					       wpa_s->ifname, obj_desc)) {
2699 		wpa_printf(MSG_ERROR,
2700 			   "Cannot register BSSID dbus object %s.",
2701 			   bss_obj_path);
2702 		goto err;
2703 	}
2704 
2705 	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
2706 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2707 
2708 	return 0;
2709 
2710 err:
2711 	free_dbus_object_desc(obj_desc);
2712 	return -1;
2713 }
2714 
2715 
2716 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
2717 	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
2718 	  (WPADBusMethodHandler) wpas_dbus_handler_scan,
2719 	  {
2720 		  { "args", "a{sv}", ARG_IN },
2721 		  END_ARGS
2722 	  }
2723 	},
2724 	{ "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE,
2725 	  (WPADBusMethodHandler) wpas_dbus_handler_signal_poll,
2726 	  {
2727 		  { "args", "a{sv}", ARG_OUT },
2728 		  END_ARGS
2729 	  }
2730 	},
2731 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
2732 	  (WPADBusMethodHandler) wpas_dbus_handler_disconnect,
2733 	  {
2734 		  END_ARGS
2735 	  }
2736 	},
2737 	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2738 	  (WPADBusMethodHandler) wpas_dbus_handler_add_network,
2739 	  {
2740 		  { "args", "a{sv}", ARG_IN },
2741 		  { "path", "o", ARG_OUT },
2742 		  END_ARGS
2743 	  }
2744 	},
2745 	{ "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
2746 	  (WPADBusMethodHandler) wpas_dbus_handler_reassociate,
2747 	  {
2748 		  END_ARGS
2749 	  }
2750 	},
2751 	{ "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
2752 	  (WPADBusMethodHandler) wpas_dbus_handler_reattach,
2753 	  {
2754 		  END_ARGS
2755 	  }
2756 	},
2757 	{ "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
2758 	  (WPADBusMethodHandler) wpas_dbus_handler_reconnect,
2759 	  {
2760 		  END_ARGS
2761 	  }
2762 	},
2763 	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2764 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_network,
2765 	  {
2766 		  { "path", "o", ARG_IN },
2767 		  END_ARGS
2768 	  }
2769 	},
2770 	{ "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
2771 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks,
2772 	  {
2773 		  END_ARGS
2774 	  }
2775 	},
2776 	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2777 	  (WPADBusMethodHandler) wpas_dbus_handler_select_network,
2778 	  {
2779 		  { "path", "o", ARG_IN },
2780 		  END_ARGS
2781 	  }
2782 	},
2783 	{ "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
2784 	  (WPADBusMethodHandler) wpas_dbus_handler_network_reply,
2785 	  {
2786 		  { "path", "o", ARG_IN },
2787 		  { "field", "s", ARG_IN },
2788 		  { "value", "s", ARG_IN },
2789 		  END_ARGS
2790 	  }
2791 	},
2792 #ifndef CONFIG_NO_CONFIG_BLOBS
2793 	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2794 	  (WPADBusMethodHandler) wpas_dbus_handler_add_blob,
2795 	  {
2796 		  { "name", "s", ARG_IN },
2797 		  { "data", "ay", ARG_IN },
2798 		  END_ARGS
2799 	  }
2800 	},
2801 	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2802 	  (WPADBusMethodHandler) wpas_dbus_handler_get_blob,
2803 	  {
2804 		  { "name", "s", ARG_IN },
2805 		  { "data", "ay", ARG_OUT },
2806 		  END_ARGS
2807 	  }
2808 	},
2809 	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2810 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_blob,
2811 	  {
2812 		  { "name", "s", ARG_IN },
2813 		  END_ARGS
2814 	  }
2815 	},
2816 #endif /* CONFIG_NO_CONFIG_BLOBS */
2817 	{ "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE,
2818 	  (WPADBusMethodHandler)
2819 	  wpas_dbus_handler_set_pkcs11_engine_and_module_path,
2820 	  {
2821 		  { "pkcs11_engine_path", "s", ARG_IN },
2822 		  { "pkcs11_module_path", "s", ARG_IN },
2823 		  END_ARGS
2824 	  }
2825 	},
2826 #ifdef CONFIG_WPS
2827 	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
2828 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_start,
2829 	  {
2830 		  { "args", "a{sv}", ARG_IN },
2831 		  { "output", "a{sv}", ARG_OUT },
2832 		  END_ARGS
2833 	  }
2834 	},
2835 	{ "Cancel", WPAS_DBUS_NEW_IFACE_WPS,
2836 	  (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel,
2837 	  {
2838 		  END_ARGS
2839 	  }
2840 	},
2841 #endif /* CONFIG_WPS */
2842 #ifdef CONFIG_P2P
2843 	{ "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2844 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_find,
2845 	  {
2846 		  { "args", "a{sv}", ARG_IN },
2847 		  END_ARGS
2848 	  }
2849 	},
2850 	{ "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2851 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find,
2852 	  {
2853 		  END_ARGS
2854 	  }
2855 	},
2856 	{ "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2857 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen,
2858 	  {
2859 		  { "timeout", "i", ARG_IN },
2860 		  END_ARGS
2861 	  }
2862 	},
2863 	{ "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2864 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten,
2865 	  {
2866 		  { "args", "a{sv}", ARG_IN },
2867 		  END_ARGS
2868 	  }
2869 	},
2870 	{ "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2871 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request,
2872 	  {
2873 		  { "args", "a{sv}", ARG_IN },
2874 		  END_ARGS
2875 	  }
2876 	},
2877 	{ "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2878 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req,
2879 	  {
2880 		  { "peer", "o", ARG_IN },
2881 		  { "config_method", "s", ARG_IN },
2882 		  END_ARGS
2883 	  }
2884 	},
2885 	{ "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2886 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect,
2887 	  {
2888 		  { "args", "a{sv}", ARG_IN },
2889 		  { "generated_pin", "s", ARG_OUT },
2890 		  END_ARGS
2891 	  }
2892 	},
2893 	{ "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2894 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add,
2895 	  {
2896 		  { "args", "a{sv}", ARG_IN },
2897 		  END_ARGS
2898 	  }
2899 	},
2900 	{ "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2901 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel,
2902 	  {
2903 		  END_ARGS
2904 	  }
2905 	},
2906 	{ "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2907 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite,
2908 	  {
2909 		  { "args", "a{sv}", ARG_IN },
2910 		  END_ARGS
2911 	  }
2912 	},
2913 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2914 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect,
2915 	  {
2916 		  END_ARGS
2917 	  }
2918 	},
2919 	{ "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2920 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer,
2921 	  {
2922 		  { "peer", "o", ARG_IN },
2923 		  END_ARGS
2924 	  }
2925 	},
2926 	{ "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2927 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client,
2928 	  {
2929 		  { "args", "a{sv}", ARG_IN },
2930 		  END_ARGS
2931 	  }
2932 	},
2933 	{ "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2934 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush,
2935 	  {
2936 		  END_ARGS
2937 	  }
2938 	},
2939 	{ "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2940 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service,
2941 	  {
2942 		  { "args", "a{sv}", ARG_IN },
2943 		  END_ARGS
2944 	  }
2945 	},
2946 	{ "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2947 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service,
2948 	  {
2949 		  { "args", "a{sv}", ARG_IN },
2950 		  END_ARGS
2951 	  }
2952 	},
2953 	{ "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2954 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service,
2955 	  {
2956 		  END_ARGS
2957 	  }
2958 	},
2959 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2960 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req,
2961 	  {
2962 		  { "args", "a{sv}", ARG_IN },
2963 		  { "ref", "t", ARG_OUT },
2964 		  END_ARGS
2965 	  }
2966 	},
2967 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2968 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res,
2969 	  {
2970 		  { "args", "a{sv}", ARG_IN },
2971 		  END_ARGS
2972 	  }
2973 	},
2974 	{ "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2975 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req,
2976 	  {
2977 		  { "args", "t", ARG_IN },
2978 		  END_ARGS
2979 	  }
2980 	},
2981 	{ "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2982 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update,
2983 	  {
2984 		  END_ARGS
2985 	  }
2986 	},
2987 	{ "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2988 	  (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external,
2989 	  {
2990 		  { "arg", "i", ARG_IN },
2991 		  END_ARGS
2992 	  }
2993 	},
2994 	{ "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2995 	  (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
2996 	  {
2997 		  { "args", "a{sv}", ARG_IN },
2998 		  { "path", "o", ARG_OUT },
2999 		  END_ARGS
3000 	  }
3001 	},
3002 	{ "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3003 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
3004 	  {
3005 		  { "path", "o", ARG_IN },
3006 		  END_ARGS
3007 	  }
3008 	},
3009 	{ "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3010 	  (WPADBusMethodHandler)
3011 	  wpas_dbus_handler_remove_all_persistent_groups,
3012 	  {
3013 		  END_ARGS
3014 	  }
3015 	},
3016 #endif /* CONFIG_P2P */
3017 	{ "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
3018 	  (WPADBusMethodHandler) wpas_dbus_handler_flush_bss,
3019 	  {
3020 		  { "age", "u", ARG_IN },
3021 		  END_ARGS
3022 	  }
3023 	},
3024 #ifdef CONFIG_AP
3025 	{ "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3026 	  (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
3027 	  {
3028 		  END_ARGS
3029 	  }
3030 	},
3031 	{ "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
3032 	  (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
3033 	  {
3034 		  END_ARGS
3035 	  }
3036 	},
3037 #endif /* CONFIG_AP */
3038 	{ "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE,
3039 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff,
3040 	  {
3041 		  END_ARGS
3042 	  }
3043 	},
3044 	{ "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE,
3045 	  (WPADBusMethodHandler) wpas_dbus_handler_eap_logon,
3046 	  {
3047 		  END_ARGS
3048 	  }
3049 	},
3050 #ifdef CONFIG_AUTOSCAN
3051 	{ "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
3052 	  (WPADBusMethodHandler) wpas_dbus_handler_autoscan,
3053 	  {
3054 		  { "arg", "s", ARG_IN },
3055 		  END_ARGS
3056 	  }
3057 	},
3058 #endif /* CONFIG_AUTOSCAN */
3059 #ifdef CONFIG_TDLS
3060 	{ "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE,
3061 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover,
3062 	  {
3063 		  { "peer_address", "s", ARG_IN },
3064 		  END_ARGS
3065 	  }
3066 	},
3067 	{ "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE,
3068 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup,
3069 	  {
3070 		  { "peer_address", "s", ARG_IN },
3071 		  END_ARGS
3072 	  }
3073 	},
3074 	{ "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE,
3075 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_status,
3076 	  {
3077 		  { "peer_address", "s", ARG_IN },
3078 		  { "status", "s", ARG_OUT },
3079 		  END_ARGS
3080 	  }
3081 	},
3082 	{ "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE,
3083 	  (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown,
3084 	  {
3085 		  { "peer_address", "s", ARG_IN },
3086 		  END_ARGS
3087 	  }
3088 	},
3089 #endif /* CONFIG_TDLS */
3090 	{ "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
3091 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
3092 	  {
3093 		  { "frame_id", "i", ARG_IN },
3094 		  { "ielems", "ay", ARG_IN },
3095 		  END_ARGS
3096 	  }
3097 	},
3098 	{ "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
3099 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
3100 	  {
3101 		  { "frame_id", "i", ARG_IN },
3102 		  { "ielems", "ay", ARG_OUT },
3103 		  END_ARGS
3104 	  }
3105 	},
3106 	{ "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
3107 	  (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
3108 	  {
3109 		  { "frame_id", "i", ARG_IN },
3110 		  { "ielems", "ay", ARG_IN },
3111 		  END_ARGS
3112 	  }
3113 	},
3114 #ifndef CONFIG_NO_CONFIG_WRITE
3115 	{ "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
3116 	  (WPADBusMethodHandler) wpas_dbus_handler_save_config,
3117 	  {
3118 		  END_ARGS
3119 	  }
3120 	},
3121 #endif /* CONFIG_NO_CONFIG_WRITE */
3122 	{ NULL, NULL, NULL, { END_ARGS } }
3123 };
3124 
3125 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
3126 	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
3127 	  wpas_dbus_getter_capabilities,
3128 	  NULL,
3129 	  NULL
3130 	},
3131 	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3132 	  wpas_dbus_getter_state,
3133 	  NULL,
3134 	  NULL
3135 	},
3136 	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3137 	  wpas_dbus_getter_scanning,
3138 	  NULL,
3139 	  NULL
3140 	},
3141 	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3142 	  wpas_dbus_getter_ap_scan,
3143 	  wpas_dbus_setter_ap_scan,
3144 	  NULL
3145 	},
3146 #ifdef CONFIG_IEEE80211W
3147 	{ "Pmf", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3148 	  wpas_dbus_getter_pmf,
3149 	  wpas_dbus_setter_pmf,
3150 	  NULL
3151 	},
3152 #endif /* CONFIG_IEEE80211W */
3153 	{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3154 	  wpas_dbus_getter_bss_expire_age,
3155 	  wpas_dbus_setter_bss_expire_age,
3156 	  NULL
3157 	},
3158 	{ "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
3159 	  wpas_dbus_getter_bss_expire_count,
3160 	  wpas_dbus_setter_bss_expire_count,
3161 	  NULL
3162 	},
3163 	{ "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3164 	  wpas_dbus_getter_country,
3165 	  wpas_dbus_setter_country,
3166 	  NULL
3167 	},
3168 	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3169 	  wpas_dbus_getter_ifname,
3170 	  NULL,
3171 	  NULL
3172 	},
3173 	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3174 	  wpas_dbus_getter_driver,
3175 	  NULL,
3176 	  NULL
3177 	},
3178 	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3179 	  wpas_dbus_getter_bridge_ifname,
3180 	  NULL,
3181 	  NULL
3182 	},
3183 	{ "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3184 	  wpas_dbus_getter_config_file,
3185 	  NULL,
3186 	  NULL
3187 	},
3188 	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3189 	  wpas_dbus_getter_current_bss,
3190 	  NULL,
3191 	  NULL
3192 	},
3193 	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
3194 	  wpas_dbus_getter_current_network,
3195 	  NULL,
3196 	  NULL
3197 	},
3198 	{ "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3199 	  wpas_dbus_getter_current_auth_mode,
3200 	  NULL,
3201 	  NULL
3202 	},
3203 	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
3204 	  wpas_dbus_getter_blobs,
3205 	  NULL,
3206 	  NULL
3207 	},
3208 	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3209 	  wpas_dbus_getter_bsss,
3210 	  NULL,
3211 	  NULL
3212 	},
3213 	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
3214 	  wpas_dbus_getter_networks,
3215 	  NULL,
3216 	  NULL
3217 	},
3218 	{ "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
3219 	  wpas_dbus_getter_fast_reauth,
3220 	  wpas_dbus_setter_fast_reauth,
3221 	  NULL
3222 	},
3223 	{ "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3224 	  wpas_dbus_getter_scan_interval,
3225 	  wpas_dbus_setter_scan_interval,
3226 	  NULL
3227 	},
3228 	{ "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3229 	  wpas_dbus_getter_pkcs11_engine_path,
3230 	  NULL,
3231 	  NULL
3232 	},
3233 	{ "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
3234 	  wpas_dbus_getter_pkcs11_module_path,
3235 	  NULL,
3236 	  NULL
3237 	},
3238 #ifdef CONFIG_WPS
3239 	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
3240 	  wpas_dbus_getter_process_credentials,
3241 	  wpas_dbus_setter_process_credentials,
3242 	  NULL
3243 	},
3244 	{ "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
3245 	  wpas_dbus_getter_config_methods,
3246 	  wpas_dbus_setter_config_methods,
3247 	  NULL
3248 	},
3249 	{
3250 	  "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3251 	  wpas_dbus_getter_wps_device_name,
3252 	  wpas_dbus_setter_wps_device_name,
3253 	  NULL
3254 	},
3255 	{
3256 	  "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s",
3257 	  wpas_dbus_getter_wps_manufacturer,
3258 	  wpas_dbus_setter_wps_manufacturer,
3259 	  NULL
3260 	},
3261 	{
3262 	  "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s",
3263 	  wpas_dbus_getter_wps_device_model_name,
3264 	  wpas_dbus_setter_wps_device_model_name,
3265 	  NULL
3266 	},
3267 	{
3268 	  "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3269 	  wpas_dbus_getter_wps_device_model_number,
3270 	  wpas_dbus_setter_wps_device_model_number,
3271 	  NULL
3272 	},
3273 	{
3274 	  "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s",
3275 	  wpas_dbus_getter_wps_device_serial_number,
3276 	  wpas_dbus_setter_wps_device_serial_number,
3277 	  NULL
3278 	},
3279 	{
3280 	  "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay",
3281 	  wpas_dbus_getter_wps_device_device_type,
3282 	  wpas_dbus_setter_wps_device_device_type,
3283 	  NULL
3284 	},
3285 #endif /* CONFIG_WPS */
3286 #ifdef CONFIG_P2P
3287 	{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
3288 	  wpas_dbus_getter_p2p_device_config,
3289 	  wpas_dbus_setter_p2p_device_config,
3290 	  NULL
3291 	},
3292 	{ "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3293 	  wpas_dbus_getter_p2p_peers,
3294 	  NULL,
3295 	  NULL
3296 	},
3297 	{ "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
3298 	  wpas_dbus_getter_p2p_role,
3299 	  NULL,
3300 	  NULL
3301 	},
3302 	{ "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3303 	  wpas_dbus_getter_p2p_group,
3304 	  NULL,
3305 	  NULL
3306 	},
3307 	{ "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
3308 	  wpas_dbus_getter_p2p_peergo,
3309 	  NULL,
3310 	  NULL
3311 	},
3312 	{ "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
3313 	  wpas_dbus_getter_persistent_groups,
3314 	  NULL,
3315 	  NULL
3316 	},
3317 #endif /* CONFIG_P2P */
3318 	{ "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3319 	  wpas_dbus_getter_disconnect_reason,
3320 	  NULL,
3321 	  NULL
3322 	},
3323 	{ "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
3324 	  wpas_dbus_getter_assoc_status_code,
3325 	  NULL,
3326 	  NULL
3327 	},
3328 	{ NULL, NULL, NULL, NULL, NULL, NULL }
3329 };
3330 
3331 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
3332 	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
3333 	  {
3334 		  { "success", "b", ARG_OUT },
3335 		  END_ARGS
3336 	  }
3337 	},
3338 	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3339 	  {
3340 		  { "path", "o", ARG_OUT },
3341 		  { "properties", "a{sv}", ARG_OUT },
3342 		  END_ARGS
3343 	  }
3344 	},
3345 	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3346 	  {
3347 		  { "path", "o", ARG_OUT },
3348 		  END_ARGS
3349 	  }
3350 	},
3351 	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3352 	  {
3353 		  { "name", "s", ARG_OUT },
3354 		  END_ARGS
3355 	  }
3356 	},
3357 	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3358 	  {
3359 		  { "name", "s", ARG_OUT },
3360 		  END_ARGS
3361 	  }
3362 	},
3363 	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
3364 	  {
3365 		  { "path", "o", ARG_OUT },
3366 		  { "properties", "a{sv}", ARG_OUT },
3367 		  END_ARGS
3368 	  }
3369 	},
3370 	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
3371 	  {
3372 		  { "path", "o", ARG_OUT },
3373 		  END_ARGS
3374 	  }
3375 	},
3376 	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
3377 	  {
3378 		  { "path", "o", ARG_OUT },
3379 		  END_ARGS
3380 	  }
3381 	},
3382 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3383 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
3384 	  {
3385 		  { "properties", "a{sv}", ARG_OUT },
3386 		  END_ARGS
3387 	  }
3388 	},
3389 #ifdef CONFIG_WPS
3390 	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
3391 	  {
3392 		  { "name", "s", ARG_OUT },
3393 		  { "args", "a{sv}", ARG_OUT },
3394 		  END_ARGS
3395 	  }
3396 	},
3397 	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
3398 	  {
3399 		  { "credentials", "a{sv}", ARG_OUT },
3400 		  END_ARGS
3401 	  }
3402 	},
3403 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3404 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
3405 	  {
3406 		  { "properties", "a{sv}", ARG_OUT },
3407 		  END_ARGS
3408 	  }
3409 	},
3410 #endif /* CONFIG_WPS */
3411 #ifdef CONFIG_P2P
3412 	{ "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3413 	  {
3414 		  { "path", "o", ARG_OUT },
3415 		  END_ARGS
3416 	  }
3417 	},
3418 	{ "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3419 	  {
3420 		  { "path", "o", ARG_OUT },
3421 		  { "properties", "a{sv}", ARG_OUT },
3422 		  END_ARGS
3423 	  }
3424 	},
3425 	{ "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3426 	  {
3427 		  { "path", "o", ARG_OUT },
3428 		  END_ARGS
3429 	  }
3430 	},
3431 	{ "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3432 	  {
3433 		  END_ARGS
3434 	  }
3435 	},
3436 	{ "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3437 	  {
3438 		  { "peer_object", "o", ARG_OUT },
3439 		  { "pin", "s", ARG_OUT },
3440 		  END_ARGS
3441 	  }
3442 	},
3443 	{ "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3444 	  {
3445 		  { "peer_object", "o", ARG_OUT },
3446 		  { "pin", "s", ARG_OUT },
3447 		  END_ARGS
3448 	  }
3449 	},
3450 	{ "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3451 	  {
3452 		  { "peer_object", "o", ARG_OUT },
3453 		  END_ARGS
3454 	  }
3455 	},
3456 	{ "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3457 	  {
3458 		  { "peer_object", "o", ARG_OUT },
3459 		  END_ARGS
3460 	  }
3461 	},
3462 	{ "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3463 	  {
3464 		  { "peer_object", "o", ARG_OUT },
3465 		  END_ARGS
3466 	  }
3467 	},
3468 	{ "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3469 	  {
3470 		  { "peer_object", "o", ARG_OUT },
3471 		  END_ARGS
3472 	  }
3473 	},
3474 	{ "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3475 	  {
3476 		  { "peer_object", "o", ARG_OUT },
3477 		  { "status", "i", ARG_OUT },
3478 		  END_ARGS
3479 	  }
3480 	},
3481 	{ "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3482 	  {
3483 		  { "properties", "a{sv}", ARG_OUT },
3484 		  END_ARGS
3485 	  }
3486 	},
3487 	{ "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3488 	  {
3489 		  { "reason", "s", ARG_OUT },
3490 		  END_ARGS
3491 	  }
3492 	},
3493 	{ "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3494 	  {
3495 		  { "properties", "a{sv}", ARG_OUT },
3496 		  END_ARGS
3497 	  }
3498 	},
3499 	{ "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3500 	  {
3501 		  { "properties", "a{sv}", ARG_OUT },
3502 		  END_ARGS
3503 	  }
3504 	},
3505 	{ "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3506 	  {
3507 		  { "path", "o", ARG_OUT },
3508 		  { "dev_passwd_id", "q", ARG_OUT },
3509 		  { "device_go_intent", "y", ARG_OUT },
3510 		  END_ARGS
3511 	  }
3512 	},
3513 	{ "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3514 	  {
3515 		  { "invite_result", "a{sv}", ARG_OUT },
3516 		  END_ARGS
3517 	  }
3518 	},
3519 	{ "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3520 	  {
3521 		  { "properties", "a{sv}", ARG_OUT },
3522 		  END_ARGS
3523 	  }
3524 	},
3525 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3526 	  {
3527 		  { "sd_request", "a{sv}", ARG_OUT },
3528 		  END_ARGS
3529 	  }
3530 	},
3531 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3532 	  {
3533 		  { "sd_response", "a{sv}", ARG_OUT },
3534 		  END_ARGS
3535 	  }
3536 	},
3537 	{ "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3538 	  {
3539 		  { "path", "o", ARG_OUT },
3540 		  { "properties", "a{sv}", ARG_OUT },
3541 		  END_ARGS
3542 	  }
3543 	},
3544 	{ "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3545 	  {
3546 		  { "path", "o", ARG_OUT },
3547 		  END_ARGS
3548 	  }
3549 	},
3550 	{ "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3551 	  {
3552 		  { "name", "s", ARG_OUT },
3553 		  { "args", "a{sv}", ARG_OUT },
3554 		  END_ARGS
3555 	  }
3556 	},
3557 	{ "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3558 	  {
3559 		  { "properties", "a{sv}", ARG_OUT },
3560 		  END_ARGS
3561 	  }
3562 	},
3563 #endif /* CONFIG_P2P */
3564 #ifdef CONFIG_AP
3565 	{ "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
3566 	  {
3567 		  { "args", "a{sv}", ARG_OUT },
3568 		  END_ARGS
3569 	  }
3570 	},
3571 #endif /* CONFIG_AP */
3572 	{ "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
3573 	  {
3574 		  { "certification", "a{sv}", ARG_OUT },
3575 		  END_ARGS
3576 	  }
3577 	},
3578 	{ "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
3579 	  {
3580 		  { "status", "s", ARG_OUT },
3581 		  { "parameter", "s", ARG_OUT },
3582 		  END_ARGS
3583 	  }
3584 	},
3585 	{ "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
3586 	  {
3587 		  { "name", "s", ARG_OUT },
3588 		  END_ARGS
3589 	  }
3590 	},
3591 	{ "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE,
3592 	  {
3593 		  { "name", "s", ARG_OUT },
3594 		  END_ARGS
3595 	  }
3596 	},
3597 	{ "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
3598 	  {
3599 		  { "path", "o", ARG_OUT },
3600 		  { "field", "s", ARG_OUT },
3601 		  { "text", "s", ARG_OUT },
3602 		  END_ARGS
3603 	  }
3604 	},
3605 	{ NULL, NULL, { END_ARGS } }
3606 };
3607 
3608 
wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv * priv)3609 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
3610 {
3611 	size_t all_size;
3612 	unsigned int i, j, count, num_const, num_globals;
3613 	const char *global_name;
3614 	static const char * const ignored_globals[] = {
3615 		"bss_expiration_age", "bss_expiration_scan_count",
3616 		"ap_scan", "country", "fast_reauth",
3617 		"pkcs11_engine_path", "pkcs11_module_path"
3618 	};
3619 
3620 	/* wpas_dbus_interface_properties terminates with a NULL element */
3621 	num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
3622 
3623 	num_globals = wpa_config_get_num_global_field_names();
3624 	priv->globals_start = num_const;
3625 
3626 	/* allocate enough for all properties + terminating NULL element */
3627 	all_size = (num_globals + num_const + 1) *
3628 		sizeof(wpas_dbus_interface_properties[0]);
3629 	priv->all_interface_properties = os_zalloc(all_size);
3630 	if (!priv->all_interface_properties) {
3631 		wpa_printf(MSG_ERROR,
3632 			   "dbus: Not enough memory for interface properties");
3633 		return -1;
3634 	}
3635 
3636 	/* Copy constant interface properties to the start of the array */
3637 	os_memcpy(priv->all_interface_properties,
3638 		  wpas_dbus_interface_properties,
3639 		  sizeof(wpas_dbus_interface_properties));
3640 
3641 	/* Dynamically construct interface global properties */
3642 	for (i = 0, count = num_const; i < num_globals; i++) {
3643 		struct wpa_dbus_property_desc *desc;
3644 		int no_var = 0;
3645 
3646 		/* ignore globals that are actually just methods */
3647 		global_name = wpa_config_get_global_field_name(i, &no_var);
3648 		if (no_var)
3649 			continue;
3650 		/* Ignore fields already explicitly exposed */
3651 		for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
3652 			if (os_strcmp(global_name, ignored_globals[j]) == 0)
3653 				break;
3654 		}
3655 		if (j < ARRAY_SIZE(ignored_globals))
3656 			continue;
3657 
3658 		desc = &priv->all_interface_properties[count++];
3659 		desc->dbus_property = uscore_to_dbus(global_name);
3660 		if (!desc->dbus_property) {
3661 			wpa_printf(MSG_ERROR,
3662 				   "dbus: Not enough memory for D-Bus property name");
3663 			goto error;
3664 		}
3665 		desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
3666 		desc->type = "s";
3667 		desc->getter = wpas_dbus_getter_iface_global;
3668 		desc->setter = wpas_dbus_setter_iface_global;
3669 		desc->data = global_name;
3670 	}
3671 
3672 	return 0;
3673 
3674 error:
3675 	wpa_dbus_ctrl_iface_props_deinit(priv);
3676 	return -1;
3677 }
3678 
3679 
3680 /**
3681  * wpas_dbus_register_interface - Register an interface with D-Bus
3682  * @wpa_s: wpa_supplicant interface structure
3683  * Returns: 0 on success, -1 on failure
3684  */
wpas_dbus_register_interface(struct wpa_supplicant * wpa_s)3685 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
3686 {
3687 	struct wpa_dbus_object_desc *obj_desc = NULL;
3688 	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
3689 	int next;
3690 
3691 	/* Do nothing if the control interface is not turned on */
3692 	if (ctrl_iface == NULL)
3693 		return 0;
3694 
3695 	/* Create and set the interface's object path */
3696 	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3697 	if (wpa_s->dbus_new_path == NULL)
3698 		return -1;
3699 	next = ctrl_iface->next_objid++;
3700 	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
3701 		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
3702 		    next);
3703 
3704 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3705 	if (!obj_desc) {
3706 		wpa_printf(MSG_ERROR,
3707 			   "Not enough memory to create object description");
3708 		goto err;
3709 	}
3710 
3711 	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
3712 			   ctrl_iface->all_interface_properties,
3713 			   wpas_dbus_interface_signals);
3714 
3715 	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
3716 		   wpa_s->dbus_new_path);
3717 	if (wpa_dbus_register_object_per_iface(ctrl_iface,
3718 					       wpa_s->dbus_new_path,
3719 					       wpa_s->ifname, obj_desc))
3720 		goto err;
3721 
3722 	wpas_dbus_signal_interface_added(wpa_s);
3723 
3724 	return 0;
3725 
3726 err:
3727 	os_free(wpa_s->dbus_new_path);
3728 	wpa_s->dbus_new_path = NULL;
3729 	free_dbus_object_desc(obj_desc);
3730 	return -1;
3731 }
3732 
3733 
3734 /**
3735  * wpas_dbus_unregister_interface - Unregister the interface from D-Bus
3736  * @wpa_s: wpa_supplicant interface structure
3737  * Returns: 0 on success, -1 on failure
3738  */
wpas_dbus_unregister_interface(struct wpa_supplicant * wpa_s)3739 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
3740 {
3741 	struct wpas_dbus_priv *ctrl_iface;
3742 
3743 	/* Do nothing if the control interface is not turned on */
3744 	if (wpa_s == NULL || wpa_s->global == NULL)
3745 		return 0;
3746 	ctrl_iface = wpa_s->global->dbus;
3747 	if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL)
3748 		return 0;
3749 
3750 	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
3751 		   wpa_s->dbus_new_path);
3752 
3753 #ifdef CONFIG_AP
3754 	if (wpa_s->preq_notify_peer) {
3755 		wpas_dbus_unsubscribe_noc(ctrl_iface);
3756 		os_free(wpa_s->preq_notify_peer);
3757 		wpa_s->preq_notify_peer = NULL;
3758 	}
3759 #endif /* CONFIG_AP */
3760 
3761 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3762 						 wpa_s->dbus_new_path))
3763 		return -1;
3764 
3765 	wpas_dbus_signal_interface_removed(wpa_s);
3766 
3767 	os_free(wpa_s->dbus_new_path);
3768 	wpa_s->dbus_new_path = NULL;
3769 
3770 	return 0;
3771 }
3772 
3773 #ifdef CONFIG_P2P
3774 
3775 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
3776 	{ "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
3777 	  wpas_dbus_getter_p2p_peer_device_name,
3778 	  NULL,
3779 	  NULL
3780 	},
3781 	{ "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
3782 	  wpas_dbus_getter_p2p_peer_manufacturer,
3783 	  NULL,
3784 	  NULL
3785 	},
3786 	{ "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
3787 	  wpas_dbus_getter_p2p_peer_modelname,
3788 	  NULL,
3789 	  NULL
3790 	},
3791 	{ "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
3792 	  wpas_dbus_getter_p2p_peer_modelnumber,
3793 	  NULL,
3794 	  NULL
3795 	},
3796 	{ "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
3797 	  wpas_dbus_getter_p2p_peer_serialnumber,
3798 	  NULL,
3799 	  NULL
3800 	},
3801 	{ "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3802 	  wpas_dbus_getter_p2p_peer_primary_device_type,
3803 	  NULL,
3804 	  NULL
3805 	},
3806 	{ "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
3807 	  wpas_dbus_getter_p2p_peer_config_method,
3808 	  NULL,
3809 	  NULL
3810 	},
3811 	{ "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
3812 	  wpas_dbus_getter_p2p_peer_level,
3813 	  NULL,
3814 	  NULL
3815 	},
3816 	{ "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
3817 	  wpas_dbus_getter_p2p_peer_device_capability,
3818 	  NULL,
3819 	  NULL
3820 	},
3821 	{ "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
3822 	  wpas_dbus_getter_p2p_peer_group_capability,
3823 	  NULL,
3824 	  NULL
3825 	},
3826 	{ "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
3827 	  wpas_dbus_getter_p2p_peer_secondary_device_types,
3828 	  NULL,
3829 	  NULL
3830 	},
3831 	{ "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
3832 	  wpas_dbus_getter_p2p_peer_vendor_extension,
3833 	  NULL,
3834 	  NULL
3835 	},
3836 	{ "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3837 	  wpas_dbus_getter_p2p_peer_ies,
3838 	  NULL,
3839 	  NULL
3840 	},
3841 	{ "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3842 	  wpas_dbus_getter_p2p_peer_device_address,
3843 	  NULL,
3844 	  NULL
3845 	},
3846 	{ "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
3847 	  wpas_dbus_getter_p2p_peer_groups,
3848 	  NULL,
3849 	  NULL
3850 	},
3851 	{ NULL, NULL, NULL, NULL, NULL, NULL }
3852 };
3853 
3854 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
3855 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
3856 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
3857 	  {
3858 		  { "properties", "a{sv}", ARG_OUT },
3859 		  END_ARGS
3860 	  }
3861 	},
3862 	{ NULL, NULL, { END_ARGS } }
3863 };
3864 
3865 /**
3866  * wpas_dbus_signal_peer - Send a peer related event signal
3867  * @wpa_s: %wpa_supplicant network interface data
3868  * @dev: peer device object
3869  * @interface: name of the interface emitting this signal.
3870  *	In case of peer objects, it would be emitted by either
3871  *	the "interface object" or by "peer objects"
3872  * @sig_name: signal name - DeviceFound
3873  * @properties: Whether to add a second argument with object properties
3874  *
3875  * Notify listeners about event related with p2p peer device
3876  */
wpas_dbus_signal_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr,const char * interface,const char * sig_name,int properties)3877 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
3878 				  const u8 *dev_addr, const char *interface,
3879 				  const char *sig_name, int properties)
3880 {
3881 	struct wpas_dbus_priv *iface;
3882 	DBusMessage *msg;
3883 	DBusMessageIter iter;
3884 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
3885 
3886 	if (wpa_s->p2p_mgmt)
3887 		wpa_s = wpa_s->parent;
3888 
3889 	iface = wpa_s->global->dbus;
3890 
3891 	/* Do nothing if the control interface is not turned on */
3892 	if (iface == NULL || !wpa_s->dbus_new_path)
3893 		return;
3894 
3895 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3896 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3897 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
3898 
3899 	msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
3900 				      sig_name);
3901 	if (msg == NULL)
3902 		return;
3903 
3904 	dbus_message_iter_init_append(msg, &iter);
3905 	path = peer_obj_path;
3906 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
3907 					    &path) ||
3908 	    (properties && !wpa_dbus_get_object_properties(
3909 		    iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
3910 		    &iter)))
3911 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
3912 	else
3913 		dbus_connection_send(iface->con, msg, NULL);
3914 
3915 	dbus_message_unref(msg);
3916 }
3917 
3918 
3919 /**
3920  * wpas_dbus_signal_peer_found - Send a peer found signal
3921  * @wpa_s: %wpa_supplicant network interface data
3922  * @dev_addr: Peer P2P Device Address
3923  *
3924  * Notify listeners about find a p2p peer device found
3925  */
wpas_dbus_signal_peer_device_found(struct wpa_supplicant * wpa_s,const u8 * dev_addr)3926 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
3927 					const u8 *dev_addr)
3928 {
3929 	wpas_dbus_signal_peer(wpa_s, dev_addr,
3930 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3931 			      "DeviceFound", FALSE);
3932 
3933 	wpas_dbus_signal_peer(wpa_s, dev_addr,
3934 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3935 			      "DeviceFoundProperties", TRUE);
3936 }
3937 
3938 /**
3939  * wpas_dbus_signal_peer_lost - Send a peer lost signal
3940  * @wpa_s: %wpa_supplicant network interface data
3941  * @dev_addr: Peer P2P Device Address
3942  *
3943  * Notify listeners about lost a p2p peer device
3944  */
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant * wpa_s,const u8 * dev_addr)3945 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
3946 				       const u8 *dev_addr)
3947 {
3948 	wpas_dbus_signal_peer(wpa_s, dev_addr,
3949 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3950 			      "DeviceLost", FALSE);
3951 }
3952 
3953 /**
3954  * wpas_dbus_register_peer - Register a discovered peer object with dbus
3955  * @wpa_s: wpa_supplicant interface structure
3956  * @dev_addr: P2P Device Address of the peer
3957  * Returns: 0 on success, -1 on failure
3958  *
3959  * Registers network representing object with dbus
3960  */
wpas_dbus_register_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)3961 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
3962 {
3963 	struct wpas_dbus_priv *ctrl_iface;
3964 	struct wpa_dbus_object_desc *obj_desc;
3965 	struct peer_handler_args *arg;
3966 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3967 
3968 	/* Do nothing if the control interface is not turned on */
3969 	if (wpa_s == NULL || wpa_s->global == NULL)
3970 		return 0;
3971 
3972 	ctrl_iface = wpa_s->global->dbus;
3973 	if (ctrl_iface == NULL)
3974 		return 0;
3975 
3976 	wpa_s = wpa_s->parent->parent;
3977 	if (!wpa_s->dbus_new_path)
3978 		return 0;
3979 
3980 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3981 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3982 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
3983 
3984 	wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
3985 		   peer_obj_path);
3986 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3987 	if (!obj_desc) {
3988 		wpa_printf(MSG_ERROR,
3989 			   "Not enough memory to create object description");
3990 		goto err;
3991 	}
3992 
3993 	/* allocate memory for handlers arguments */
3994 	arg = os_zalloc(sizeof(struct peer_handler_args));
3995 	if (!arg) {
3996 		wpa_printf(MSG_ERROR,
3997 			   "Not enough memory to create arguments for method");
3998 		goto err;
3999 	}
4000 
4001 	arg->wpa_s = wpa_s;
4002 	os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
4003 
4004 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
4005 			   NULL,
4006 			   wpas_dbus_p2p_peer_properties,
4007 			   wpas_dbus_p2p_peer_signals);
4008 
4009 	if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
4010 					       wpa_s->ifname, obj_desc))
4011 		goto err;
4012 
4013 	return 0;
4014 
4015 err:
4016 	free_dbus_object_desc(obj_desc);
4017 	return -1;
4018 }
4019 
4020 /**
4021  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
4022  * @wpa_s: wpa_supplicant interface structure
4023  * @dev_addr: p2p device addr
4024  * Returns: 0 on success, -1 on failure
4025  *
4026  * Registers network representing object with dbus
4027  */
wpas_dbus_unregister_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4028 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
4029 				  const u8 *dev_addr)
4030 {
4031 	struct wpas_dbus_priv *ctrl_iface;
4032 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4033 	int ret;
4034 
4035 	/* Do nothing if the control interface is not turned on */
4036 	if (wpa_s == NULL || wpa_s->global == NULL)
4037 		return 0;
4038 
4039 	wpa_s = wpa_s->parent->parent;
4040 	if (!wpa_s->dbus_new_path)
4041 		return 0;
4042 
4043 	ctrl_iface = wpa_s->global->dbus;
4044 	if (ctrl_iface == NULL)
4045 		return 0;
4046 
4047 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4048 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4049 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
4050 
4051 	wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
4052 		   peer_obj_path);
4053 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
4054 
4055 	return ret;
4056 }
4057 
4058 
4059 /**
4060  * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal
4061  * @wpa_s: %wpa_supplicant network interface data
4062  *
4063  * Notify listeners about P2P Find stopped
4064  */
wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant * wpa_s)4065 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s)
4066 {
4067 	struct wpas_dbus_priv *iface;
4068 	DBusMessage *msg;
4069 
4070 	iface = wpa_s->global->dbus;
4071 
4072 	/* Do nothing if the control interface is not turned on */
4073 	if (iface == NULL || !wpa_s->dbus_new_path)
4074 		return;
4075 
4076 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
4077 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
4078 				      "FindStopped");
4079 	if (msg == NULL)
4080 		return;
4081 
4082 	dbus_connection_send(iface->con, msg, NULL);
4083 
4084 	dbus_message_unref(msg);
4085 }
4086 
4087 
4088 /**
4089  * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal
4090  * @wpa_s: %wpa_supplicant network interface data
4091  * @dev_addr: P2P Device Address
4092  *
4093  * Notify listeners about peer Groups property changes.
4094  */
wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant * wpa_s,const u8 * dev_addr)4095 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
4096 					  const u8 *dev_addr)
4097 {
4098 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4099 
4100 	if (wpa_s->p2p_mgmt)
4101 		wpa_s = wpa_s->parent;
4102 
4103 	if (!wpa_s->dbus_new_path)
4104 		return;
4105 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4106 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
4107 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
4108 
4109 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
4110 				       WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
4111 }
4112 
4113 
4114 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
4115 	{ "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
4116 	  wpas_dbus_getter_p2p_group_members,
4117 	  NULL,
4118 	  NULL
4119 	},
4120 	{ "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
4121 	  wpas_dbus_getter_p2p_group,
4122 	  NULL,
4123 	  NULL
4124 	},
4125 	{ "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4126 	  wpas_dbus_getter_p2p_role,
4127 	  NULL,
4128 	  NULL
4129 	},
4130 	{ "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4131 	  wpas_dbus_getter_p2p_group_ssid,
4132 	  NULL,
4133 	  NULL
4134 	},
4135 	{ "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4136 	  wpas_dbus_getter_p2p_group_bssid,
4137 	  NULL,
4138 	  NULL
4139 	},
4140 	{ "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
4141 	  wpas_dbus_getter_p2p_group_frequency,
4142 	  NULL,
4143 	  NULL
4144 	},
4145 	{ "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
4146 	  wpas_dbus_getter_p2p_group_passphrase,
4147 	  NULL,
4148 	  NULL
4149 	},
4150 	{ "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
4151 	  wpas_dbus_getter_p2p_group_psk,
4152 	  NULL,
4153 	  NULL
4154 	},
4155 	{ "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
4156 	  wpas_dbus_getter_p2p_group_vendor_ext,
4157 	  wpas_dbus_setter_p2p_group_vendor_ext,
4158 	  NULL
4159 	},
4160 	{ NULL, NULL, NULL, NULL, NULL, NULL }
4161 };
4162 
4163 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
4164 	{ "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4165 	  {
4166 		  { "peer", "o", ARG_OUT },
4167 		  END_ARGS
4168 	  }
4169 	},
4170 	{ "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
4171 	  {
4172 		  { "peer", "o", ARG_OUT },
4173 		  END_ARGS
4174 	  }
4175 	},
4176 	{ NULL, NULL, { END_ARGS } }
4177 };
4178 
4179 /**
4180  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
4181  * @wpa_s: wpa_supplicant interface structure
4182  * @ssid: SSID struct
4183  * Returns: 0 on success, -1 on failure
4184  *
4185  * Registers p2p group representing object with dbus
4186  */
wpas_dbus_register_p2p_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)4187 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
4188 				  struct wpa_ssid *ssid)
4189 {
4190 	struct wpas_dbus_priv *ctrl_iface;
4191 	struct wpa_dbus_object_desc *obj_desc;
4192 	char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4193 
4194 	/* Do nothing if the control interface is not turned on */
4195 	if (wpa_s == NULL || wpa_s->global == NULL)
4196 		return;
4197 
4198 	ctrl_iface = wpa_s->global->dbus;
4199 	if (ctrl_iface == NULL)
4200 		return;
4201 
4202 	if (wpa_s->dbus_groupobj_path) {
4203 		wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
4204 			   __func__, wpa_s->dbus_groupobj_path);
4205 		return;
4206 	}
4207 
4208 	if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
4209 		return;
4210 
4211 	wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
4212 	if (wpa_s->dbus_groupobj_path == NULL)
4213 		return;
4214 
4215 	wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
4216 		   group_obj_path);
4217 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4218 	if (!obj_desc) {
4219 		wpa_printf(MSG_ERROR,
4220 			   "Not enough memory to create object description");
4221 		goto err;
4222 	}
4223 
4224 	wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
4225 			   wpas_dbus_p2p_group_properties,
4226 			   wpas_dbus_p2p_group_signals);
4227 
4228 	if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
4229 					       wpa_s->ifname, obj_desc))
4230 		goto err;
4231 
4232 	return;
4233 
4234 err:
4235 	if (wpa_s->dbus_groupobj_path) {
4236 		os_free(wpa_s->dbus_groupobj_path);
4237 		wpa_s->dbus_groupobj_path = NULL;
4238 	}
4239 
4240 	free_dbus_object_desc(obj_desc);
4241 }
4242 
4243 /**
4244  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
4245  * @wpa_s: wpa_supplicant interface structure
4246  * @ssid: network name of the p2p group started
4247  */
wpas_dbus_unregister_p2p_group(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid)4248 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
4249 				    const struct wpa_ssid *ssid)
4250 {
4251 	struct wpas_dbus_priv *ctrl_iface;
4252 
4253 	/* Do nothing if the control interface is not turned on */
4254 	if (wpa_s == NULL || wpa_s->global == NULL)
4255 		return;
4256 
4257 	if (wpa_s->p2p_mgmt)
4258 		wpa_s = wpa_s->parent;
4259 
4260 	ctrl_iface = wpa_s->global->dbus;
4261 	if (ctrl_iface == NULL)
4262 		return;
4263 
4264 	if (!wpa_s->dbus_groupobj_path) {
4265 		wpa_printf(MSG_DEBUG,
4266 			   "%s: Group object '%s' already unregistered",
4267 			   __func__, wpa_s->dbus_groupobj_path);
4268 		return;
4269 	}
4270 
4271 	peer_groups_changed(wpa_s);
4272 
4273 	wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
4274 		   wpa_s->dbus_groupobj_path);
4275 
4276 	wpa_dbus_unregister_object_per_iface(ctrl_iface,
4277 					     wpa_s->dbus_groupobj_path);
4278 
4279 	os_free(wpa_s->dbus_groupobj_path);
4280 	wpa_s->dbus_groupobj_path = NULL;
4281 }
4282 
4283 static const struct wpa_dbus_property_desc
4284 	wpas_dbus_persistent_group_properties[] = {
4285 	{ "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
4286 	  wpas_dbus_getter_persistent_group_properties,
4287 	  wpas_dbus_setter_persistent_group_properties,
4288 	  NULL
4289 	},
4290 	{ NULL, NULL, NULL, NULL, NULL, NULL }
4291 };
4292 
4293 /* No signals intended for persistent group objects */
4294 
4295 /**
4296  * wpas_dbus_register_persistent_group - Register a configured(saved)
4297  *	persistent group with dbus
4298  * @wpa_s: wpa_supplicant interface structure
4299  * @ssid: persistent group (still represented as a network within wpa)
4300  *	  configuration data
4301  * Returns: 0 on success, -1 on failure
4302  *
4303  * Registers a persistent group representing object with dbus.
4304  */
wpas_dbus_register_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)4305 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
4306 					struct wpa_ssid *ssid)
4307 {
4308 	struct wpas_dbus_priv *ctrl_iface;
4309 	struct wpa_dbus_object_desc *obj_desc;
4310 	struct network_handler_args *arg;
4311 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4312 
4313 	/* Do nothing if the control interface is not turned on */
4314 	if (wpa_s == NULL || wpa_s->global == NULL)
4315 		return 0;
4316 	wpa_s = wpa_s->parent->parent;
4317 	if (!wpa_s->dbus_new_path)
4318 		return 0;
4319 
4320 	/* Make sure ssid is a persistent group */
4321 	if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
4322 		return -1; /* should we return w/o complaining? */
4323 
4324 	if (wpa_s->p2p_mgmt)
4325 		wpa_s = wpa_s->parent;
4326 
4327 	ctrl_iface = wpa_s->global->dbus;
4328 	if (ctrl_iface == NULL)
4329 		return 0;
4330 
4331 	/*
4332 	 * Intentionally not coming up with different numbering scheme
4333 	 * for persistent groups.
4334 	 */
4335 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4336 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
4337 		    wpa_s->dbus_new_path, ssid->id);
4338 
4339 	wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
4340 		   pgrp_obj_path);
4341 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
4342 	if (!obj_desc) {
4343 		wpa_printf(MSG_ERROR,
4344 			   "dbus: Not enough memory to create object description");
4345 		goto err;
4346 	}
4347 
4348 	/*
4349 	 * Reusing the same context structure as that for networks
4350 	 * since these are represented using same data structure.
4351 	 */
4352 	/* allocate memory for handlers arguments */
4353 	arg = os_zalloc(sizeof(struct network_handler_args));
4354 	if (!arg) {
4355 		wpa_printf(MSG_ERROR,
4356 			   "dbus: Not enough memory to create arguments for method");
4357 		goto err;
4358 	}
4359 
4360 	arg->wpa_s = wpa_s;
4361 	arg->ssid = ssid;
4362 
4363 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
4364 			   wpas_dbus_persistent_group_properties,
4365 			   NULL);
4366 
4367 	if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
4368 					       wpa_s->ifname, obj_desc))
4369 		goto err;
4370 
4371 	wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
4372 
4373 	return 0;
4374 
4375 err:
4376 	free_dbus_object_desc(obj_desc);
4377 	return -1;
4378 }
4379 
4380 
4381 /**
4382  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
4383  *	from dbus
4384  * @wpa_s: wpa_supplicant interface structure
4385  * @nid: network id
4386  * Returns: 0 on success, -1 on failure
4387  *
4388  * Unregisters persistent group representing object from dbus
4389  *
4390  * NOTE: There is a slight issue with the semantics here. While the
4391  * implementation simply means the persistent group is unloaded from memory,
4392  * it should not get interpreted as the group is actually being erased/removed
4393  * from persistent storage as well.
4394  */
wpas_dbus_unregister_persistent_group(struct wpa_supplicant * wpa_s,int nid)4395 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
4396 					  int nid)
4397 {
4398 	struct wpas_dbus_priv *ctrl_iface;
4399 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
4400 	int ret;
4401 
4402 	/* Do nothing if the control interface is not turned on */
4403 	if (wpa_s == NULL || wpa_s->global == NULL)
4404 		return 0;
4405 
4406 	wpa_s = wpa_s->parent->parent;
4407 
4408 	ctrl_iface = wpa_s->global->dbus;
4409 	if (ctrl_iface == NULL || !wpa_s->dbus_new_path)
4410 		return 0;
4411 
4412 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
4413 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
4414 		    wpa_s->dbus_new_path, nid);
4415 
4416 	wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
4417 		   pgrp_obj_path);
4418 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
4419 
4420 	if (!ret)
4421 		wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
4422 
4423 	return ret;
4424 }
4425 
4426 #endif /* CONFIG_P2P */
4427