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