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