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