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