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