• 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 #ifdef CONFIG_P2P
873 
874 /**
875  * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed
876  * @wpa_s: %wpa_supplicant network interface data
877  * @role: role of this device (client or GO)
878  * Sends signal with i/f name and role as string arguments
879  */
wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant * wpa_s,const char * role)880 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
881 					const char *role)
882 {
883 
884 	DBusMessage *msg;
885 	DBusMessageIter iter;
886 	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
887 	char *ifname = wpa_s->ifname;
888 
889 	/* Do nothing if the control interface is not turned on */
890 	if (iface == NULL)
891 		return;
892 
893 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
894 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
895 				      "GroupFinished");
896 	if (msg == NULL)
897 		return;
898 
899 	dbus_message_iter_init_append(msg, &iter);
900 
901 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname)) {
902 		wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
903 				      "signal -not enough memory for ifname ");
904 		goto err;
905 	}
906 
907 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &role))
908 		wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
909 				      "signal -not enough memory for role ");
910 	else
911 		dbus_connection_send(iface->con, msg, NULL);
912 
913 err:
914 	dbus_message_unref(msg);
915 }
916 
917 
918 /**
919  * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events
920  *
921  * @dev_addr - who sent the request or responded to our request.
922  * @request - Will be 1 if request, 0 for response.
923  * @status - valid only in case of response
924  * @config_methods - wps config methods
925  * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method
926  *
927  * Sends following provision discovery related events:
928  *	ProvisionDiscoveryRequestDisplayPin
929  *	ProvisionDiscoveryResponseDisplayPin
930  *	ProvisionDiscoveryRequestEnterPin
931  *	ProvisionDiscoveryResponseEnterPin
932  *	ProvisionDiscoveryPBCRequest
933  *	ProvisionDiscoveryPBCResponse
934  *
935  *	TODO::
936  *	ProvisionDiscoveryFailure (timeout case)
937  */
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)938 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s,
939 					      const u8 *dev_addr, int request,
940 					      enum p2p_prov_disc_status status,
941 					      u16 config_methods,
942 					      unsigned int generated_pin)
943 {
944 	DBusMessage *msg;
945 	DBusMessageIter iter;
946 	struct wpas_dbus_priv *iface;
947 	char *_signal;
948 	int add_pin = 0;
949 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
950 	int error_ret = 1;
951 	char pin[9], *p_pin = NULL;
952 
953 	iface = wpa_s->global->dbus;
954 
955 	/* Do nothing if the control interface is not turned on */
956 	if (iface == NULL)
957 		return;
958 
959 	if (request || !status) {
960 		if (config_methods & WPS_CONFIG_DISPLAY)
961 			_signal = request ?
962 				 "ProvisionDiscoveryRequestDisplayPin" :
963 				 "ProvisionDiscoveryResponseEnterPin";
964 		else if (config_methods & WPS_CONFIG_KEYPAD)
965 			_signal = request ?
966 				 "ProvisionDiscoveryRequestEnterPin" :
967 				 "ProvisionDiscoveryResponseDisplayPin";
968 		else if (config_methods & WPS_CONFIG_PUSHBUTTON)
969 			_signal = request ? "ProvisionDiscoveryPBCRequest" :
970 				   "ProvisionDiscoveryPBCResponse";
971 		else
972 			return; /* Unknown or un-supported method */
973 	} else if (!request && status)
974 		/* Explicit check for failure response */
975 		_signal = "ProvisionDiscoveryFailure";
976 
977 	add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) ||
978 		   (!request && !status &&
979 			(config_methods & WPS_CONFIG_KEYPAD)));
980 
981 	if (add_pin) {
982 		os_snprintf(pin, sizeof(pin), "%08d", generated_pin);
983 		p_pin = pin;
984 	}
985 
986 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
987 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal);
988 	if (msg == NULL)
989 		return;
990 
991 	/* Check if this is a known peer */
992 	if (!p2p_peer_known(wpa_s->global->p2p, dev_addr))
993 		goto error;
994 
995 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
996 			"%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
997 			COMPACT_MACSTR,
998 			wpa_s->dbus_new_path, MAC2STR(dev_addr));
999 
1000 	path = peer_obj_path;
1001 
1002 	dbus_message_iter_init_append(msg, &iter);
1003 
1004 	if (!dbus_message_iter_append_basic(&iter,
1005 					    DBUS_TYPE_OBJECT_PATH,
1006 					    &path))
1007 			goto error;
1008 
1009 	if (!request && status)
1010 		/* Attach status to ProvisionDiscoveryFailure */
1011 		error_ret = !dbus_message_iter_append_basic(&iter,
1012 						    DBUS_TYPE_INT32,
1013 						    &status);
1014 	else
1015 		error_ret = (add_pin &&
1016 				 !dbus_message_iter_append_basic(&iter,
1017 							DBUS_TYPE_STRING,
1018 							&p_pin));
1019 
1020 error:
1021 	if (!error_ret)
1022 		dbus_connection_send(iface->con, msg, NULL);
1023 	else
1024 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1025 
1026 	dbus_message_unref(msg);
1027 }
1028 
1029 
wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant * wpa_s,const u8 * src,u16 dev_passwd_id)1030 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s,
1031 				     const u8 *src, u16 dev_passwd_id)
1032 {
1033 	DBusMessage *msg;
1034 	DBusMessageIter iter;
1035 	struct wpas_dbus_priv *iface;
1036 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1037 
1038 	iface = wpa_s->global->dbus;
1039 
1040 	/* Do nothing if the control interface is not turned on */
1041 	if (iface == NULL)
1042 		return;
1043 
1044 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1045 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1046 		    wpa_s->dbus_new_path, MAC2STR(src));
1047 	path = peer_obj_path;
1048 
1049 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1050 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1051 				      "GONegotiationRequest");
1052 	if (msg == NULL)
1053 		return;
1054 
1055 	dbus_message_iter_init_append(msg, &iter);
1056 
1057 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1058 					    &path) ||
1059 	    !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16,
1060 					    &dev_passwd_id))
1061 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1062 	else
1063 		dbus_connection_send(iface->con, msg, NULL);
1064 
1065 	dbus_message_unref(msg);
1066 }
1067 
1068 
wpas_dbus_get_group_obj_path(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid,char * group_obj_path)1069 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
1070 					const struct wpa_ssid *ssid,
1071 					char *group_obj_path)
1072 {
1073 	char group_name[3];
1074 
1075 	if (os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN))
1076 		return -1;
1077 
1078 	os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2);
1079 	group_name[2] = '\0';
1080 
1081 	os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1082 		    "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s",
1083 		    wpa_s->dbus_new_path, group_name);
1084 
1085 	return 0;
1086 }
1087 
1088 
1089 /**
1090  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
1091  * started. Emitted when a group is successfully started
1092  * irrespective of the role (client/GO) of the current device
1093  *
1094  * @wpa_s: %wpa_supplicant network interface data
1095  * @ssid: SSID object
1096  * @client: this device is P2P client
1097  * @network_id: network id of the group started, use instead of ssid->id
1098  *	to account for persistent groups
1099  */
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid,int client,int network_id)1100 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
1101 					const struct wpa_ssid *ssid,
1102 					int client, int network_id)
1103 {
1104 	DBusMessage *msg;
1105 	DBusMessageIter iter, dict_iter;
1106 	struct wpas_dbus_priv *iface;
1107 	char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
1108 
1109 	iface = wpa_s->parent->global->dbus;
1110 
1111 	/* Do nothing if the control interface is not turned on */
1112 	if (iface == NULL)
1113 		return;
1114 
1115 	if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
1116 		return;
1117 
1118 	/* New interface has been created for this group */
1119 	msg = dbus_message_new_signal(wpa_s->parent->dbus_new_path,
1120 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1121 				      "GroupStarted");
1122 
1123 	if (msg == NULL)
1124 		return;
1125 
1126 	dbus_message_iter_init_append(msg, &iter);
1127 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1128 		goto nomem;
1129 
1130 	/*
1131 	 * In case the device supports creating a separate interface the
1132 	 * DBus client will need to know the object path for the interface
1133 	 * object this group was created on, so include it here.
1134 	 */
1135 	if (!wpa_dbus_dict_append_object_path(&dict_iter,
1136 					"interface_object",
1137 					wpa_s->dbus_new_path))
1138 		goto nomem;
1139 
1140 	if (!wpa_dbus_dict_append_string(&dict_iter, "role",
1141 					 client ? "client" : "GO"))
1142 		goto nomem;
1143 
1144 	if (!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
1145 					     group_obj_path) ||
1146 	   !wpa_dbus_dict_close_write(&iter, &dict_iter))
1147 		goto nomem;
1148 
1149 	dbus_connection_send(iface->con, msg, NULL);
1150 
1151 nomem:
1152 	dbus_message_unref(msg);
1153 }
1154 
1155 
1156 /**
1157  *
1158  * Method to emit GONeogtiation Success or Failure signals based
1159  * on status.
1160  * @status: Status of the GO neg request. 0 for success, other for errors.
1161  */
wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant * wpa_s,struct p2p_go_neg_results * res)1162 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s,
1163 				      struct p2p_go_neg_results *res)
1164 {
1165 	DBusMessage *msg;
1166 	DBusMessageIter iter, dict_iter;
1167 	DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array;
1168 	struct wpas_dbus_priv *iface;
1169 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1170 	dbus_int32_t freqs[P2P_MAX_CHANNELS];
1171 	dbus_int32_t *f_array = freqs;
1172 
1173 
1174 	iface = wpa_s->global->dbus;
1175 
1176 	os_memset(freqs, 0, sizeof(freqs));
1177 	/* Do nothing if the control interface is not turned on */
1178 	if (iface == NULL)
1179 		return;
1180 
1181 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1182 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
1183 		    wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr));
1184 	path = peer_obj_path;
1185 
1186 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1187 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1188 				      res->status ? "GONegotiationFailure" :
1189 						    "GONegotiationSuccess");
1190 	if (msg == NULL)
1191 		return;
1192 
1193 	dbus_message_iter_init_append(msg, &iter);
1194 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1195 		goto err;
1196 	if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1197 					      path) ||
1198 	    !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status))
1199 		goto err;
1200 
1201 	if (!res->status) {
1202 		int i = 0;
1203 		int freq_list_num = 0;
1204 
1205 		if (res->role_go) {
1206 			if (!wpa_dbus_dict_append_byte_array(
1207 				    &dict_iter, "passphrase",
1208 				    (const char *) res->passphrase,
1209 				    sizeof(res->passphrase)))
1210 				goto err;
1211 		}
1212 
1213 		if (!wpa_dbus_dict_append_string(&dict_iter, "role_go",
1214 						 res->role_go ? "GO" :
1215 						 "client") ||
1216 		    !wpa_dbus_dict_append_int32(&dict_iter, "frequency",
1217 						res->freq) ||
1218 		    !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid",
1219 						     (const char *) res->ssid,
1220 						     res->ssid_len) ||
1221 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
1222 						     "peer_device_addr",
1223 						     (const char *)
1224 						     res->peer_device_addr,
1225 						     ETH_ALEN) ||
1226 		    !wpa_dbus_dict_append_byte_array(&dict_iter,
1227 						     "peer_interface_addr",
1228 						     (const char *)
1229 						     res->peer_interface_addr,
1230 						     ETH_ALEN) ||
1231 		    !wpa_dbus_dict_append_string(&dict_iter, "wps_method",
1232 						 p2p_wps_method_text(
1233 							 res->wps_method)))
1234 			goto err;
1235 
1236 		for (i = 0; i < P2P_MAX_CHANNELS; i++) {
1237 			if (res->freq_list[i]) {
1238 				freqs[i] = res->freq_list[i];
1239 				freq_list_num++;
1240 			}
1241 		}
1242 
1243 		if (!wpa_dbus_dict_begin_array(&dict_iter,
1244 					       "frequency_list",
1245 					       DBUS_TYPE_INT32_AS_STRING,
1246 					       &iter_dict_entry,
1247 					       &iter_dict_val,
1248 					       &iter_dict_array))
1249 			goto err;
1250 
1251 		if (!dbus_message_iter_append_fixed_array(&iter_dict_array,
1252 							  DBUS_TYPE_INT32,
1253 							  &f_array,
1254 							  freq_list_num))
1255 			goto err;
1256 
1257 		if (!wpa_dbus_dict_end_array(&dict_iter,
1258 					     &iter_dict_entry,
1259 					     &iter_dict_val,
1260 					     &iter_dict_array))
1261 			goto err;
1262 
1263 		if (!wpa_dbus_dict_append_int32(&dict_iter, "persistent_group",
1264 						res->persistent_group) ||
1265 		    !wpa_dbus_dict_append_uint32(&dict_iter,
1266 						 "peer_config_timeout",
1267 						 res->peer_config_timeout))
1268 			goto err;
1269 	}
1270 
1271 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1272 		goto err;
1273 
1274 	dbus_connection_send(iface->con, msg, NULL);
1275 err:
1276 	dbus_message_unref(msg);
1277 }
1278 
1279 
1280 /**
1281  *
1282  * Method to emit Invitation Result signal based on status and
1283  * bssid
1284  * @status: Status of the Invite request. 0 for success, other
1285  * for errors
1286  * @bssid : Basic Service Set Identifier
1287  */
wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant * wpa_s,int status,const u8 * bssid)1288 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s,
1289 					    int status, const u8 *bssid)
1290 {
1291 	DBusMessage *msg;
1292 	DBusMessageIter iter, dict_iter;
1293 	struct wpas_dbus_priv *iface;
1294 
1295 	wpa_printf(MSG_INFO, "%s\n", __func__);
1296 
1297 	iface = wpa_s->global->dbus;
1298 	/* Do nothing if the control interface is not turned on */
1299 	if (iface == NULL)
1300 		return;
1301 
1302 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1303 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1304 				      "InvitationResult");
1305 
1306 	if (msg == NULL)
1307 		return;
1308 
1309 	dbus_message_iter_init_append(msg, &iter);
1310 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1311 		goto nomem;
1312 
1313 	if (!wpa_dbus_dict_append_int32(&dict_iter, "status", status))
1314 		goto nomem;
1315 	if (bssid) {
1316 		if (!wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID",
1317 						     (const char *) bssid,
1318 						     ETH_ALEN))
1319 			goto nomem;
1320 	}
1321 	if (!wpa_dbus_dict_close_write(&iter, &dict_iter))
1322 		goto nomem;
1323 
1324 	dbus_connection_send(iface->con, msg, NULL);
1325 
1326 nomem:
1327 	dbus_message_unref(msg);
1328 }
1329 
1330 
1331 /**
1332  *
1333  * Method to emit a signal for a peer joining the group.
1334  * The signal will carry path to the group member object
1335  * constructed using p2p i/f addr used for connecting.
1336  *
1337  * @wpa_s: %wpa_supplicant network interface data
1338  * @member_addr: addr (p2p i/f) of the peer joining the group
1339  */
wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant * wpa_s,const u8 * member)1340 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
1341 				      const u8 *member)
1342 {
1343 	struct wpas_dbus_priv *iface;
1344 	DBusMessage *msg;
1345 	DBusMessageIter iter;
1346 	char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1347 
1348 	iface = wpa_s->global->dbus;
1349 
1350 	/* Do nothing if the control interface is not turned on */
1351 	if (iface == NULL)
1352 		return;
1353 
1354 	if (!wpa_s->dbus_groupobj_path)
1355 		return;
1356 
1357 	os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1358 			"%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
1359 			COMPACT_MACSTR,
1360 			wpa_s->dbus_groupobj_path, MAC2STR(member));
1361 
1362 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1363 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1364 				      "PeerJoined");
1365 	if (msg == NULL)
1366 		return;
1367 
1368 	dbus_message_iter_init_append(msg, &iter);
1369 	path = groupmember_obj_path;
1370 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1371 					    &path))
1372 		goto err;
1373 
1374 	dbus_connection_send(iface->con, msg, NULL);
1375 
1376 	dbus_message_unref(msg);
1377 	return;
1378 
1379 err:
1380 	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1381 	dbus_message_unref(msg);
1382 }
1383 
1384 
1385 /**
1386  *
1387  * Method to emit a signal for a peer disconnecting the group.
1388  * The signal will carry path to the group member object
1389  * constructed using p2p i/f addr used for connecting.
1390  *
1391  * @wpa_s: %wpa_supplicant network interface data
1392  * @member_addr: addr (p2p i/f) of the peer joining the group
1393  */
wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant * wpa_s,const u8 * member)1394 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
1395 				      const u8 *member)
1396 {
1397 	struct wpas_dbus_priv *iface;
1398 	DBusMessage *msg;
1399 	DBusMessageIter iter;
1400 	char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1401 
1402 	iface = wpa_s->global->dbus;
1403 
1404 	/* Do nothing if the control interface is not turned on */
1405 	if (iface == NULL)
1406 		return;
1407 
1408 	if (!wpa_s->dbus_groupobj_path)
1409 		return;
1410 
1411 	os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1412 			"%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
1413 			COMPACT_MACSTR,
1414 			wpa_s->dbus_groupobj_path, MAC2STR(member));
1415 
1416 	msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
1417 				      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
1418 				      "PeerDisconnected");
1419 	if (msg == NULL)
1420 		return;
1421 
1422 	dbus_message_iter_init_append(msg, &iter);
1423 	path = groupmember_obj_path;
1424 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1425 					    &path))
1426 		goto err;
1427 
1428 	dbus_connection_send(iface->con, msg, NULL);
1429 
1430 	dbus_message_unref(msg);
1431 	return;
1432 
1433 err:
1434 	wpa_printf(MSG_ERROR, "dbus: Failed to construct PeerDisconnected "
1435 			      "signal");
1436 	dbus_message_unref(msg);
1437 }
1438 
1439 
1440 /**
1441  *
1442  * Method to emit a signal for a service discovery request.
1443  * The signal will carry station address, frequency, dialog token,
1444  * update indicator and it tlvs
1445  *
1446  * @wpa_s: %wpa_supplicant network interface data
1447  * @sa: station addr (p2p i/f) of the peer
1448  * @dialog_token: service discovery request dialog token
1449  * @update_indic: service discovery request update indicator
1450  * @tlvs: service discovery request genrated byte array of tlvs
1451  * @tlvs_len: service discovery request tlvs length
1452  */
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)1453 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s,
1454 				     int freq, const u8 *sa, u8 dialog_token,
1455 				     u16 update_indic, const u8 *tlvs,
1456 				     size_t tlvs_len)
1457 {
1458 	DBusMessage *msg;
1459 	DBusMessageIter iter, dict_iter;
1460 	struct wpas_dbus_priv *iface;
1461 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1462 	iface = wpa_s->global->dbus;
1463 
1464 	/* Do nothing if the control interface is not turned on */
1465 	if (iface == NULL)
1466 		return;
1467 
1468 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1469 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1470 				      "ServiceDiscoveryRequest");
1471 	if (msg == NULL)
1472 		return;
1473 
1474 	/* Check if this is a known peer */
1475 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
1476 		goto error;
1477 
1478 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1479 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1480 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1481 
1482 	path = peer_obj_path;
1483 
1484 	dbus_message_iter_init_append(msg, &iter);
1485 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1486 		goto error;
1487 
1488 
1489 	if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1490 					      path) ||
1491 	    !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) ||
1492 	    !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token",
1493 					dialog_token) ||
1494 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1495 					 update_indic) ||
1496 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1497 					     (const char *) tlvs,
1498 					     tlvs_len) ||
1499 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1500 		goto error;
1501 
1502 	dbus_connection_send(iface->con, msg, NULL);
1503 	dbus_message_unref(msg);
1504 	return;
1505 error:
1506 	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1507 	dbus_message_unref(msg);
1508 }
1509 
1510 
1511 /**
1512  *
1513  * Method to emit a signal for a service discovery response.
1514  * The signal will carry station address, update indicator and it
1515  * tlvs
1516  *
1517  * @wpa_s: %wpa_supplicant network interface data
1518  * @sa: station addr (p2p i/f) of the peer
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_response(struct wpa_supplicant * wpa_s,const u8 * sa,u16 update_indic,const u8 * tlvs,size_t tlvs_len)1523 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s,
1524 				      const u8 *sa, u16 update_indic,
1525 				      const u8 *tlvs, size_t tlvs_len)
1526 {
1527 	DBusMessage *msg;
1528 	DBusMessageIter iter, dict_iter;
1529 	struct wpas_dbus_priv *iface;
1530 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1531 	iface = wpa_s->global->dbus;
1532 
1533 	/* Do nothing if the control interface is not turned on */
1534 	if (iface == NULL)
1535 		return;
1536 
1537 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1538 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1539 				"ServiceDiscoveryResponse");
1540 	if (msg == NULL)
1541 		return;
1542 
1543 	/* Check if this is a known peer */
1544 	if (!p2p_peer_known(wpa_s->global->p2p, sa))
1545 		goto error;
1546 
1547 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1548 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
1549 		    COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa));
1550 
1551 	path = peer_obj_path;
1552 
1553 	dbus_message_iter_init_append(msg, &iter);
1554 	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
1555 		goto error;
1556 
1557 	if (!wpa_dbus_dict_append_object_path(&dict_iter, "peer_object",
1558 					      path) ||
1559 	    !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator",
1560 					 update_indic) ||
1561 	    !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs",
1562 					     (const char *) tlvs,
1563 					     tlvs_len) ||
1564 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1565 		goto error;
1566 
1567 
1568 	dbus_connection_send(iface->con, msg, NULL);
1569 	dbus_message_unref(msg);
1570 	return;
1571 error:
1572 	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1573 	dbus_message_unref(msg);
1574 }
1575 
1576 /**
1577  * wpas_dbus_signal_persistent_group - Send a persistent group related
1578  *	event signal
1579  * @wpa_s: %wpa_supplicant network interface data
1580  * @id: new persistent group id
1581  * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved
1582  * @properties: determines if add second argument with object properties
1583  *
1584  * Notify listeners about an event related to persistent groups.
1585  */
wpas_dbus_signal_persistent_group(struct wpa_supplicant * wpa_s,int id,const char * sig_name,int properties)1586 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
1587 					      int id, const char *sig_name,
1588 					      int properties)
1589 {
1590 	struct wpas_dbus_priv *iface;
1591 	DBusMessage *msg;
1592 	DBusMessageIter iter;
1593 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
1594 
1595 	iface = wpa_s->global->dbus;
1596 
1597 	/* Do nothing if the control interface is not turned on */
1598 	if (iface == NULL)
1599 		return;
1600 
1601 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
1602 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
1603 		    wpa_s->dbus_new_path, id);
1604 
1605 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1606 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1607 				      sig_name);
1608 	if (msg == NULL)
1609 		return;
1610 
1611 	dbus_message_iter_init_append(msg, &iter);
1612 	path = pgrp_obj_path;
1613 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
1614 					    &path))
1615 		goto err;
1616 
1617 	if (properties) {
1618 		if (!wpa_dbus_get_object_properties(
1619 			    iface, pgrp_obj_path,
1620 			    WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter))
1621 			goto err;
1622 	}
1623 
1624 	dbus_connection_send(iface->con, msg, NULL);
1625 
1626 	dbus_message_unref(msg);
1627 	return;
1628 
1629 err:
1630 	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1631 	dbus_message_unref(msg);
1632 }
1633 
1634 
1635 /**
1636  * wpas_dbus_signal_persistent_group_added - Send a persistent_group
1637  *	added signal
1638  * @wpa_s: %wpa_supplicant network interface data
1639  * @id: new persistent group id
1640  *
1641  * Notify listeners about addition of a new persistent group.
1642  */
wpas_dbus_signal_persistent_group_added(struct wpa_supplicant * wpa_s,int id)1643 static void wpas_dbus_signal_persistent_group_added(
1644 	struct wpa_supplicant *wpa_s, int id)
1645 {
1646 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded",
1647 					  TRUE);
1648 }
1649 
1650 
1651 /**
1652  * wpas_dbus_signal_persistent_group_removed - Send a persistent_group
1653  *	removed signal
1654  * @wpa_s: %wpa_supplicant network interface data
1655  * @id: persistent group id
1656  *
1657  * Notify listeners about removal of a persistent group.
1658  */
wpas_dbus_signal_persistent_group_removed(struct wpa_supplicant * wpa_s,int id)1659 static void wpas_dbus_signal_persistent_group_removed(
1660 	struct wpa_supplicant *wpa_s, int id)
1661 {
1662 	wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved",
1663 					  FALSE);
1664 }
1665 
1666 
1667 /**
1668  * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event
1669  * @wpa_s: %wpa_supplicant network interface data
1670  *
1671  * Sends Event dbus signal with name "fail" and dictionary containing
1672  * "msg" field with fail message number (int32) as arguments
1673  */
wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant * wpa_s,struct wps_event_fail * fail)1674 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
1675 				     struct wps_event_fail *fail)
1676 {
1677 
1678 	DBusMessage *msg;
1679 	DBusMessageIter iter, dict_iter;
1680 	struct wpas_dbus_priv *iface;
1681 	char *key = "fail";
1682 
1683 	iface = wpa_s->global->dbus;
1684 
1685 	/* Do nothing if the control interface is not turned on */
1686 	if (iface == NULL)
1687 		return;
1688 
1689 	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
1690 				      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
1691 				      "WpsFailed");
1692 	if (msg == NULL)
1693 		return;
1694 
1695 	dbus_message_iter_init_append(msg, &iter);
1696 
1697 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
1698 	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
1699 	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
1700 	    !wpa_dbus_dict_append_int16(&dict_iter, "config_error",
1701 					fail->config_error) ||
1702 	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
1703 		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
1704 	else
1705 		dbus_connection_send(iface->con, msg, NULL);
1706 
1707 	dbus_message_unref(msg);
1708 }
1709 
1710 #endif /*CONFIG_P2P*/
1711 
1712 
1713 /**
1714  * wpas_dbus_signal_prop_changed - Signals change of property
1715  * @wpa_s: %wpa_supplicant network interface data
1716  * @property: indicates which property has changed
1717  *
1718  * Sends PropertyChanged signals with path, interface and arguments
1719  * depending on which property has changed.
1720  */
wpas_dbus_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_prop property)1721 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
1722 				   enum wpas_dbus_prop property)
1723 {
1724 	char *prop;
1725 	dbus_bool_t flush;
1726 
1727 	if (wpa_s->dbus_new_path == NULL)
1728 		return; /* Skip signal since D-Bus setup is not yet ready */
1729 
1730 	flush = FALSE;
1731 	switch (property) {
1732 	case WPAS_DBUS_PROP_AP_SCAN:
1733 		prop = "ApScan";
1734 		break;
1735 	case WPAS_DBUS_PROP_SCANNING:
1736 		prop = "Scanning";
1737 		break;
1738 	case WPAS_DBUS_PROP_STATE:
1739 		prop = "State";
1740 		break;
1741 	case WPAS_DBUS_PROP_CURRENT_BSS:
1742 		prop = "CurrentBSS";
1743 		break;
1744 	case WPAS_DBUS_PROP_CURRENT_NETWORK:
1745 		prop = "CurrentNetwork";
1746 		break;
1747 	case WPAS_DBUS_PROP_BSSS:
1748 		prop = "BSSs";
1749 		break;
1750 	case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
1751 		prop = "CurrentAuthMode";
1752 		break;
1753 	case WPAS_DBUS_PROP_DISCONNECT_REASON:
1754 		prop = "DisconnectReason";
1755 		flush = TRUE;
1756 		break;
1757 	default:
1758 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
1759 			   __func__, property);
1760 		return;
1761 	}
1762 
1763 	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
1764 				       wpa_s->dbus_new_path,
1765 				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
1766 	if (flush) {
1767 		wpa_dbus_flush_object_changed_properties(
1768 			wpa_s->global->dbus->con, wpa_s->dbus_new_path);
1769 	}
1770 }
1771 
1772 
1773 /**
1774  * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
1775  * @wpa_s: %wpa_supplicant network interface data
1776  * @property: indicates which property has changed
1777  * @id: unique BSS identifier
1778  *
1779  * Sends PropertyChanged signals with path, interface, and arguments depending
1780  * on which property has changed.
1781  */
wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant * wpa_s,enum wpas_dbus_bss_prop property,unsigned int id)1782 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
1783 				       enum wpas_dbus_bss_prop property,
1784 				       unsigned int id)
1785 {
1786 	char path[WPAS_DBUS_OBJECT_PATH_MAX];
1787 	char *prop;
1788 
1789 	switch (property) {
1790 	case WPAS_DBUS_BSS_PROP_SIGNAL:
1791 		prop = "Signal";
1792 		break;
1793 	case WPAS_DBUS_BSS_PROP_FREQ:
1794 		prop = "Frequency";
1795 		break;
1796 	case WPAS_DBUS_BSS_PROP_MODE:
1797 		prop = "Mode";
1798 		break;
1799 	case WPAS_DBUS_BSS_PROP_PRIVACY:
1800 		prop = "Privacy";
1801 		break;
1802 	case WPAS_DBUS_BSS_PROP_RATES:
1803 		prop = "Rates";
1804 		break;
1805 	case WPAS_DBUS_BSS_PROP_WPA:
1806 		prop = "WPA";
1807 		break;
1808 	case WPAS_DBUS_BSS_PROP_RSN:
1809 		prop = "RSN";
1810 		break;
1811 	case WPAS_DBUS_BSS_PROP_WPS:
1812 		prop = "WPS";
1813 		break;
1814 	case WPAS_DBUS_BSS_PROP_IES:
1815 		prop = "IEs";
1816 		break;
1817 	default:
1818 		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
1819 			   __func__, property);
1820 		return;
1821 	}
1822 
1823 	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
1824 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
1825 		    wpa_s->dbus_new_path, id);
1826 
1827 	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
1828 				       WPAS_DBUS_NEW_IFACE_BSS, prop);
1829 }
1830 
1831 
1832 /**
1833  * wpas_dbus_signal_debug_level_changed - Signals change of debug param
1834  * @global: wpa_global structure
1835  *
1836  * Sends PropertyChanged signals informing that debug level has changed.
1837  */
wpas_dbus_signal_debug_level_changed(struct wpa_global * global)1838 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
1839 {
1840 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1841 				       WPAS_DBUS_NEW_INTERFACE,
1842 				       "DebugLevel");
1843 }
1844 
1845 
1846 /**
1847  * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
1848  * @global: wpa_global structure
1849  *
1850  * Sends PropertyChanged signals informing that debug timestamp has changed.
1851  */
wpas_dbus_signal_debug_timestamp_changed(struct wpa_global * global)1852 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
1853 {
1854 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1855 				       WPAS_DBUS_NEW_INTERFACE,
1856 				       "DebugTimestamp");
1857 }
1858 
1859 
1860 /**
1861  * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
1862  * @global: wpa_global structure
1863  *
1864  * Sends PropertyChanged signals informing that debug show_keys has changed.
1865  */
wpas_dbus_signal_debug_show_keys_changed(struct wpa_global * global)1866 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
1867 {
1868 	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
1869 				       WPAS_DBUS_NEW_INTERFACE,
1870 				       "DebugShowKeys");
1871 }
1872 
1873 
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)1874 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
1875 			       void *priv,
1876 			       WPADBusArgumentFreeFunction priv_free,
1877 			       const struct wpa_dbus_method_desc *methods,
1878 			       const struct wpa_dbus_property_desc *properties,
1879 			       const struct wpa_dbus_signal_desc *signals)
1880 {
1881 	int n;
1882 
1883 	obj_desc->user_data = priv;
1884 	obj_desc->user_data_free_func = priv_free;
1885 	obj_desc->methods = methods;
1886 	obj_desc->properties = properties;
1887 	obj_desc->signals = signals;
1888 
1889 	for (n = 0; properties && properties->dbus_property; properties++)
1890 		n++;
1891 
1892 	obj_desc->prop_changed_flags = os_zalloc(n);
1893 	if (!obj_desc->prop_changed_flags)
1894 		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
1895 			   __func__);
1896 }
1897 
1898 
1899 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
1900 	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
1901 	  (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
1902 	  {
1903 		  { "args", "a{sv}", ARG_IN },
1904 		  { "path", "o", ARG_OUT },
1905 		  END_ARGS
1906 	  }
1907 	},
1908 	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
1909 	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
1910 	  {
1911 		  { "path", "o", ARG_IN },
1912 		  END_ARGS
1913 	  }
1914 	},
1915 	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
1916 	  (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
1917 	  {
1918 		  { "ifname", "s", ARG_IN },
1919 		  { "path", "o", ARG_OUT },
1920 		  END_ARGS
1921 	  }
1922 	},
1923 #ifdef CONFIG_AUTOSCAN
1924 	{ "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE,
1925 	  (WPADBusMethodHandler) &wpas_dbus_handler_autoscan,
1926 	  {
1927 		  { "arg", "s", ARG_IN },
1928 		  END_ARGS
1929 	  }
1930 	},
1931 #endif /* CONFIG_AUTOSCAN */
1932 	{ NULL, NULL, NULL, { END_ARGS } }
1933 };
1934 
1935 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
1936 	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
1937 	  wpas_dbus_getter_debug_level,
1938 	  wpas_dbus_setter_debug_level
1939 	},
1940 	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
1941 	  wpas_dbus_getter_debug_timestamp,
1942 	  wpas_dbus_setter_debug_timestamp
1943 	},
1944 	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
1945 	  wpas_dbus_getter_debug_show_keys,
1946 	  wpas_dbus_setter_debug_show_keys
1947 	},
1948 	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
1949 	  wpas_dbus_getter_interfaces,
1950 	  NULL
1951 	},
1952 	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
1953 	  wpas_dbus_getter_eap_methods,
1954 	  NULL
1955 	},
1956 	{ "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
1957 	  wpas_dbus_getter_global_capabilities,
1958 	  NULL
1959 	},
1960 	{ NULL, NULL, NULL, NULL, NULL }
1961 };
1962 
1963 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
1964 	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
1965 	  {
1966 		  { "path", "o", ARG_OUT },
1967 		  { "properties", "a{sv}", ARG_OUT },
1968 		  END_ARGS
1969 	  }
1970 	},
1971 	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
1972 	  {
1973 		  { "path", "o", ARG_OUT },
1974 		  END_ARGS
1975 	  }
1976 	},
1977 	{ "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
1978 	  {
1979 		  { "path", "o", ARG_OUT },
1980 		  { "field", "s", ARG_OUT },
1981 		  { "text", "s", ARG_OUT },
1982 		  END_ARGS
1983 	  }
1984 	},
1985 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
1986 	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
1987 	  {
1988 		  { "properties", "a{sv}", ARG_OUT },
1989 		  END_ARGS
1990 	  }
1991 	},
1992 	{ NULL, NULL, { END_ARGS } }
1993 };
1994 
1995 
1996 /**
1997  * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
1998  * @global: Pointer to global data from wpa_supplicant_init()
1999  * Returns: 0 on success or -1 on failure
2000  *
2001  * Initialize the dbus control interface for wpa_supplicantand and start
2002  * receiving commands from external programs over the bus.
2003  */
wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv * priv)2004 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
2005 {
2006 	struct wpa_dbus_object_desc *obj_desc;
2007 	int ret;
2008 
2009 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2010 	if (!obj_desc) {
2011 		wpa_printf(MSG_ERROR, "Not enough memory "
2012 			   "to create object description");
2013 		return -1;
2014 	}
2015 
2016 	wpas_dbus_register(obj_desc, priv->global, NULL,
2017 			   wpas_dbus_global_methods,
2018 			   wpas_dbus_global_properties,
2019 			   wpas_dbus_global_signals);
2020 
2021 	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
2022 		   WPAS_DBUS_NEW_PATH);
2023 	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
2024 				       WPAS_DBUS_NEW_SERVICE,
2025 				       obj_desc);
2026 	if (ret < 0)
2027 		free_dbus_object_desc(obj_desc);
2028 	else
2029 		priv->dbus_new_initialized = 1;
2030 
2031 	return ret;
2032 }
2033 
2034 
2035 /**
2036  * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
2037  * wpa_supplicant
2038  * @iface: Pointer to dbus private data from wpas_dbus_init()
2039  *
2040  * Deinitialize the dbus control interface that was initialized with
2041  * wpas_dbus_ctrl_iface_init().
2042  */
wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv * iface)2043 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
2044 {
2045 	if (!iface->dbus_new_initialized)
2046 		return;
2047 	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
2048 		   WPAS_DBUS_NEW_PATH);
2049 	dbus_connection_unregister_object_path(iface->con,
2050 					       WPAS_DBUS_NEW_PATH);
2051 }
2052 
2053 
wpa_dbus_free(void * ptr)2054 static void wpa_dbus_free(void *ptr)
2055 {
2056 	os_free(ptr);
2057 }
2058 
2059 
2060 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
2061 	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
2062 	  wpas_dbus_getter_network_properties,
2063 	  wpas_dbus_setter_network_properties
2064 	},
2065 	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
2066 	  wpas_dbus_getter_enabled,
2067 	  wpas_dbus_setter_enabled
2068 	},
2069 	{ NULL, NULL, NULL, NULL, NULL }
2070 };
2071 
2072 
2073 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
2074 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2075 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
2076 	  {
2077 		  { "properties", "a{sv}", ARG_OUT },
2078 		  END_ARGS
2079 	  }
2080 	},
2081 	{ NULL, NULL, { END_ARGS } }
2082 };
2083 
2084 
2085 /**
2086  * wpas_dbus_register_network - Register a configured network with dbus
2087  * @wpa_s: wpa_supplicant interface structure
2088  * @ssid: network configuration data
2089  * Returns: 0 on success, -1 on failure
2090  *
2091  * Registers network representing object with dbus
2092  */
wpas_dbus_register_network(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)2093 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
2094 			       struct wpa_ssid *ssid)
2095 {
2096 	struct wpas_dbus_priv *ctrl_iface;
2097 	struct wpa_dbus_object_desc *obj_desc;
2098 	struct network_handler_args *arg;
2099 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2100 
2101 #ifdef CONFIG_P2P
2102 	/*
2103 	 * If it is a persistent group register it as such.
2104 	 * This is to handle cases where an interface is being initialized
2105 	 * with a list of networks read from config.
2106 	 */
2107 	if (network_is_persistent_group(ssid))
2108 		return wpas_dbus_register_persistent_group(wpa_s, ssid);
2109 #endif /* CONFIG_P2P */
2110 
2111 	/* Do nothing if the control interface is not turned on */
2112 	if (wpa_s == NULL || wpa_s->global == NULL)
2113 		return 0;
2114 	ctrl_iface = wpa_s->global->dbus;
2115 	if (ctrl_iface == NULL)
2116 		return 0;
2117 
2118 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2119 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2120 		    wpa_s->dbus_new_path, ssid->id);
2121 
2122 	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
2123 		   net_obj_path);
2124 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2125 	if (!obj_desc) {
2126 		wpa_printf(MSG_ERROR, "Not enough memory "
2127 			   "to create object description");
2128 		goto err;
2129 	}
2130 
2131 	/* allocate memory for handlers arguments */
2132 	arg = os_zalloc(sizeof(struct network_handler_args));
2133 	if (!arg) {
2134 		wpa_printf(MSG_ERROR, "Not enough memory "
2135 			   "to create arguments for method");
2136 		goto err;
2137 	}
2138 
2139 	arg->wpa_s = wpa_s;
2140 	arg->ssid = ssid;
2141 
2142 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2143 			   wpas_dbus_network_properties,
2144 			   wpas_dbus_network_signals);
2145 
2146 	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
2147 					       wpa_s->ifname, obj_desc))
2148 		goto err;
2149 
2150 	wpas_dbus_signal_network_added(wpa_s, ssid->id);
2151 
2152 	return 0;
2153 
2154 err:
2155 	free_dbus_object_desc(obj_desc);
2156 	return -1;
2157 }
2158 
2159 
2160 /**
2161  * wpas_dbus_unregister_network - Unregister a configured network from dbus
2162  * @wpa_s: wpa_supplicant interface structure
2163  * @nid: network id
2164  * Returns: 0 on success, -1 on failure
2165  *
2166  * Unregisters network representing object from dbus
2167  */
wpas_dbus_unregister_network(struct wpa_supplicant * wpa_s,int nid)2168 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
2169 {
2170 	struct wpas_dbus_priv *ctrl_iface;
2171 	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2172 	int ret;
2173 #ifdef CONFIG_P2P
2174 	struct wpa_ssid *ssid;
2175 
2176 	ssid = wpa_config_get_network(wpa_s->conf, nid);
2177 
2178 	/* If it is a persistent group unregister it as such */
2179 	if (ssid && network_is_persistent_group(ssid))
2180 		return wpas_dbus_unregister_persistent_group(wpa_s, nid);
2181 #endif /* CONFIG_P2P */
2182 
2183 	/* Do nothing if the control interface is not turned on */
2184 	if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL)
2185 		return 0;
2186 	ctrl_iface = wpa_s->global->dbus;
2187 	if (ctrl_iface == NULL)
2188 		return 0;
2189 
2190 	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2191 		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
2192 		    wpa_s->dbus_new_path, nid);
2193 
2194 	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
2195 		   net_obj_path);
2196 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
2197 
2198 	if (!ret)
2199 		wpas_dbus_signal_network_removed(wpa_s, nid);
2200 
2201 	return ret;
2202 }
2203 
2204 
2205 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
2206 	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2207 	  wpas_dbus_getter_bss_ssid,
2208 	  NULL
2209 	},
2210 	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2211 	  wpas_dbus_getter_bss_bssid,
2212 	  NULL
2213 	},
2214 	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
2215 	  wpas_dbus_getter_bss_privacy,
2216 	  NULL
2217 	},
2218 	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
2219 	  wpas_dbus_getter_bss_mode,
2220 	  NULL
2221 	},
2222 	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
2223 	  wpas_dbus_getter_bss_signal,
2224 	  NULL
2225 	},
2226 	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
2227 	  wpas_dbus_getter_bss_frequency,
2228 	  NULL
2229 	},
2230 	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
2231 	  wpas_dbus_getter_bss_rates,
2232 	  NULL
2233 	},
2234 	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2235 	  wpas_dbus_getter_bss_wpa,
2236 	  NULL
2237 	},
2238 	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2239 	  wpas_dbus_getter_bss_rsn,
2240 	  NULL
2241 	},
2242 	{ "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
2243 	  wpas_dbus_getter_bss_wps,
2244 	  NULL
2245 	},
2246 	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
2247 	  wpas_dbus_getter_bss_ies,
2248 	  NULL
2249 	},
2250 	{ NULL, NULL, NULL, NULL, NULL }
2251 };
2252 
2253 
2254 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
2255 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2256 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
2257 	  {
2258 		  { "properties", "a{sv}", ARG_OUT },
2259 		  END_ARGS
2260 	  }
2261 	},
2262 	{ NULL, NULL, { END_ARGS } }
2263 };
2264 
2265 
2266 /**
2267  * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
2268  * @wpa_s: wpa_supplicant interface structure
2269  * @bssid: scanned network bssid
2270  * @id: unique BSS identifier
2271  * Returns: 0 on success, -1 on failure
2272  *
2273  * Unregisters BSS representing object from dbus
2274  */
wpas_dbus_unregister_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)2275 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
2276 			     u8 bssid[ETH_ALEN], unsigned int id)
2277 {
2278 	struct wpas_dbus_priv *ctrl_iface;
2279 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2280 
2281 	/* Do nothing if the control interface is not turned on */
2282 	if (wpa_s == NULL || wpa_s->global == NULL)
2283 		return 0;
2284 	ctrl_iface = wpa_s->global->dbus;
2285 	if (ctrl_iface == NULL)
2286 		return 0;
2287 
2288 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2289 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2290 		    wpa_s->dbus_new_path, id);
2291 
2292 	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
2293 		   bss_obj_path);
2294 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
2295 		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
2296 			   bss_obj_path);
2297 		return -1;
2298 	}
2299 
2300 	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
2301 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2302 
2303 	return 0;
2304 }
2305 
2306 
2307 /**
2308  * wpas_dbus_register_bss - Register a scanned BSS with dbus
2309  * @wpa_s: wpa_supplicant interface structure
2310  * @bssid: scanned network bssid
2311  * @id: unique BSS identifier
2312  * Returns: 0 on success, -1 on failure
2313  *
2314  * Registers BSS representing object with dbus
2315  */
wpas_dbus_register_bss(struct wpa_supplicant * wpa_s,u8 bssid[ETH_ALEN],unsigned int id)2316 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
2317 			   u8 bssid[ETH_ALEN], unsigned int id)
2318 {
2319 	struct wpas_dbus_priv *ctrl_iface;
2320 	struct wpa_dbus_object_desc *obj_desc;
2321 	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
2322 	struct bss_handler_args *arg;
2323 
2324 	/* Do nothing if the control interface is not turned on */
2325 	if (wpa_s == NULL || wpa_s->global == NULL)
2326 		return 0;
2327 	ctrl_iface = wpa_s->global->dbus;
2328 	if (ctrl_iface == NULL)
2329 		return 0;
2330 
2331 	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
2332 		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
2333 		    wpa_s->dbus_new_path, id);
2334 
2335 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
2336 	if (!obj_desc) {
2337 		wpa_printf(MSG_ERROR, "Not enough memory "
2338 			   "to create object description");
2339 		goto err;
2340 	}
2341 
2342 	arg = os_zalloc(sizeof(struct bss_handler_args));
2343 	if (!arg) {
2344 		wpa_printf(MSG_ERROR, "Not enough memory "
2345 			   "to create arguments for handler");
2346 		goto err;
2347 	}
2348 	arg->wpa_s = wpa_s;
2349 	arg->id = id;
2350 
2351 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
2352 			   wpas_dbus_bss_properties,
2353 			   wpas_dbus_bss_signals);
2354 
2355 	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
2356 		   bss_obj_path);
2357 	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
2358 					       wpa_s->ifname, obj_desc)) {
2359 		wpa_printf(MSG_ERROR,
2360 			   "Cannot register BSSID dbus object %s.",
2361 			   bss_obj_path);
2362 		goto err;
2363 	}
2364 
2365 	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
2366 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
2367 
2368 	return 0;
2369 
2370 err:
2371 	free_dbus_object_desc(obj_desc);
2372 	return -1;
2373 }
2374 
2375 
2376 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
2377 	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
2378 	  (WPADBusMethodHandler) &wpas_dbus_handler_scan,
2379 	  {
2380 		  { "args", "a{sv}", ARG_IN },
2381 		  END_ARGS
2382 	  }
2383 	},
2384 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
2385 	  (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
2386 	  {
2387 		  END_ARGS
2388 	  }
2389 	},
2390 	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2391 	  (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
2392 	  {
2393 		  { "args", "a{sv}", ARG_IN },
2394 		  { "path", "o", ARG_OUT },
2395 		  END_ARGS
2396 	  }
2397 	},
2398 	{ "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE,
2399 	  (WPADBusMethodHandler) &wpas_dbus_handler_reassociate,
2400 	  {
2401 		  END_ARGS
2402 	  }
2403 	},
2404 	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2405 	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
2406 	  {
2407 		  { "path", "o", ARG_IN },
2408 		  END_ARGS
2409 	  }
2410 	},
2411 	{ "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
2412 	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks,
2413 	  {
2414 		  END_ARGS
2415 	  }
2416 	},
2417 	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
2418 	  (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
2419 	  {
2420 		  { "path", "o", ARG_IN },
2421 		  END_ARGS
2422 	  }
2423 	},
2424 	{ "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE,
2425 	  (WPADBusMethodHandler) &wpas_dbus_handler_network_reply,
2426 	  {
2427 		  { "path", "o", ARG_IN },
2428 		  { "field", "s", ARG_IN },
2429 		  { "value", "s", ARG_IN },
2430 		  END_ARGS
2431 	  }
2432 	},
2433 #ifndef CONFIG_NO_CONFIG_BLOBS
2434 	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2435 	  (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
2436 	  {
2437 		  { "name", "s", ARG_IN },
2438 		  { "data", "ay", ARG_IN },
2439 		  END_ARGS
2440 	  }
2441 	},
2442 	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2443 	  (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
2444 	  {
2445 		  { "name", "s", ARG_IN },
2446 		  { "data", "ay", ARG_OUT },
2447 		  END_ARGS
2448 	  }
2449 	},
2450 	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
2451 	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
2452 	  {
2453 		  { "name", "s", ARG_IN },
2454 		  END_ARGS
2455 	  }
2456 	},
2457 #endif /* CONFIG_NO_CONFIG_BLOBS */
2458 #ifdef CONFIG_WPS
2459 	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
2460 	  (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
2461 	  {
2462 		  { "args", "a{sv}", ARG_IN },
2463 		  { "output", "a{sv}", ARG_OUT },
2464 		  END_ARGS
2465 	  }
2466 	},
2467 #endif /* CONFIG_WPS */
2468 #ifdef CONFIG_P2P
2469 	{ "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2470 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_find,
2471 	  {
2472 		  { "args", "a{sv}", ARG_IN },
2473 		  END_ARGS
2474 	  }
2475 	},
2476 	{ "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2477 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_stop_find,
2478 	  {
2479 		  END_ARGS
2480 	  }
2481 	},
2482 	{ "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2483 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_listen,
2484 	  {
2485 		  { "timeout", "i", ARG_IN },
2486 		  END_ARGS
2487 	  }
2488 	},
2489 	{ "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2490 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_extendedlisten,
2491 	  {
2492 		  { "args", "a{sv}", ARG_IN },
2493 		  END_ARGS
2494 	  }
2495 	},
2496 	{ "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2497 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_presence_request,
2498 	  {
2499 		  { "args", "a{sv}", ARG_IN },
2500 		  END_ARGS
2501 	  }
2502 	},
2503 	{ "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2504 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_prov_disc_req,
2505 	  {
2506 		  { "peer", "o", ARG_IN },
2507 		  { "config_method", "s", ARG_IN },
2508 		  END_ARGS
2509 	  }
2510 	},
2511 	{ "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2512 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_connect,
2513 	  {
2514 		  { "args", "a{sv}", ARG_IN },
2515 		  { "generated_pin", "s", ARG_OUT },
2516 		  END_ARGS
2517 	  }
2518 	},
2519 	{ "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2520 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_group_add,
2521 	  {
2522 		  { "args", "a{sv}", ARG_IN },
2523 		  END_ARGS
2524 	  }
2525 	},
2526 	{ "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2527 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_invite,
2528 	  {
2529 		  { "args", "a{sv}", ARG_IN },
2530 		  END_ARGS
2531 	  }
2532 	},
2533 	{ "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2534 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_disconnect,
2535 	  {
2536 		  END_ARGS
2537 	  }
2538 	},
2539 	{ "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2540 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_rejectpeer,
2541 	  {
2542 		  { "peer", "o", ARG_IN },
2543 		  END_ARGS
2544 	  }
2545 	},
2546 	{ "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2547 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush,
2548 	  {
2549 		  END_ARGS
2550 	  }
2551 	},
2552 	{ "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2553 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_add_service,
2554 	  {
2555 		  { "args", "a{sv}", ARG_IN },
2556 		  END_ARGS
2557 	  }
2558 	},
2559 	{ "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2560 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_delete_service,
2561 	  {
2562 		  { "args", "a{sv}", ARG_IN },
2563 		  END_ARGS
2564 	  }
2565 	},
2566 	{ "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2567 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush_service,
2568 	  {
2569 		  END_ARGS
2570 	  }
2571 	},
2572 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2573 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req,
2574 	  {
2575 		  { "args", "a{sv}", ARG_IN },
2576 		  END_ARGS
2577 	  }
2578 	},
2579 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2580 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_res,
2581 	  {
2582 		  { "args", "a{sv}", ARG_IN },
2583 		  END_ARGS
2584 	  }
2585 	},
2586 	{ "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2587 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_cancel_req,
2588 	  {
2589 		  { "args", "t", ARG_IN },
2590 		  END_ARGS
2591 	  }
2592 	},
2593 	{ "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2594 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_update,
2595 	  {
2596 		  END_ARGS
2597 	  }
2598 	},
2599 	{ "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2600 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
2601 	  {
2602 		  { "arg", "i", ARG_IN },
2603 		  END_ARGS
2604 	  }
2605 	},
2606 	{ "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2607 	  (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external,
2608 	  {
2609 		  { "arg", "i", ARG_IN },
2610 		  END_ARGS
2611 	  }
2612 	},
2613 	{ "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2614 	  (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group,
2615 	  {
2616 		  { "args", "a{sv}", ARG_IN },
2617 		  { "path", "o", ARG_OUT },
2618 		  END_ARGS
2619 	  }
2620 	},
2621 	{ "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2622 	  (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group,
2623 	  {
2624 		  { "path", "o", ARG_IN },
2625 		  END_ARGS
2626 	  }
2627 	},
2628 	{ "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2629 	  (WPADBusMethodHandler)
2630 	  wpas_dbus_handler_remove_all_persistent_groups,
2631 	  {
2632 		  END_ARGS
2633 	  }
2634 	},
2635 #endif /* CONFIG_P2P */
2636 	{ "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
2637 	  (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss,
2638 	  {
2639 		  { "age", "u", ARG_IN },
2640 		  END_ARGS
2641 	  }
2642 	},
2643 #ifdef CONFIG_AP
2644 	{ "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
2645 	  (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq,
2646 	  {
2647 		  END_ARGS
2648 	  }
2649 	},
2650 	{ "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE,
2651 	  (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq,
2652 	  {
2653 		  END_ARGS
2654 	  }
2655 	},
2656 #endif /* CONFIG_AP */
2657 	{ NULL, NULL, NULL, { END_ARGS } }
2658 };
2659 
2660 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
2661 	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
2662 	  wpas_dbus_getter_capabilities,
2663 	  NULL
2664 	},
2665 	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2666 	  wpas_dbus_getter_state,
2667 	  NULL
2668 	},
2669 	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2670 	  wpas_dbus_getter_scanning,
2671 	  NULL
2672 	},
2673 	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2674 	  wpas_dbus_getter_ap_scan,
2675 	  wpas_dbus_setter_ap_scan
2676 	},
2677 	{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2678 	  wpas_dbus_getter_bss_expire_age,
2679 	  wpas_dbus_setter_bss_expire_age
2680 	},
2681 	{ "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
2682 	  wpas_dbus_getter_bss_expire_count,
2683 	  wpas_dbus_setter_bss_expire_count
2684 	},
2685 	{ "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2686 	  wpas_dbus_getter_country,
2687 	  wpas_dbus_setter_country
2688 	},
2689 	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2690 	  wpas_dbus_getter_ifname,
2691 	  NULL
2692 	},
2693 	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2694 	  wpas_dbus_getter_driver,
2695 	  NULL
2696 	},
2697 	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2698 	  wpas_dbus_getter_bridge_ifname,
2699 	  NULL
2700 	},
2701 	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2702 	  wpas_dbus_getter_current_bss,
2703 	  NULL
2704 	},
2705 	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
2706 	  wpas_dbus_getter_current_network,
2707 	  NULL
2708 	},
2709 	{ "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
2710 	  wpas_dbus_getter_current_auth_mode,
2711 	  NULL
2712 	},
2713 	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
2714 	  wpas_dbus_getter_blobs,
2715 	  NULL
2716 	},
2717 	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2718 	  wpas_dbus_getter_bsss,
2719 	  NULL
2720 	},
2721 	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
2722 	  wpas_dbus_getter_networks,
2723 	  NULL
2724 	},
2725 	{ "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
2726 	  wpas_dbus_getter_fast_reauth,
2727 	  wpas_dbus_setter_fast_reauth
2728 	},
2729 	{ "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
2730 	  wpas_dbus_getter_scan_interval,
2731 	  wpas_dbus_setter_scan_interval
2732 	},
2733 #ifdef CONFIG_WPS
2734 	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
2735 	  wpas_dbus_getter_process_credentials,
2736 	  wpas_dbus_setter_process_credentials
2737 	},
2738 #endif /* CONFIG_WPS */
2739 #ifdef CONFIG_P2P
2740 	{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
2741 	  wpas_dbus_getter_p2p_device_config,
2742 	  wpas_dbus_setter_p2p_device_config
2743 	},
2744 	{ "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2745 	  wpas_dbus_getter_p2p_peers,
2746 	  NULL
2747 	},
2748 	{ "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
2749 	  wpas_dbus_getter_p2p_role,
2750 	  NULL
2751 	},
2752 	{ "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2753 	  wpas_dbus_getter_p2p_group,
2754 	  NULL
2755 	},
2756 	{ "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
2757 	  wpas_dbus_getter_p2p_peergo,
2758 	  NULL
2759 	},
2760 	{ "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
2761 	  wpas_dbus_getter_persistent_groups,
2762 	  NULL
2763 	},
2764 #endif /* CONFIG_P2P */
2765 	{ "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
2766 	  wpas_dbus_getter_disconnect_reason,
2767 	  NULL
2768 	},
2769 	{ NULL, NULL, NULL, NULL, NULL }
2770 };
2771 
2772 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
2773 	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
2774 	  {
2775 		  { "success", "b", ARG_OUT },
2776 		  END_ARGS
2777 	  }
2778 	},
2779 	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2780 	  {
2781 		  { "path", "o", ARG_OUT },
2782 		  { "properties", "a{sv}", ARG_OUT },
2783 		  END_ARGS
2784 	  }
2785 	},
2786 	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2787 	  {
2788 		  { "path", "o", ARG_OUT },
2789 		  END_ARGS
2790 	  }
2791 	},
2792 	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2793 	  {
2794 		  { "name", "s", ARG_OUT },
2795 		  END_ARGS
2796 	  }
2797 	},
2798 	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2799 	  {
2800 		  { "name", "s", ARG_OUT },
2801 		  END_ARGS
2802 	  }
2803 	},
2804 	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
2805 	  {
2806 		  { "path", "o", ARG_OUT },
2807 		  { "properties", "a{sv}", ARG_OUT },
2808 		  END_ARGS
2809 	  }
2810 	},
2811 	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
2812 	  {
2813 		  { "path", "o", ARG_OUT },
2814 		  END_ARGS
2815 	  }
2816 	},
2817 	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
2818 	  {
2819 		  { "path", "o", ARG_OUT },
2820 		  END_ARGS
2821 	  }
2822 	},
2823 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2824 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
2825 	  {
2826 		  { "properties", "a{sv}", ARG_OUT },
2827 		  END_ARGS
2828 	  }
2829 	},
2830 #ifdef CONFIG_WPS
2831 	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
2832 	  {
2833 		  { "name", "s", ARG_OUT },
2834 		  { "args", "a{sv}", ARG_OUT },
2835 		  END_ARGS
2836 	  }
2837 	},
2838 	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
2839 	  {
2840 		  { "credentials", "a{sv}", ARG_OUT },
2841 		  END_ARGS
2842 	  }
2843 	},
2844 	/* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
2845 	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
2846 	  {
2847 		  { "properties", "a{sv}", ARG_OUT },
2848 		  END_ARGS
2849 	  }
2850 	},
2851 #endif /* CONFIG_WPS */
2852 #ifdef CONFIG_P2P
2853 	{ "P2PStateChanged", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2854 	  {
2855 		  { "states", "a{ss}", ARG_OUT },
2856 		  END_ARGS
2857 	  }
2858 	},
2859 	{ "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2860 	  {
2861 		  { "path", "o", ARG_OUT },
2862 		  { "properties", "a{sv}", ARG_OUT },
2863 		  END_ARGS
2864 	  }
2865 	},
2866 	{ "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2867 	  {
2868 		  { "path", "o", ARG_OUT },
2869 		  END_ARGS
2870 	  }
2871 	},
2872 	{ "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2873 	  {
2874 		  { "peer_object", "o", ARG_OUT },
2875 		  { "pin", "s", ARG_OUT },
2876 		  END_ARGS
2877 	  }
2878 	},
2879 	{ "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2880 	  {
2881 		  { "peer_object", "o", ARG_OUT },
2882 		  { "pin", "s", ARG_OUT },
2883 		  END_ARGS
2884 	  }
2885 	},
2886 	{ "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2887 	  {
2888 		  { "peer_object", "o", ARG_OUT },
2889 		  END_ARGS
2890 	  }
2891 	},
2892 	{ "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2893 	  {
2894 		  { "peer_object", "o", ARG_OUT },
2895 		  END_ARGS
2896 	  }
2897 	},
2898 	{ "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2899 	  {
2900 		  { "peer_object", "o", ARG_OUT },
2901 		  END_ARGS
2902 	  }
2903 	},
2904 	{ "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2905 	  {
2906 		  { "peer_object", "o", ARG_OUT },
2907 		  END_ARGS
2908 	  }
2909 	},
2910 	{ "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2911 	  {
2912 		  { "peer_object", "o", ARG_OUT },
2913 		  { "status", "i", ARG_OUT },
2914 		  END_ARGS
2915 	  }
2916 	},
2917 	{ "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2918 	  {
2919 		  { "properties", "a{sv}", ARG_OUT },
2920 		  END_ARGS
2921 	  }
2922 	},
2923 	{ "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2924 	  {
2925 		  END_ARGS
2926 	  }
2927 	},
2928 	{ "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2929 	  {
2930 		  { "status", "i", ARG_OUT },
2931 		  END_ARGS
2932 	  }
2933 	},
2934 	{ "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2935 	  {
2936 		  { "path", "o", ARG_OUT },
2937 		  { "dev_passwd_id", "i", ARG_OUT },
2938 		  END_ARGS
2939 	  }
2940 	},
2941 	{ "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2942 	  {
2943 		  { "invite_result", "a{sv}", ARG_OUT },
2944 		  END_ARGS
2945 	  }
2946 	},
2947 	{ "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2948 	  {
2949 		  { "ifname", "s", ARG_OUT },
2950 		  { "role", "s", ARG_OUT },
2951 		  END_ARGS
2952 	  }
2953 	},
2954 	{ "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2955 	  {
2956 		  { "sd_request", "a{sv}", ARG_OUT },
2957 		  END_ARGS
2958 	  }
2959 	},
2960 	{ "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2961 	  {
2962 		  { "sd_response", "a{sv}", ARG_OUT },
2963 		  END_ARGS
2964 	  }
2965 	},
2966 	{ "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2967 	  {
2968 		  { "path", "o", ARG_OUT },
2969 		  { "properties", "a{sv}", ARG_OUT },
2970 		  END_ARGS
2971 	  }
2972 	},
2973 	{ "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2974 	  {
2975 		  { "path", "o", ARG_OUT },
2976 		  END_ARGS
2977 	  }
2978 	},
2979 	{ "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
2980 	  {
2981 		  { "name", "s", ARG_OUT },
2982 		  { "args", "a{sv}", ARG_OUT },
2983 		  END_ARGS
2984 	  }
2985 	},
2986 #endif /* CONFIG_P2P */
2987 #ifdef CONFIG_AP
2988 	{ "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
2989 	  {
2990 		  { "args", "a{sv}", ARG_OUT },
2991 		  END_ARGS
2992 	  }
2993 	},
2994 #endif /* CONFIG_AP */
2995 	{ "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE,
2996 	  {
2997 		  { "certification", "a{sv}", ARG_OUT },
2998 		  END_ARGS
2999 	  }
3000 	},
3001 	{ "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE,
3002 	  {
3003 		  { "status", "s", ARG_OUT },
3004 		  { "parameter", "s", ARG_OUT },
3005 		  END_ARGS
3006 	  }
3007 	},
3008 	{ NULL, NULL, { END_ARGS } }
3009 };
3010 
3011 
wpas_dbus_register_interface(struct wpa_supplicant * wpa_s)3012 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
3013 {
3014 
3015 	struct wpa_dbus_object_desc *obj_desc = NULL;
3016 	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
3017 	int next;
3018 
3019 	/* Do nothing if the control interface is not turned on */
3020 	if (ctrl_iface == NULL)
3021 		return 0;
3022 
3023 	/* Create and set the interface's object path */
3024 	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
3025 	if (wpa_s->dbus_new_path == NULL)
3026 		return -1;
3027 	next = ctrl_iface->next_objid++;
3028 	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
3029 		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
3030 		    next);
3031 
3032 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3033 	if (!obj_desc) {
3034 		wpa_printf(MSG_ERROR, "Not enough memory "
3035 			   "to create object description");
3036 		goto err;
3037 	}
3038 
3039 	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
3040 			   wpas_dbus_interface_properties,
3041 			   wpas_dbus_interface_signals);
3042 
3043 	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
3044 		   wpa_s->dbus_new_path);
3045 	if (wpa_dbus_register_object_per_iface(ctrl_iface,
3046 					       wpa_s->dbus_new_path,
3047 					       wpa_s->ifname, obj_desc))
3048 		goto err;
3049 
3050 	wpas_dbus_signal_interface_added(wpa_s);
3051 
3052 	return 0;
3053 
3054 err:
3055 	os_free(wpa_s->dbus_new_path);
3056 	wpa_s->dbus_new_path = NULL;
3057 	free_dbus_object_desc(obj_desc);
3058 	return -1;
3059 }
3060 
3061 
wpas_dbus_unregister_interface(struct wpa_supplicant * wpa_s)3062 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
3063 {
3064 	struct wpas_dbus_priv *ctrl_iface;
3065 
3066 	/* Do nothing if the control interface is not turned on */
3067 	if (wpa_s == NULL || wpa_s->global == NULL)
3068 		return 0;
3069 	ctrl_iface = wpa_s->global->dbus;
3070 	if (ctrl_iface == NULL)
3071 		return 0;
3072 
3073 	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
3074 		   wpa_s->dbus_new_path);
3075 
3076 #ifdef CONFIG_AP
3077 	if (wpa_s->preq_notify_peer) {
3078 		wpas_dbus_unsubscribe_noc(ctrl_iface);
3079 		os_free(wpa_s->preq_notify_peer);
3080 		wpa_s->preq_notify_peer = NULL;
3081 	}
3082 #endif /* CONFIG_AP */
3083 
3084 	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
3085 						 wpa_s->dbus_new_path))
3086 		return -1;
3087 
3088 	wpas_dbus_signal_interface_removed(wpa_s);
3089 
3090 	os_free(wpa_s->dbus_new_path);
3091 	wpa_s->dbus_new_path = NULL;
3092 
3093 	return 0;
3094 }
3095 
3096 #ifdef CONFIG_P2P
3097 
3098 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
3099 	{ "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
3100 	  wpas_dbus_getter_p2p_peer_device_name,
3101 	  NULL
3102 	},
3103 	{ "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3104 	  wpas_dbus_getter_p2p_peer_primary_device_type,
3105 	  NULL
3106 	},
3107 	{ "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
3108 	  wpas_dbus_getter_p2p_peer_config_method,
3109 	  NULL
3110 	},
3111 	{ "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
3112 	  wpas_dbus_getter_p2p_peer_level,
3113 	  NULL
3114 	},
3115 	{ "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
3116 	  wpas_dbus_getter_p2p_peer_device_capability,
3117 	  NULL
3118 	},
3119 	{ "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
3120 	  wpas_dbus_getter_p2p_peer_group_capability,
3121 	  NULL
3122 	},
3123 	{ "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
3124 	  wpas_dbus_getter_p2p_peer_secondary_device_types,
3125 	  NULL
3126 	},
3127 	{ "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
3128 	  wpas_dbus_getter_p2p_peer_vendor_extension,
3129 	  NULL
3130 	},
3131 	{ "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
3132 	  wpas_dbus_getter_p2p_peer_ies,
3133 	  NULL
3134 	},
3135 	{ NULL, NULL, NULL, NULL, NULL }
3136 };
3137 
3138 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
3139 
3140 	{ NULL, NULL, { END_ARGS } }
3141 };
3142 
3143 /**
3144  * wpas_dbus_signal_peer - Send a peer related event signal
3145  * @wpa_s: %wpa_supplicant network interface data
3146  * @dev: peer device object
3147  * @interface: name of the interface emitting this signal.
3148  *	In case of peer objects, it would be emitted by either
3149  *	the "interface object" or by "peer objects"
3150  * @sig_name: signal name - DeviceFound
3151  *
3152  * Notify listeners about event related with newly found p2p peer device
3153  */
wpas_dbus_signal_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr,const char * interface,const char * sig_name)3154 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
3155 				  const u8 *dev_addr, const char *interface,
3156 				  const char *sig_name)
3157 {
3158 	struct wpas_dbus_priv *iface;
3159 	DBusMessage *msg;
3160 	DBusMessageIter iter;
3161 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
3162 
3163 	iface = wpa_s->global->dbus;
3164 
3165 	/* Do nothing if the control interface is not turned on */
3166 	if (iface == NULL)
3167 		return;
3168 
3169 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3170 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3171 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
3172 
3173 	msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface,
3174 				      sig_name);
3175 	if (msg == NULL)
3176 		return;
3177 
3178 	dbus_message_iter_init_append(msg, &iter);
3179 	path = peer_obj_path;
3180 	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
3181 					    &path))
3182 		goto err;
3183 
3184 	dbus_connection_send(iface->con, msg, NULL);
3185 
3186 	dbus_message_unref(msg);
3187 	return;
3188 
3189 err:
3190 	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
3191 	dbus_message_unref(msg);
3192 }
3193 
3194 
3195 /**
3196  * wpas_dbus_signal_peer_found - Send a peer found signal
3197  * @wpa_s: %wpa_supplicant network interface data
3198  * @dev: peer device object
3199  *
3200  * Notify listeners about find a p2p peer device found
3201  */
wpas_dbus_signal_peer_device_found(struct wpa_supplicant * wpa_s,const u8 * dev_addr)3202 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s,
3203 					const u8 *dev_addr)
3204 {
3205 	wpas_dbus_signal_peer(wpa_s, dev_addr,
3206 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3207 			      "DeviceFound");
3208 }
3209 
3210 /**
3211  * wpas_dbus_signal_peer_lost - Send a peer lost signal
3212  * @wpa_s: %wpa_supplicant network interface data
3213  * @dev: peer device object
3214  *
3215  * Notify listeners about lost a p2p peer device
3216  */
wpas_dbus_signal_peer_device_lost(struct wpa_supplicant * wpa_s,const u8 * dev_addr)3217 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s,
3218 				       const u8 *dev_addr)
3219 {
3220 	wpas_dbus_signal_peer(wpa_s, dev_addr,
3221 			      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
3222 			      "DeviceLost");
3223 }
3224 
3225 /**
3226  * wpas_dbus_register_peer - Register a discovered peer object with dbus
3227  * @wpa_s: wpa_supplicant interface structure
3228  * @ssid: network configuration data
3229  * Returns: 0 on success, -1 on failure
3230  *
3231  * Registers network representing object with dbus
3232  */
wpas_dbus_register_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)3233 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr)
3234 {
3235 	struct wpas_dbus_priv *ctrl_iface;
3236 	struct wpa_dbus_object_desc *obj_desc;
3237 	struct peer_handler_args *arg;
3238 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3239 
3240 	/* Do nothing if the control interface is not turned on */
3241 	if (wpa_s == NULL || wpa_s->global == NULL)
3242 		return 0;
3243 
3244 	ctrl_iface = wpa_s->global->dbus;
3245 	if (ctrl_iface == NULL)
3246 		return 0;
3247 
3248 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3249 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3250 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
3251 
3252 	wpa_printf(MSG_INFO, "dbus: Register peer object '%s'",
3253 		   peer_obj_path);
3254 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3255 	if (!obj_desc) {
3256 		wpa_printf(MSG_ERROR, "Not enough memory "
3257 			   "to create object description");
3258 		goto err;
3259 	}
3260 
3261 	/* allocate memory for handlers arguments */
3262 	arg = os_zalloc(sizeof(struct peer_handler_args));
3263 	if (!arg) {
3264 		wpa_printf(MSG_ERROR, "Not enough memory "
3265 			   "to create arguments for method");
3266 		goto err;
3267 	}
3268 
3269 	arg->wpa_s = wpa_s;
3270 	os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN);
3271 
3272 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free,
3273 			   NULL,
3274 			   wpas_dbus_p2p_peer_properties,
3275 			   wpas_dbus_p2p_peer_signals);
3276 
3277 	if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path,
3278 					       wpa_s->ifname, obj_desc))
3279 		goto err;
3280 
3281 	return 0;
3282 
3283 err:
3284 	free_dbus_object_desc(obj_desc);
3285 	return -1;
3286 }
3287 
3288 /**
3289  * wpas_dbus_unregister_peer - Unregister a peer object with dbus
3290  * @wpa_s: wpa_supplicant interface structure
3291  * @dev_addr: p2p device addr
3292  * Returns: 0 on success, -1 on failure
3293  *
3294  * Registers network representing object with dbus
3295  */
wpas_dbus_unregister_peer(struct wpa_supplicant * wpa_s,const u8 * dev_addr)3296 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
3297 				  const u8 *dev_addr)
3298 {
3299 	struct wpas_dbus_priv *ctrl_iface;
3300 	char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3301 	int ret;
3302 
3303 	/* Do nothing if the control interface is not turned on */
3304 	if (wpa_s == NULL || wpa_s->global == NULL ||
3305 	    wpa_s->dbus_new_path == NULL)
3306 		return 0;
3307 	ctrl_iface = wpa_s->global->dbus;
3308 	if (ctrl_iface == NULL)
3309 		return 0;
3310 
3311 	os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3312 		    "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
3313 		    wpa_s->dbus_new_path, MAC2STR(dev_addr));
3314 
3315 	wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'",
3316 		   peer_obj_path);
3317 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path);
3318 
3319 	return ret;
3320 }
3321 
3322 
3323 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
3324 	{ "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
3325 	  wpas_dbus_getter_p2p_group_members,
3326 	  NULL
3327 	},
3328 	{ "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
3329 	  wpas_dbus_getter_p2p_group,
3330 	  NULL
3331 	},
3332 	{ "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
3333 	  wpas_dbus_getter_p2p_role,
3334 	  NULL
3335 	},
3336 	{ "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3337 	  wpas_dbus_getter_p2p_group_ssid,
3338 	  NULL
3339 	},
3340 	{ "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3341 	  wpas_dbus_getter_p2p_group_bssid,
3342 	  NULL
3343 	},
3344 	{ "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
3345 	  wpas_dbus_getter_p2p_group_frequency,
3346 	  NULL
3347 	},
3348 	{ "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
3349 	  wpas_dbus_getter_p2p_group_passphrase,
3350 	  NULL
3351 	},
3352 	{ "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
3353 	  wpas_dbus_getter_p2p_group_psk,
3354 	  NULL
3355 	},
3356 	{ "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
3357 	  wpas_dbus_getter_p2p_group_vendor_ext,
3358 	  wpas_dbus_setter_p2p_group_vendor_ext
3359 	},
3360 	{ NULL, NULL, NULL, NULL, NULL }
3361 };
3362 
3363 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
3364 	{ "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3365 	  {
3366 		  { "peer", "o", ARG_OUT },
3367 		  END_ARGS
3368 	  }
3369 	},
3370 	{ "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP,
3371 	  {
3372 		  { "peer", "o", ARG_OUT },
3373 		  END_ARGS
3374 	  }
3375 	},
3376 	{ NULL, NULL, { END_ARGS } }
3377 };
3378 
3379 /**
3380  * wpas_dbus_register_p2p_group - Register a p2p group object with dbus
3381  * @wpa_s: wpa_supplicant interface structure
3382  * @ssid: SSID struct
3383  * Returns: 0 on success, -1 on failure
3384  *
3385  * Registers p2p group representing object with dbus
3386  */
wpas_dbus_register_p2p_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)3387 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
3388 				  struct wpa_ssid *ssid)
3389 {
3390 	struct wpas_dbus_priv *ctrl_iface;
3391 	struct wpa_dbus_object_desc *obj_desc;
3392 	char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3393 
3394 	/* Do nothing if the control interface is not turned on */
3395 	if (wpa_s == NULL || wpa_s->global == NULL)
3396 		return;
3397 
3398 	ctrl_iface = wpa_s->global->dbus;
3399 	if (ctrl_iface == NULL)
3400 		return;
3401 
3402 	if (wpa_s->dbus_groupobj_path) {
3403 		wpa_printf(MSG_INFO, "%s: Group object '%s' already exists",
3404 			   __func__, wpa_s->dbus_groupobj_path);
3405 		return;
3406 	}
3407 
3408 	if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
3409 		return;
3410 
3411 	wpa_s->dbus_groupobj_path = os_strdup(group_obj_path);
3412 	if (wpa_s->dbus_groupobj_path == NULL)
3413 		return;
3414 
3415 	wpa_printf(MSG_INFO, "dbus: Register group object '%s'",
3416 		   group_obj_path);
3417 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3418 	if (!obj_desc) {
3419 		wpa_printf(MSG_ERROR, "Not enough memory "
3420 			   "to create object description");
3421 		goto err;
3422 	}
3423 
3424 	wpas_dbus_register(obj_desc, wpa_s, NULL, NULL,
3425 			   wpas_dbus_p2p_group_properties,
3426 			   wpas_dbus_p2p_group_signals);
3427 
3428 	if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path,
3429 					       wpa_s->ifname, obj_desc))
3430 		goto err;
3431 
3432 	return;
3433 
3434 err:
3435 	if (wpa_s->dbus_groupobj_path) {
3436 		os_free(wpa_s->dbus_groupobj_path);
3437 		wpa_s->dbus_groupobj_path = NULL;
3438 	}
3439 
3440 	free_dbus_object_desc(obj_desc);
3441 }
3442 
3443 /**
3444  * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus
3445  * @wpa_s: wpa_supplicant interface structure
3446  * @ssid: network name of the p2p group started
3447  */
wpas_dbus_unregister_p2p_group(struct wpa_supplicant * wpa_s,const struct wpa_ssid * ssid)3448 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
3449 				    const struct wpa_ssid *ssid)
3450 {
3451 	struct wpas_dbus_priv *ctrl_iface;
3452 
3453 	/* Do nothing if the control interface is not turned on */
3454 	if (wpa_s == NULL || wpa_s->global == NULL)
3455 		return;
3456 
3457 	ctrl_iface = wpa_s->global->dbus;
3458 	if (ctrl_iface == NULL)
3459 		return;
3460 
3461 	if (!wpa_s->dbus_groupobj_path) {
3462 		wpa_printf(MSG_DEBUG,
3463 			   "%s: Group object '%s' already unregistered",
3464 			   __func__, wpa_s->dbus_groupobj_path);
3465 		return;
3466 	}
3467 
3468 	wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
3469 		   wpa_s->dbus_groupobj_path);
3470 
3471 	wpa_dbus_unregister_object_per_iface(ctrl_iface,
3472 					     wpa_s->dbus_groupobj_path);
3473 
3474 	os_free(wpa_s->dbus_groupobj_path);
3475 	wpa_s->dbus_groupobj_path = NULL;
3476 }
3477 
3478 static const struct wpa_dbus_property_desc
3479 wpas_dbus_p2p_groupmember_properties[] = {
3480 	{ NULL, NULL, NULL, NULL, NULL }
3481 };
3482 
3483 /**
3484  * wpas_dbus_register_p2p_groupmember - Register a p2p groupmember
3485  * object with dbus
3486  * @wpa_s: wpa_supplicant interface structure
3487  * @p2p_if_addr: i/f addr of the device joining this group
3488  *
3489  * Registers p2p groupmember representing object with dbus
3490  */
wpas_dbus_register_p2p_groupmember(struct wpa_supplicant * wpa_s,const u8 * p2p_if_addr)3491 void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
3492 					const u8 *p2p_if_addr)
3493 {
3494 	struct wpas_dbus_priv *ctrl_iface;
3495 	struct wpa_dbus_object_desc *obj_desc = NULL;
3496 	struct groupmember_handler_args *arg;
3497 	char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3498 
3499 	/* Do nothing if the control interface is not turned on */
3500 	if (wpa_s == NULL || wpa_s->global == NULL)
3501 		return;
3502 
3503 	ctrl_iface = wpa_s->global->dbus;
3504 	if (ctrl_iface == NULL)
3505 		return;
3506 
3507 	if (!wpa_s->dbus_groupobj_path)
3508 		return;
3509 
3510 	os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3511 		"%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
3512 		wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
3513 
3514 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3515 	if (!obj_desc) {
3516 		wpa_printf(MSG_ERROR, "Not enough memory "
3517 			   "to create object description");
3518 		goto err;
3519 	}
3520 
3521 	/* allocate memory for handlers arguments */
3522 	arg = os_zalloc(sizeof(struct groupmember_handler_args));
3523 	if (!arg) {
3524 		wpa_printf(MSG_ERROR, "Not enough memory "
3525 			   "to create arguments for method");
3526 		goto err;
3527 	}
3528 
3529 	arg->wpa_s = wpa_s;
3530 	os_memcpy(arg->member_addr, p2p_if_addr, ETH_ALEN);
3531 
3532 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3533 			   wpas_dbus_p2p_groupmember_properties, NULL);
3534 
3535 	if (wpa_dbus_register_object_per_iface(ctrl_iface, groupmember_obj_path,
3536 					       wpa_s->ifname, obj_desc))
3537 		goto err;
3538 
3539 	wpa_printf(MSG_INFO,
3540 		   "dbus: Registered group member object '%s' successfully",
3541 		   groupmember_obj_path);
3542 	return;
3543 
3544 err:
3545 	free_dbus_object_desc(obj_desc);
3546 }
3547 
3548 /**
3549  * wpas_dbus_unregister_p2p_groupmember - Unregister a p2p groupmember
3550  * object with dbus
3551  * @wpa_s: wpa_supplicant interface structure
3552  * @p2p_if_addr: i/f addr of the device joining this group
3553  *
3554  * Unregisters p2p groupmember representing object with dbus
3555  */
wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant * wpa_s,const u8 * p2p_if_addr)3556 void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
3557 					  const u8 *p2p_if_addr)
3558 {
3559 	struct wpas_dbus_priv *ctrl_iface;
3560 	char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3561 
3562 	/* Do nothing if the control interface is not turned on */
3563 	if (wpa_s == NULL || wpa_s->global == NULL)
3564 		return;
3565 
3566 	ctrl_iface = wpa_s->global->dbus;
3567 	if (ctrl_iface == NULL)
3568 		return;
3569 
3570 	if (!wpa_s->dbus_groupobj_path)
3571 		return;
3572 
3573 	os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3574 		"%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
3575 		wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
3576 
3577 	wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path);
3578 }
3579 
3580 
3581 static const struct wpa_dbus_property_desc
3582 	wpas_dbus_persistent_group_properties[] = {
3583 	{ "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
3584 	  wpas_dbus_getter_persistent_group_properties,
3585 	  wpas_dbus_setter_persistent_group_properties
3586 	},
3587 	{ NULL, NULL, NULL, NULL, NULL }
3588 };
3589 
3590 /* No signals intended for persistent group objects */
3591 
3592 /**
3593  * wpas_dbus_register_persistent_group - Register a configured(saved)
3594  *	persistent group with dbus
3595  * @wpa_s: wpa_supplicant interface structure
3596  * @ssid: persistent group (still represented as a network within wpa)
3597  *	  configuration data
3598  * Returns: 0 on success, -1 on failure
3599  *
3600  * Registers a persistent group representing object with dbus.
3601  */
wpas_dbus_register_persistent_group(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)3602 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s,
3603 					struct wpa_ssid *ssid)
3604 {
3605 	struct wpas_dbus_priv *ctrl_iface;
3606 	struct wpa_dbus_object_desc *obj_desc;
3607 	struct network_handler_args *arg;
3608 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3609 
3610 	/* Do nothing if the control interface is not turned on */
3611 	if (wpa_s == NULL || wpa_s->global == NULL)
3612 		return 0;
3613 
3614 	/* Make sure ssid is a persistent group */
3615 	if (ssid->disabled != 2 && !ssid->p2p_persistent_group)
3616 		return -1; /* should we return w/o complaining? */
3617 
3618 	ctrl_iface = wpa_s->global->dbus;
3619 	if (ctrl_iface == NULL)
3620 		return 0;
3621 
3622 	/*
3623 	 * Intentionally not coming up with different numbering scheme
3624 	 * for persistent groups.
3625 	 */
3626 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3627 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3628 		    wpa_s->dbus_new_path, ssid->id);
3629 
3630 	wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'",
3631 		   pgrp_obj_path);
3632 	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
3633 	if (!obj_desc) {
3634 		wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3635 			   "object description");
3636 		goto err;
3637 	}
3638 
3639 	/*
3640 	 * Reusing the same context structure as that for networks
3641 	 * since these are represented using same data structure.
3642 	 */
3643 	/* allocate memory for handlers arguments */
3644 	arg = os_zalloc(sizeof(struct network_handler_args));
3645 	if (!arg) {
3646 		wpa_printf(MSG_ERROR, "dbus: Not enough memory to create "
3647 			   "arguments for method");
3648 		goto err;
3649 	}
3650 
3651 	arg->wpa_s = wpa_s;
3652 	arg->ssid = ssid;
3653 
3654 	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
3655 			   wpas_dbus_persistent_group_properties,
3656 			   NULL);
3657 
3658 	if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path,
3659 					       wpa_s->ifname, obj_desc))
3660 		goto err;
3661 
3662 	wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id);
3663 
3664 	return 0;
3665 
3666 err:
3667 	free_dbus_object_desc(obj_desc);
3668 	return -1;
3669 }
3670 
3671 
3672 /**
3673  * wpas_dbus_unregister_persistent_group - Unregister a persistent_group
3674  *	from dbus
3675  * @wpa_s: wpa_supplicant interface structure
3676  * @nid: network id
3677  * Returns: 0 on success, -1 on failure
3678  *
3679  * Unregisters persistent group representing object from dbus
3680  *
3681  * NOTE: There is a slight issue with the semantics here. While the
3682  * implementation simply means the persistent group is unloaded from memory,
3683  * it should not get interpreted as the group is actually being erased/removed
3684  * from persistent storage as well.
3685  */
wpas_dbus_unregister_persistent_group(struct wpa_supplicant * wpa_s,int nid)3686 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
3687 					  int nid)
3688 {
3689 	struct wpas_dbus_priv *ctrl_iface;
3690 	char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
3691 	int ret;
3692 
3693 	/* Do nothing if the control interface is not turned on */
3694 	if (wpa_s == NULL || wpa_s->global == NULL ||
3695 	    wpa_s->dbus_new_path == NULL)
3696 		return 0;
3697 	ctrl_iface = wpa_s->global->dbus;
3698 	if (ctrl_iface == NULL)
3699 		return 0;
3700 
3701 	os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
3702 		    "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u",
3703 		    wpa_s->dbus_new_path, nid);
3704 
3705 	wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'",
3706 		   pgrp_obj_path);
3707 	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path);
3708 
3709 	if (!ret)
3710 		wpas_dbus_signal_persistent_group_removed(wpa_s, nid);
3711 
3712 	return ret;
3713 }
3714 
3715 #endif /* CONFIG_P2P */
3716