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