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