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