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