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