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