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