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