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