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