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 case WPAS_DBUS_BSS_PROP_AGE: 1964 prop = "Age"; 1965 break; 1966 default: 1967 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 1968 __func__, property); 1969 return; 1970 } 1971 1972 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 1973 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 1974 wpa_s->dbus_new_path, id); 1975 1976 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 1977 WPAS_DBUS_NEW_IFACE_BSS, prop); 1978 } 1979 1980 1981 /** 1982 * wpas_dbus_signal_debug_level_changed - Signals change of debug param 1983 * @global: wpa_global structure 1984 * 1985 * Sends PropertyChanged signals informing that debug level has changed. 1986 */ 1987 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global) 1988 { 1989 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 1990 WPAS_DBUS_NEW_INTERFACE, 1991 "DebugLevel"); 1992 } 1993 1994 1995 /** 1996 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param 1997 * @global: wpa_global structure 1998 * 1999 * Sends PropertyChanged signals informing that debug timestamp has changed. 2000 */ 2001 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global) 2002 { 2003 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2004 WPAS_DBUS_NEW_INTERFACE, 2005 "DebugTimestamp"); 2006 } 2007 2008 2009 /** 2010 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param 2011 * @global: wpa_global structure 2012 * 2013 * Sends PropertyChanged signals informing that debug show_keys has changed. 2014 */ 2015 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global) 2016 { 2017 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2018 WPAS_DBUS_NEW_INTERFACE, 2019 "DebugShowKeys"); 2020 } 2021 2022 2023 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc, 2024 void *priv, 2025 WPADBusArgumentFreeFunction priv_free, 2026 const struct wpa_dbus_method_desc *methods, 2027 const struct wpa_dbus_property_desc *properties, 2028 const struct wpa_dbus_signal_desc *signals) 2029 { 2030 int n; 2031 2032 obj_desc->user_data = priv; 2033 obj_desc->user_data_free_func = priv_free; 2034 obj_desc->methods = methods; 2035 obj_desc->properties = properties; 2036 obj_desc->signals = signals; 2037 2038 for (n = 0; properties && properties->dbus_property; properties++) 2039 n++; 2040 2041 obj_desc->prop_changed_flags = os_zalloc(n); 2042 if (!obj_desc->prop_changed_flags) 2043 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers", 2044 __func__); 2045 } 2046 2047 2048 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = { 2049 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE, 2050 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface, 2051 { 2052 { "args", "a{sv}", ARG_IN }, 2053 { "path", "o", ARG_OUT }, 2054 END_ARGS 2055 } 2056 }, 2057 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE, 2058 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface, 2059 { 2060 { "path", "o", ARG_IN }, 2061 END_ARGS 2062 } 2063 }, 2064 { "GetInterface", WPAS_DBUS_NEW_INTERFACE, 2065 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface, 2066 { 2067 { "ifname", "s", ARG_IN }, 2068 { "path", "o", ARG_OUT }, 2069 END_ARGS 2070 } 2071 }, 2072 { NULL, NULL, NULL, { END_ARGS } } 2073 }; 2074 2075 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = { 2076 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s", 2077 wpas_dbus_getter_debug_level, 2078 wpas_dbus_setter_debug_level 2079 }, 2080 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b", 2081 wpas_dbus_getter_debug_timestamp, 2082 wpas_dbus_setter_debug_timestamp 2083 }, 2084 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b", 2085 wpas_dbus_getter_debug_show_keys, 2086 wpas_dbus_setter_debug_show_keys 2087 }, 2088 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao", 2089 wpas_dbus_getter_interfaces, 2090 NULL 2091 }, 2092 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as", 2093 wpas_dbus_getter_eap_methods, 2094 NULL 2095 }, 2096 { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as", 2097 wpas_dbus_getter_global_capabilities, 2098 NULL 2099 }, 2100 #ifdef CONFIG_WIFI_DISPLAY 2101 { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay", 2102 wpas_dbus_getter_global_wfd_ies, 2103 wpas_dbus_setter_global_wfd_ies 2104 }, 2105 #endif /* CONFIG_WIFI_DISPLAY */ 2106 { NULL, NULL, NULL, NULL, NULL } 2107 }; 2108 2109 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = { 2110 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE, 2111 { 2112 { "path", "o", ARG_OUT }, 2113 { "properties", "a{sv}", ARG_OUT }, 2114 END_ARGS 2115 } 2116 }, 2117 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE, 2118 { 2119 { "path", "o", ARG_OUT }, 2120 END_ARGS 2121 } 2122 }, 2123 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 2124 { 2125 { "path", "o", ARG_OUT }, 2126 { "field", "s", ARG_OUT }, 2127 { "text", "s", ARG_OUT }, 2128 END_ARGS 2129 } 2130 }, 2131 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2132 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE, 2133 { 2134 { "properties", "a{sv}", ARG_OUT }, 2135 END_ARGS 2136 } 2137 }, 2138 { NULL, NULL, { END_ARGS } } 2139 }; 2140 2141 2142 /** 2143 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface 2144 * @global: Pointer to global data from wpa_supplicant_init() 2145 * Returns: 0 on success or -1 on failure 2146 * 2147 * Initialize the dbus control interface for wpa_supplicantand and start 2148 * receiving commands from external programs over the bus. 2149 */ 2150 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv) 2151 { 2152 struct wpa_dbus_object_desc *obj_desc; 2153 int ret; 2154 2155 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2156 if (!obj_desc) { 2157 wpa_printf(MSG_ERROR, "Not enough memory " 2158 "to create object description"); 2159 return -1; 2160 } 2161 2162 wpas_dbus_register(obj_desc, priv->global, NULL, 2163 wpas_dbus_global_methods, 2164 wpas_dbus_global_properties, 2165 wpas_dbus_global_signals); 2166 2167 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'", 2168 WPAS_DBUS_NEW_PATH); 2169 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH, 2170 WPAS_DBUS_NEW_SERVICE, 2171 obj_desc); 2172 if (ret < 0) 2173 free_dbus_object_desc(obj_desc); 2174 else 2175 priv->dbus_new_initialized = 1; 2176 2177 return ret; 2178 } 2179 2180 2181 /** 2182 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for 2183 * wpa_supplicant 2184 * @iface: Pointer to dbus private data from wpas_dbus_init() 2185 * 2186 * Deinitialize the dbus control interface that was initialized with 2187 * wpas_dbus_ctrl_iface_init(). 2188 */ 2189 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface) 2190 { 2191 if (!iface->dbus_new_initialized) 2192 return; 2193 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'", 2194 WPAS_DBUS_NEW_PATH); 2195 dbus_connection_unregister_object_path(iface->con, 2196 WPAS_DBUS_NEW_PATH); 2197 } 2198 2199 2200 static void wpa_dbus_free(void *ptr) 2201 { 2202 os_free(ptr); 2203 } 2204 2205 2206 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = { 2207 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}", 2208 wpas_dbus_getter_network_properties, 2209 wpas_dbus_setter_network_properties 2210 }, 2211 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b", 2212 wpas_dbus_getter_enabled, 2213 wpas_dbus_setter_enabled 2214 }, 2215 { NULL, NULL, NULL, NULL, NULL } 2216 }; 2217 2218 2219 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = { 2220 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2221 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK, 2222 { 2223 { "properties", "a{sv}", ARG_OUT }, 2224 END_ARGS 2225 } 2226 }, 2227 { NULL, NULL, { END_ARGS } } 2228 }; 2229 2230 2231 /** 2232 * wpas_dbus_register_network - Register a configured network with dbus 2233 * @wpa_s: wpa_supplicant interface structure 2234 * @ssid: network configuration data 2235 * Returns: 0 on success, -1 on failure 2236 * 2237 * Registers network representing object with dbus 2238 */ 2239 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s, 2240 struct wpa_ssid *ssid) 2241 { 2242 struct wpas_dbus_priv *ctrl_iface; 2243 struct wpa_dbus_object_desc *obj_desc; 2244 struct network_handler_args *arg; 2245 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2246 2247 #ifdef CONFIG_P2P 2248 /* 2249 * If it is a persistent group register it as such. 2250 * This is to handle cases where an interface is being initialized 2251 * with a list of networks read from config. 2252 */ 2253 if (network_is_persistent_group(ssid)) 2254 return wpas_dbus_register_persistent_group(wpa_s, ssid); 2255 #endif /* CONFIG_P2P */ 2256 2257 /* Do nothing if the control interface is not turned on */ 2258 if (wpa_s == NULL || wpa_s->global == NULL) 2259 return 0; 2260 ctrl_iface = wpa_s->global->dbus; 2261 if (ctrl_iface == NULL) 2262 return 0; 2263 2264 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2265 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2266 wpa_s->dbus_new_path, ssid->id); 2267 2268 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'", 2269 net_obj_path); 2270 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2271 if (!obj_desc) { 2272 wpa_printf(MSG_ERROR, "Not enough memory " 2273 "to create object description"); 2274 goto err; 2275 } 2276 2277 /* allocate memory for handlers arguments */ 2278 arg = os_zalloc(sizeof(struct network_handler_args)); 2279 if (!arg) { 2280 wpa_printf(MSG_ERROR, "Not enough memory " 2281 "to create arguments for method"); 2282 goto err; 2283 } 2284 2285 arg->wpa_s = wpa_s; 2286 arg->ssid = ssid; 2287 2288 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2289 wpas_dbus_network_properties, 2290 wpas_dbus_network_signals); 2291 2292 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path, 2293 wpa_s->ifname, obj_desc)) 2294 goto err; 2295 2296 wpas_dbus_signal_network_added(wpa_s, ssid->id); 2297 2298 return 0; 2299 2300 err: 2301 free_dbus_object_desc(obj_desc); 2302 return -1; 2303 } 2304 2305 2306 /** 2307 * wpas_dbus_unregister_network - Unregister a configured network from dbus 2308 * @wpa_s: wpa_supplicant interface structure 2309 * @nid: network id 2310 * Returns: 0 on success, -1 on failure 2311 * 2312 * Unregisters network representing object from dbus 2313 */ 2314 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid) 2315 { 2316 struct wpas_dbus_priv *ctrl_iface; 2317 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2318 int ret; 2319 #ifdef CONFIG_P2P 2320 struct wpa_ssid *ssid; 2321 2322 ssid = wpa_config_get_network(wpa_s->conf, nid); 2323 2324 /* If it is a persistent group unregister it as such */ 2325 if (ssid && network_is_persistent_group(ssid)) 2326 return wpas_dbus_unregister_persistent_group(wpa_s, nid); 2327 #endif /* CONFIG_P2P */ 2328 2329 /* Do nothing if the control interface is not turned on */ 2330 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL) 2331 return 0; 2332 ctrl_iface = wpa_s->global->dbus; 2333 if (ctrl_iface == NULL) 2334 return 0; 2335 2336 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2337 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2338 wpa_s->dbus_new_path, nid); 2339 2340 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'", 2341 net_obj_path); 2342 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path); 2343 2344 if (!ret) 2345 wpas_dbus_signal_network_removed(wpa_s, nid); 2346 2347 return ret; 2348 } 2349 2350 2351 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = { 2352 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2353 wpas_dbus_getter_bss_ssid, 2354 NULL 2355 }, 2356 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2357 wpas_dbus_getter_bss_bssid, 2358 NULL 2359 }, 2360 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b", 2361 wpas_dbus_getter_bss_privacy, 2362 NULL 2363 }, 2364 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s", 2365 wpas_dbus_getter_bss_mode, 2366 NULL 2367 }, 2368 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n", 2369 wpas_dbus_getter_bss_signal, 2370 NULL 2371 }, 2372 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q", 2373 wpas_dbus_getter_bss_frequency, 2374 NULL 2375 }, 2376 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au", 2377 wpas_dbus_getter_bss_rates, 2378 NULL 2379 }, 2380 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2381 wpas_dbus_getter_bss_wpa, 2382 NULL 2383 }, 2384 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2385 wpas_dbus_getter_bss_rsn, 2386 NULL 2387 }, 2388 { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2389 wpas_dbus_getter_bss_wps, 2390 NULL 2391 }, 2392 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2393 wpas_dbus_getter_bss_ies, 2394 NULL 2395 }, 2396 { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u", 2397 wpas_dbus_getter_bss_age, 2398 NULL 2399 }, 2400 { NULL, NULL, NULL, NULL, NULL } 2401 }; 2402 2403 2404 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = { 2405 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2406 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS, 2407 { 2408 { "properties", "a{sv}", ARG_OUT }, 2409 END_ARGS 2410 } 2411 }, 2412 { NULL, NULL, { END_ARGS } } 2413 }; 2414 2415 2416 /** 2417 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus 2418 * @wpa_s: wpa_supplicant interface structure 2419 * @bssid: scanned network bssid 2420 * @id: unique BSS identifier 2421 * Returns: 0 on success, -1 on failure 2422 * 2423 * Unregisters BSS representing object from dbus 2424 */ 2425 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s, 2426 u8 bssid[ETH_ALEN], unsigned int id) 2427 { 2428 struct wpas_dbus_priv *ctrl_iface; 2429 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2430 2431 /* Do nothing if the control interface is not turned on */ 2432 if (wpa_s == NULL || wpa_s->global == NULL) 2433 return 0; 2434 ctrl_iface = wpa_s->global->dbus; 2435 if (ctrl_iface == NULL) 2436 return 0; 2437 2438 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2439 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2440 wpa_s->dbus_new_path, id); 2441 2442 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'", 2443 bss_obj_path); 2444 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) { 2445 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s", 2446 bss_obj_path); 2447 return -1; 2448 } 2449 2450 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path); 2451 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 2452 2453 return 0; 2454 } 2455 2456 2457 /** 2458 * wpas_dbus_register_bss - Register a scanned BSS with dbus 2459 * @wpa_s: wpa_supplicant interface structure 2460 * @bssid: scanned network bssid 2461 * @id: unique BSS identifier 2462 * Returns: 0 on success, -1 on failure 2463 * 2464 * Registers BSS representing object with dbus 2465 */ 2466 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, 2467 u8 bssid[ETH_ALEN], unsigned int id) 2468 { 2469 struct wpas_dbus_priv *ctrl_iface; 2470 struct wpa_dbus_object_desc *obj_desc; 2471 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2472 struct bss_handler_args *arg; 2473 2474 /* Do nothing if the control interface is not turned on */ 2475 if (wpa_s == NULL || wpa_s->global == NULL) 2476 return 0; 2477 ctrl_iface = wpa_s->global->dbus; 2478 if (ctrl_iface == NULL) 2479 return 0; 2480 2481 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2482 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2483 wpa_s->dbus_new_path, id); 2484 2485 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2486 if (!obj_desc) { 2487 wpa_printf(MSG_ERROR, "Not enough memory " 2488 "to create object description"); 2489 goto err; 2490 } 2491 2492 arg = os_zalloc(sizeof(struct bss_handler_args)); 2493 if (!arg) { 2494 wpa_printf(MSG_ERROR, "Not enough memory " 2495 "to create arguments for handler"); 2496 goto err; 2497 } 2498 arg->wpa_s = wpa_s; 2499 arg->id = id; 2500 2501 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2502 wpas_dbus_bss_properties, 2503 wpas_dbus_bss_signals); 2504 2505 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'", 2506 bss_obj_path); 2507 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path, 2508 wpa_s->ifname, obj_desc)) { 2509 wpa_printf(MSG_ERROR, 2510 "Cannot register BSSID dbus object %s.", 2511 bss_obj_path); 2512 goto err; 2513 } 2514 2515 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path); 2516 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 2517 2518 return 0; 2519 2520 err: 2521 free_dbus_object_desc(obj_desc); 2522 return -1; 2523 } 2524 2525 2526 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { 2527 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE, 2528 (WPADBusMethodHandler) &wpas_dbus_handler_scan, 2529 { 2530 { "args", "a{sv}", ARG_IN }, 2531 END_ARGS 2532 } 2533 }, 2534 { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE, 2535 (WPADBusMethodHandler) &wpas_dbus_handler_signal_poll, 2536 { 2537 { "args", "a{sv}", ARG_OUT }, 2538 END_ARGS 2539 } 2540 }, 2541 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 2542 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect, 2543 { 2544 END_ARGS 2545 } 2546 }, 2547 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2548 (WPADBusMethodHandler) &wpas_dbus_handler_add_network, 2549 { 2550 { "args", "a{sv}", ARG_IN }, 2551 { "path", "o", ARG_OUT }, 2552 END_ARGS 2553 } 2554 }, 2555 { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE, 2556 (WPADBusMethodHandler) &wpas_dbus_handler_reassociate, 2557 { 2558 END_ARGS 2559 } 2560 }, 2561 { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE, 2562 (WPADBusMethodHandler) &wpas_dbus_handler_reattach, 2563 { 2564 END_ARGS 2565 } 2566 }, 2567 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2568 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network, 2569 { 2570 { "path", "o", ARG_IN }, 2571 END_ARGS 2572 } 2573 }, 2574 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE, 2575 (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks, 2576 { 2577 END_ARGS 2578 } 2579 }, 2580 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2581 (WPADBusMethodHandler) &wpas_dbus_handler_select_network, 2582 { 2583 { "path", "o", ARG_IN }, 2584 END_ARGS 2585 } 2586 }, 2587 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE, 2588 (WPADBusMethodHandler) &wpas_dbus_handler_network_reply, 2589 { 2590 { "path", "o", ARG_IN }, 2591 { "field", "s", ARG_IN }, 2592 { "value", "s", ARG_IN }, 2593 END_ARGS 2594 } 2595 }, 2596 #ifndef CONFIG_NO_CONFIG_BLOBS 2597 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2598 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob, 2599 { 2600 { "name", "s", ARG_IN }, 2601 { "data", "ay", ARG_IN }, 2602 END_ARGS 2603 } 2604 }, 2605 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2606 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob, 2607 { 2608 { "name", "s", ARG_IN }, 2609 { "data", "ay", ARG_OUT }, 2610 END_ARGS 2611 } 2612 }, 2613 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2614 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob, 2615 { 2616 { "name", "s", ARG_IN }, 2617 END_ARGS 2618 } 2619 }, 2620 #endif /* CONFIG_NO_CONFIG_BLOBS */ 2621 { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, 2622 (WPADBusMethodHandler) 2623 &wpas_dbus_handler_set_pkcs11_engine_and_module_path, 2624 { 2625 { "pkcs11_engine_path", "s", ARG_IN }, 2626 { "pkcs11_module_path", "s", ARG_IN }, 2627 END_ARGS 2628 } 2629 }, 2630 #ifdef CONFIG_WPS 2631 { "Start", WPAS_DBUS_NEW_IFACE_WPS, 2632 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start, 2633 { 2634 { "args", "a{sv}", ARG_IN }, 2635 { "output", "a{sv}", ARG_OUT }, 2636 END_ARGS 2637 } 2638 }, 2639 #endif /* CONFIG_WPS */ 2640 #ifdef CONFIG_P2P 2641 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2642 (WPADBusMethodHandler)wpas_dbus_handler_p2p_find, 2643 { 2644 { "args", "a{sv}", ARG_IN }, 2645 END_ARGS 2646 } 2647 }, 2648 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2649 (WPADBusMethodHandler)wpas_dbus_handler_p2p_stop_find, 2650 { 2651 END_ARGS 2652 } 2653 }, 2654 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2655 (WPADBusMethodHandler)wpas_dbus_handler_p2p_listen, 2656 { 2657 { "timeout", "i", ARG_IN }, 2658 END_ARGS 2659 } 2660 }, 2661 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2662 (WPADBusMethodHandler)wpas_dbus_handler_p2p_extendedlisten, 2663 { 2664 { "args", "a{sv}", ARG_IN }, 2665 END_ARGS 2666 } 2667 }, 2668 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2669 (WPADBusMethodHandler)wpas_dbus_handler_p2p_presence_request, 2670 { 2671 { "args", "a{sv}", ARG_IN }, 2672 END_ARGS 2673 } 2674 }, 2675 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2676 (WPADBusMethodHandler)wpas_dbus_handler_p2p_prov_disc_req, 2677 { 2678 { "peer", "o", ARG_IN }, 2679 { "config_method", "s", ARG_IN }, 2680 END_ARGS 2681 } 2682 }, 2683 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2684 (WPADBusMethodHandler)wpas_dbus_handler_p2p_connect, 2685 { 2686 { "args", "a{sv}", ARG_IN }, 2687 { "generated_pin", "s", ARG_OUT }, 2688 END_ARGS 2689 } 2690 }, 2691 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2692 (WPADBusMethodHandler)wpas_dbus_handler_p2p_group_add, 2693 { 2694 { "args", "a{sv}", ARG_IN }, 2695 END_ARGS 2696 } 2697 }, 2698 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2699 (WPADBusMethodHandler)wpas_dbus_handler_p2p_invite, 2700 { 2701 { "args", "a{sv}", ARG_IN }, 2702 END_ARGS 2703 } 2704 }, 2705 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2706 (WPADBusMethodHandler)wpas_dbus_handler_p2p_disconnect, 2707 { 2708 END_ARGS 2709 } 2710 }, 2711 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2712 (WPADBusMethodHandler)wpas_dbus_handler_p2p_rejectpeer, 2713 { 2714 { "peer", "o", ARG_IN }, 2715 END_ARGS 2716 } 2717 }, 2718 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2719 (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush, 2720 { 2721 END_ARGS 2722 } 2723 }, 2724 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2725 (WPADBusMethodHandler)wpas_dbus_handler_p2p_add_service, 2726 { 2727 { "args", "a{sv}", ARG_IN }, 2728 END_ARGS 2729 } 2730 }, 2731 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2732 (WPADBusMethodHandler)wpas_dbus_handler_p2p_delete_service, 2733 { 2734 { "args", "a{sv}", ARG_IN }, 2735 END_ARGS 2736 } 2737 }, 2738 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2739 (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush_service, 2740 { 2741 END_ARGS 2742 } 2743 }, 2744 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2745 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req, 2746 { 2747 { "args", "a{sv}", ARG_IN }, 2748 { "ref", "t", ARG_OUT }, 2749 END_ARGS 2750 } 2751 }, 2752 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2753 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_res, 2754 { 2755 { "args", "a{sv}", ARG_IN }, 2756 END_ARGS 2757 } 2758 }, 2759 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2760 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_cancel_req, 2761 { 2762 { "args", "t", ARG_IN }, 2763 END_ARGS 2764 } 2765 }, 2766 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2767 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_update, 2768 { 2769 END_ARGS 2770 } 2771 }, 2772 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2773 (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external, 2774 { 2775 { "arg", "i", ARG_IN }, 2776 END_ARGS 2777 } 2778 }, 2779 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2780 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group, 2781 { 2782 { "args", "a{sv}", ARG_IN }, 2783 { "path", "o", ARG_OUT }, 2784 END_ARGS 2785 } 2786 }, 2787 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2788 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group, 2789 { 2790 { "path", "o", ARG_IN }, 2791 END_ARGS 2792 } 2793 }, 2794 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2795 (WPADBusMethodHandler) 2796 wpas_dbus_handler_remove_all_persistent_groups, 2797 { 2798 END_ARGS 2799 } 2800 }, 2801 #endif /* CONFIG_P2P */ 2802 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, 2803 (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss, 2804 { 2805 { "age", "u", ARG_IN }, 2806 END_ARGS 2807 } 2808 }, 2809 #ifdef CONFIG_AP 2810 { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 2811 (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq, 2812 { 2813 END_ARGS 2814 } 2815 }, 2816 { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 2817 (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq, 2818 { 2819 END_ARGS 2820 } 2821 }, 2822 #endif /* CONFIG_AP */ 2823 { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE, 2824 (WPADBusMethodHandler) &wpas_dbus_handler_eap_logoff, 2825 { 2826 END_ARGS 2827 } 2828 }, 2829 { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE, 2830 (WPADBusMethodHandler) &wpas_dbus_handler_eap_logon, 2831 { 2832 END_ARGS 2833 } 2834 }, 2835 #ifdef CONFIG_AUTOSCAN 2836 { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE, 2837 (WPADBusMethodHandler) &wpas_dbus_handler_autoscan, 2838 { 2839 { "arg", "s", ARG_IN }, 2840 END_ARGS 2841 } 2842 }, 2843 #endif /* CONFIG_AUTOSCAN */ 2844 #ifdef CONFIG_TDLS 2845 { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE, 2846 (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover, 2847 { 2848 { "peer_address", "s", ARG_IN }, 2849 END_ARGS 2850 } 2851 }, 2852 { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE, 2853 (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup, 2854 { 2855 { "peer_address", "s", ARG_IN }, 2856 END_ARGS 2857 } 2858 }, 2859 { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, 2860 (WPADBusMethodHandler) wpas_dbus_handler_tdls_status, 2861 { 2862 { "peer_address", "s", ARG_IN }, 2863 { "status", "s", ARG_OUT }, 2864 END_ARGS 2865 } 2866 }, 2867 { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE, 2868 (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown, 2869 { 2870 { "peer_address", "s", ARG_IN }, 2871 END_ARGS 2872 } 2873 }, 2874 #endif /* CONFIG_TDLS */ 2875 { NULL, NULL, NULL, { END_ARGS } } 2876 }; 2877 2878 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { 2879 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}", 2880 wpas_dbus_getter_capabilities, 2881 NULL 2882 }, 2883 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2884 wpas_dbus_getter_state, 2885 NULL 2886 }, 2887 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 2888 wpas_dbus_getter_scanning, 2889 NULL 2890 }, 2891 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2892 wpas_dbus_getter_ap_scan, 2893 wpas_dbus_setter_ap_scan 2894 }, 2895 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2896 wpas_dbus_getter_bss_expire_age, 2897 wpas_dbus_setter_bss_expire_age 2898 }, 2899 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2900 wpas_dbus_getter_bss_expire_count, 2901 wpas_dbus_setter_bss_expire_count 2902 }, 2903 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2904 wpas_dbus_getter_country, 2905 wpas_dbus_setter_country 2906 }, 2907 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2908 wpas_dbus_getter_ifname, 2909 NULL 2910 }, 2911 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2912 wpas_dbus_getter_driver, 2913 NULL 2914 }, 2915 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2916 wpas_dbus_getter_bridge_ifname, 2917 NULL 2918 }, 2919 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 2920 wpas_dbus_getter_current_bss, 2921 NULL 2922 }, 2923 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 2924 wpas_dbus_getter_current_network, 2925 NULL 2926 }, 2927 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2928 wpas_dbus_getter_current_auth_mode, 2929 NULL 2930 }, 2931 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}", 2932 wpas_dbus_getter_blobs, 2933 NULL 2934 }, 2935 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 2936 wpas_dbus_getter_bsss, 2937 NULL 2938 }, 2939 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 2940 wpas_dbus_getter_networks, 2941 NULL 2942 }, 2943 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 2944 wpas_dbus_getter_fast_reauth, 2945 wpas_dbus_setter_fast_reauth 2946 }, 2947 { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 2948 wpas_dbus_getter_scan_interval, 2949 wpas_dbus_setter_scan_interval 2950 }, 2951 { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2952 wpas_dbus_getter_pkcs11_engine_path, 2953 NULL 2954 }, 2955 { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2956 wpas_dbus_getter_pkcs11_module_path, 2957 NULL 2958 }, 2959 #ifdef CONFIG_WPS 2960 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b", 2961 wpas_dbus_getter_process_credentials, 2962 wpas_dbus_setter_process_credentials 2963 }, 2964 { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s", 2965 wpas_dbus_getter_config_methods, 2966 wpas_dbus_setter_config_methods 2967 }, 2968 #endif /* CONFIG_WPS */ 2969 #ifdef CONFIG_P2P 2970 { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}", 2971 wpas_dbus_getter_p2p_device_config, 2972 wpas_dbus_setter_p2p_device_config 2973 }, 2974 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 2975 wpas_dbus_getter_p2p_peers, 2976 NULL 2977 }, 2978 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s", 2979 wpas_dbus_getter_p2p_role, 2980 NULL 2981 }, 2982 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 2983 wpas_dbus_getter_p2p_group, 2984 NULL 2985 }, 2986 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 2987 wpas_dbus_getter_p2p_peergo, 2988 NULL 2989 }, 2990 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 2991 wpas_dbus_getter_persistent_groups, 2992 NULL 2993 }, 2994 #endif /* CONFIG_P2P */ 2995 { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 2996 wpas_dbus_getter_disconnect_reason, 2997 NULL 2998 }, 2999 { NULL, NULL, NULL, NULL, NULL } 3000 }; 3001 3002 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { 3003 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE, 3004 { 3005 { "success", "b", ARG_OUT }, 3006 END_ARGS 3007 } 3008 }, 3009 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3010 { 3011 { "path", "o", ARG_OUT }, 3012 { "properties", "a{sv}", ARG_OUT }, 3013 END_ARGS 3014 } 3015 }, 3016 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3017 { 3018 { "path", "o", ARG_OUT }, 3019 END_ARGS 3020 } 3021 }, 3022 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3023 { 3024 { "name", "s", ARG_OUT }, 3025 END_ARGS 3026 } 3027 }, 3028 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3029 { 3030 { "name", "s", ARG_OUT }, 3031 END_ARGS 3032 } 3033 }, 3034 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3035 { 3036 { "path", "o", ARG_OUT }, 3037 { "properties", "a{sv}", ARG_OUT }, 3038 END_ARGS 3039 } 3040 }, 3041 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3042 { 3043 { "path", "o", ARG_OUT }, 3044 END_ARGS 3045 } 3046 }, 3047 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE, 3048 { 3049 { "path", "o", ARG_OUT }, 3050 END_ARGS 3051 } 3052 }, 3053 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3054 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE, 3055 { 3056 { "properties", "a{sv}", ARG_OUT }, 3057 END_ARGS 3058 } 3059 }, 3060 #ifdef CONFIG_WPS 3061 { "Event", WPAS_DBUS_NEW_IFACE_WPS, 3062 { 3063 { "name", "s", ARG_OUT }, 3064 { "args", "a{sv}", ARG_OUT }, 3065 END_ARGS 3066 } 3067 }, 3068 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS, 3069 { 3070 { "credentials", "a{sv}", ARG_OUT }, 3071 END_ARGS 3072 } 3073 }, 3074 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3075 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS, 3076 { 3077 { "properties", "a{sv}", ARG_OUT }, 3078 END_ARGS 3079 } 3080 }, 3081 #endif /* CONFIG_WPS */ 3082 #ifdef CONFIG_P2P 3083 { "P2PStateChanged", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3084 { 3085 { "states", "a{ss}", ARG_OUT }, 3086 END_ARGS 3087 } 3088 }, 3089 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3090 { 3091 { "path", "o", ARG_OUT }, 3092 END_ARGS 3093 } 3094 }, 3095 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3096 { 3097 { "path", "o", ARG_OUT }, 3098 END_ARGS 3099 } 3100 }, 3101 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3102 { 3103 { "peer_object", "o", ARG_OUT }, 3104 { "pin", "s", ARG_OUT }, 3105 END_ARGS 3106 } 3107 }, 3108 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3109 { 3110 { "peer_object", "o", ARG_OUT }, 3111 { "pin", "s", ARG_OUT }, 3112 END_ARGS 3113 } 3114 }, 3115 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3116 { 3117 { "peer_object", "o", ARG_OUT }, 3118 END_ARGS 3119 } 3120 }, 3121 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3122 { 3123 { "peer_object", "o", ARG_OUT }, 3124 END_ARGS 3125 } 3126 }, 3127 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3128 { 3129 { "peer_object", "o", ARG_OUT }, 3130 END_ARGS 3131 } 3132 }, 3133 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3134 { 3135 { "peer_object", "o", ARG_OUT }, 3136 END_ARGS 3137 } 3138 }, 3139 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3140 { 3141 { "peer_object", "o", ARG_OUT }, 3142 { "status", "i", ARG_OUT }, 3143 END_ARGS 3144 } 3145 }, 3146 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3147 { 3148 { "properties", "a{sv}", ARG_OUT }, 3149 END_ARGS 3150 } 3151 }, 3152 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3153 { 3154 { "properties", "a{sv}", ARG_OUT }, 3155 END_ARGS 3156 } 3157 }, 3158 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3159 { 3160 { "properties", "a{sv}", ARG_OUT }, 3161 END_ARGS 3162 } 3163 }, 3164 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3165 { 3166 { "path", "o", ARG_OUT }, 3167 { "dev_passwd_id", "i", ARG_OUT }, 3168 END_ARGS 3169 } 3170 }, 3171 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3172 { 3173 { "invite_result", "a{sv}", ARG_OUT }, 3174 END_ARGS 3175 } 3176 }, 3177 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3178 { 3179 { "properties", "a{sv}", ARG_OUT }, 3180 END_ARGS 3181 } 3182 }, 3183 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3184 { 3185 { "sd_request", "a{sv}", ARG_OUT }, 3186 END_ARGS 3187 } 3188 }, 3189 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3190 { 3191 { "sd_response", "a{sv}", ARG_OUT }, 3192 END_ARGS 3193 } 3194 }, 3195 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3196 { 3197 { "path", "o", ARG_OUT }, 3198 { "properties", "a{sv}", ARG_OUT }, 3199 END_ARGS 3200 } 3201 }, 3202 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3203 { 3204 { "path", "o", ARG_OUT }, 3205 END_ARGS 3206 } 3207 }, 3208 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3209 { 3210 { "name", "s", ARG_OUT }, 3211 { "args", "a{sv}", ARG_OUT }, 3212 END_ARGS 3213 } 3214 }, 3215 #endif /* CONFIG_P2P */ 3216 #ifdef CONFIG_AP 3217 { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 3218 { 3219 { "args", "a{sv}", ARG_OUT }, 3220 END_ARGS 3221 } 3222 }, 3223 #endif /* CONFIG_AP */ 3224 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE, 3225 { 3226 { "certification", "a{sv}", ARG_OUT }, 3227 END_ARGS 3228 } 3229 }, 3230 { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE, 3231 { 3232 { "status", "s", ARG_OUT }, 3233 { "parameter", "s", ARG_OUT }, 3234 END_ARGS 3235 } 3236 }, 3237 { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE, 3238 { 3239 { "name", "s", ARG_OUT }, 3240 END_ARGS 3241 } 3242 }, 3243 { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE, 3244 { 3245 { "name", "s", ARG_OUT }, 3246 END_ARGS 3247 } 3248 }, 3249 { NULL, NULL, { END_ARGS } } 3250 }; 3251 3252 3253 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s) 3254 { 3255 3256 struct wpa_dbus_object_desc *obj_desc = NULL; 3257 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus; 3258 int next; 3259 3260 /* Do nothing if the control interface is not turned on */ 3261 if (ctrl_iface == NULL) 3262 return 0; 3263 3264 /* Create and set the interface's object path */ 3265 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 3266 if (wpa_s->dbus_new_path == NULL) 3267 return -1; 3268 next = ctrl_iface->next_objid++; 3269 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX, 3270 WPAS_DBUS_NEW_PATH_INTERFACES "/%u", 3271 next); 3272 3273 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3274 if (!obj_desc) { 3275 wpa_printf(MSG_ERROR, "Not enough memory " 3276 "to create object description"); 3277 goto err; 3278 } 3279 3280 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods, 3281 wpas_dbus_interface_properties, 3282 wpas_dbus_interface_signals); 3283 3284 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", 3285 wpa_s->dbus_new_path); 3286 if (wpa_dbus_register_object_per_iface(ctrl_iface, 3287 wpa_s->dbus_new_path, 3288 wpa_s->ifname, obj_desc)) 3289 goto err; 3290 3291 wpas_dbus_signal_interface_added(wpa_s); 3292 3293 return 0; 3294 3295 err: 3296 os_free(wpa_s->dbus_new_path); 3297 wpa_s->dbus_new_path = NULL; 3298 free_dbus_object_desc(obj_desc); 3299 return -1; 3300 } 3301 3302 3303 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s) 3304 { 3305 struct wpas_dbus_priv *ctrl_iface; 3306 3307 /* Do nothing if the control interface is not turned on */ 3308 if (wpa_s == NULL || wpa_s->global == NULL) 3309 return 0; 3310 ctrl_iface = wpa_s->global->dbus; 3311 if (ctrl_iface == NULL) 3312 return 0; 3313 3314 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'", 3315 wpa_s->dbus_new_path); 3316 3317 #ifdef CONFIG_AP 3318 if (wpa_s->preq_notify_peer) { 3319 wpas_dbus_unsubscribe_noc(ctrl_iface); 3320 os_free(wpa_s->preq_notify_peer); 3321 wpa_s->preq_notify_peer = NULL; 3322 } 3323 #endif /* CONFIG_AP */ 3324 3325 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, 3326 wpa_s->dbus_new_path)) 3327 return -1; 3328 3329 wpas_dbus_signal_interface_removed(wpa_s); 3330 3331 os_free(wpa_s->dbus_new_path); 3332 wpa_s->dbus_new_path = NULL; 3333 3334 return 0; 3335 } 3336 3337 #ifdef CONFIG_P2P 3338 3339 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = { 3340 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 3341 wpas_dbus_getter_p2p_peer_device_name, 3342 NULL 3343 }, 3344 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 3345 wpas_dbus_getter_p2p_peer_primary_device_type, 3346 NULL 3347 }, 3348 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q", 3349 wpas_dbus_getter_p2p_peer_config_method, 3350 NULL 3351 }, 3352 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i", 3353 wpas_dbus_getter_p2p_peer_level, 3354 NULL 3355 }, 3356 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 3357 wpas_dbus_getter_p2p_peer_device_capability, 3358 NULL 3359 }, 3360 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 3361 wpas_dbus_getter_p2p_peer_group_capability, 3362 NULL 3363 }, 3364 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 3365 wpas_dbus_getter_p2p_peer_secondary_device_types, 3366 NULL 3367 }, 3368 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 3369 wpas_dbus_getter_p2p_peer_vendor_extension, 3370 NULL 3371 }, 3372 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 3373 wpas_dbus_getter_p2p_peer_ies, 3374 NULL 3375 }, 3376 { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 3377 wpas_dbus_getter_p2p_peer_device_address, 3378 NULL 3379 }, 3380 { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao", 3381 wpas_dbus_getter_p2p_peer_groups, 3382 NULL 3383 }, 3384 { NULL, NULL, NULL, NULL, NULL } 3385 }; 3386 3387 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = { 3388 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3389 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER, 3390 { 3391 { "properties", "a{sv}", ARG_OUT }, 3392 END_ARGS 3393 } 3394 }, 3395 { NULL, NULL, { END_ARGS } } 3396 }; 3397 3398 /** 3399 * wpas_dbus_signal_peer - Send a peer related event signal 3400 * @wpa_s: %wpa_supplicant network interface data 3401 * @dev: peer device object 3402 * @interface: name of the interface emitting this signal. 3403 * In case of peer objects, it would be emitted by either 3404 * the "interface object" or by "peer objects" 3405 * @sig_name: signal name - DeviceFound 3406 * 3407 * Notify listeners about event related with newly found p2p peer device 3408 */ 3409 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s, 3410 const u8 *dev_addr, const char *interface, 3411 const char *sig_name) 3412 { 3413 struct wpas_dbus_priv *iface; 3414 DBusMessage *msg; 3415 DBusMessageIter iter; 3416 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 3417 3418 iface = wpa_s->global->dbus; 3419 3420 /* Do nothing if the control interface is not turned on */ 3421 if (iface == NULL) 3422 return; 3423 3424 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3425 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 3426 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 3427 3428 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface, 3429 sig_name); 3430 if (msg == NULL) 3431 return; 3432 3433 dbus_message_iter_init_append(msg, &iter); 3434 path = peer_obj_path; 3435 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 3436 &path)) 3437 goto err; 3438 3439 dbus_connection_send(iface->con, msg, NULL); 3440 3441 dbus_message_unref(msg); 3442 return; 3443 3444 err: 3445 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 3446 dbus_message_unref(msg); 3447 } 3448 3449 3450 /** 3451 * wpas_dbus_signal_peer_found - Send a peer found signal 3452 * @wpa_s: %wpa_supplicant network interface data 3453 * @dev: peer device object 3454 * 3455 * Notify listeners about find a p2p peer device found 3456 */ 3457 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s, 3458 const u8 *dev_addr) 3459 { 3460 wpas_dbus_signal_peer(wpa_s, dev_addr, 3461 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3462 "DeviceFound"); 3463 } 3464 3465 /** 3466 * wpas_dbus_signal_peer_lost - Send a peer lost signal 3467 * @wpa_s: %wpa_supplicant network interface data 3468 * @dev: peer device object 3469 * 3470 * Notify listeners about lost a p2p peer device 3471 */ 3472 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s, 3473 const u8 *dev_addr) 3474 { 3475 wpas_dbus_signal_peer(wpa_s, dev_addr, 3476 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3477 "DeviceLost"); 3478 } 3479 3480 /** 3481 * wpas_dbus_register_peer - Register a discovered peer object with dbus 3482 * @wpa_s: wpa_supplicant interface structure 3483 * @ssid: network configuration data 3484 * Returns: 0 on success, -1 on failure 3485 * 3486 * Registers network representing object with dbus 3487 */ 3488 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr) 3489 { 3490 struct wpas_dbus_priv *ctrl_iface; 3491 struct wpa_dbus_object_desc *obj_desc; 3492 struct peer_handler_args *arg; 3493 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3494 3495 /* Do nothing if the control interface is not turned on */ 3496 if (wpa_s == NULL || wpa_s->global == NULL) 3497 return 0; 3498 3499 ctrl_iface = wpa_s->global->dbus; 3500 if (ctrl_iface == NULL) 3501 return 0; 3502 3503 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3504 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 3505 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 3506 3507 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'", 3508 peer_obj_path); 3509 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3510 if (!obj_desc) { 3511 wpa_printf(MSG_ERROR, "Not enough memory " 3512 "to create object description"); 3513 goto err; 3514 } 3515 3516 /* allocate memory for handlers arguments */ 3517 arg = os_zalloc(sizeof(struct peer_handler_args)); 3518 if (!arg) { 3519 wpa_printf(MSG_ERROR, "Not enough memory " 3520 "to create arguments for method"); 3521 goto err; 3522 } 3523 3524 arg->wpa_s = wpa_s; 3525 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN); 3526 3527 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, 3528 NULL, 3529 wpas_dbus_p2p_peer_properties, 3530 wpas_dbus_p2p_peer_signals); 3531 3532 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path, 3533 wpa_s->ifname, obj_desc)) 3534 goto err; 3535 3536 return 0; 3537 3538 err: 3539 free_dbus_object_desc(obj_desc); 3540 return -1; 3541 } 3542 3543 /** 3544 * wpas_dbus_unregister_peer - Unregister a peer object with dbus 3545 * @wpa_s: wpa_supplicant interface structure 3546 * @dev_addr: p2p device addr 3547 * Returns: 0 on success, -1 on failure 3548 * 3549 * Registers network representing object with dbus 3550 */ 3551 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s, 3552 const u8 *dev_addr) 3553 { 3554 struct wpas_dbus_priv *ctrl_iface; 3555 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3556 int ret; 3557 3558 /* Do nothing if the control interface is not turned on */ 3559 if (wpa_s == NULL || wpa_s->global == NULL || 3560 wpa_s->dbus_new_path == NULL) 3561 return 0; 3562 ctrl_iface = wpa_s->global->dbus; 3563 if (ctrl_iface == NULL) 3564 return 0; 3565 3566 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3567 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 3568 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 3569 3570 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'", 3571 peer_obj_path); 3572 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path); 3573 3574 return ret; 3575 } 3576 3577 3578 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s, 3579 const u8 *dev_addr) 3580 { 3581 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3582 3583 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3584 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 3585 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 3586 3587 wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path, 3588 WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups"); 3589 } 3590 3591 3592 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = { 3593 { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao", 3594 wpas_dbus_getter_p2p_group_members, 3595 NULL 3596 }, 3597 { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o", 3598 wpas_dbus_getter_p2p_group, 3599 NULL 3600 }, 3601 { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", 3602 wpas_dbus_getter_p2p_role, 3603 NULL 3604 }, 3605 { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 3606 wpas_dbus_getter_p2p_group_ssid, 3607 NULL 3608 }, 3609 { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 3610 wpas_dbus_getter_p2p_group_bssid, 3611 NULL 3612 }, 3613 { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q", 3614 wpas_dbus_getter_p2p_group_frequency, 3615 NULL 3616 }, 3617 { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", 3618 wpas_dbus_getter_p2p_group_passphrase, 3619 NULL 3620 }, 3621 { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 3622 wpas_dbus_getter_p2p_group_psk, 3623 NULL 3624 }, 3625 { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay", 3626 wpas_dbus_getter_p2p_group_vendor_ext, 3627 wpas_dbus_setter_p2p_group_vendor_ext 3628 }, 3629 { NULL, NULL, NULL, NULL, NULL } 3630 }; 3631 3632 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = { 3633 { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP, 3634 { 3635 { "peer", "o", ARG_OUT }, 3636 END_ARGS 3637 } 3638 }, 3639 { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP, 3640 { 3641 { "peer", "o", ARG_OUT }, 3642 END_ARGS 3643 } 3644 }, 3645 { NULL, NULL, { END_ARGS } } 3646 }; 3647 3648 /** 3649 * wpas_dbus_register_p2p_group - Register a p2p group object with dbus 3650 * @wpa_s: wpa_supplicant interface structure 3651 * @ssid: SSID struct 3652 * Returns: 0 on success, -1 on failure 3653 * 3654 * Registers p2p group representing object with dbus 3655 */ 3656 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s, 3657 struct wpa_ssid *ssid) 3658 { 3659 struct wpas_dbus_priv *ctrl_iface; 3660 struct wpa_dbus_object_desc *obj_desc; 3661 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3662 3663 /* Do nothing if the control interface is not turned on */ 3664 if (wpa_s == NULL || wpa_s->global == NULL) 3665 return; 3666 3667 ctrl_iface = wpa_s->global->dbus; 3668 if (ctrl_iface == NULL) 3669 return; 3670 3671 if (wpa_s->dbus_groupobj_path) { 3672 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists", 3673 __func__, wpa_s->dbus_groupobj_path); 3674 return; 3675 } 3676 3677 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0) 3678 return; 3679 3680 wpa_s->dbus_groupobj_path = os_strdup(group_obj_path); 3681 if (wpa_s->dbus_groupobj_path == NULL) 3682 return; 3683 3684 wpa_printf(MSG_INFO, "dbus: Register group object '%s'", 3685 group_obj_path); 3686 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3687 if (!obj_desc) { 3688 wpa_printf(MSG_ERROR, "Not enough memory " 3689 "to create object description"); 3690 goto err; 3691 } 3692 3693 wpas_dbus_register(obj_desc, wpa_s, NULL, NULL, 3694 wpas_dbus_p2p_group_properties, 3695 wpas_dbus_p2p_group_signals); 3696 3697 if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path, 3698 wpa_s->ifname, obj_desc)) 3699 goto err; 3700 3701 return; 3702 3703 err: 3704 if (wpa_s->dbus_groupobj_path) { 3705 os_free(wpa_s->dbus_groupobj_path); 3706 wpa_s->dbus_groupobj_path = NULL; 3707 } 3708 3709 free_dbus_object_desc(obj_desc); 3710 } 3711 3712 /** 3713 * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus 3714 * @wpa_s: wpa_supplicant interface structure 3715 * @ssid: network name of the p2p group started 3716 */ 3717 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s, 3718 const struct wpa_ssid *ssid) 3719 { 3720 struct wpas_dbus_priv *ctrl_iface; 3721 3722 /* Do nothing if the control interface is not turned on */ 3723 if (wpa_s == NULL || wpa_s->global == NULL) 3724 return; 3725 3726 ctrl_iface = wpa_s->global->dbus; 3727 if (ctrl_iface == NULL) 3728 return; 3729 3730 if (!wpa_s->dbus_groupobj_path) { 3731 wpa_printf(MSG_DEBUG, 3732 "%s: Group object '%s' already unregistered", 3733 __func__, wpa_s->dbus_groupobj_path); 3734 return; 3735 } 3736 3737 peer_groups_changed(wpa_s); 3738 3739 wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'", 3740 wpa_s->dbus_groupobj_path); 3741 3742 wpa_dbus_unregister_object_per_iface(ctrl_iface, 3743 wpa_s->dbus_groupobj_path); 3744 3745 os_free(wpa_s->dbus_groupobj_path); 3746 wpa_s->dbus_groupobj_path = NULL; 3747 } 3748 3749 static const struct wpa_dbus_property_desc 3750 wpas_dbus_persistent_group_properties[] = { 3751 { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}", 3752 wpas_dbus_getter_persistent_group_properties, 3753 wpas_dbus_setter_persistent_group_properties 3754 }, 3755 { NULL, NULL, NULL, NULL, NULL } 3756 }; 3757 3758 /* No signals intended for persistent group objects */ 3759 3760 /** 3761 * wpas_dbus_register_persistent_group - Register a configured(saved) 3762 * persistent group with dbus 3763 * @wpa_s: wpa_supplicant interface structure 3764 * @ssid: persistent group (still represented as a network within wpa) 3765 * configuration data 3766 * Returns: 0 on success, -1 on failure 3767 * 3768 * Registers a persistent group representing object with dbus. 3769 */ 3770 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s, 3771 struct wpa_ssid *ssid) 3772 { 3773 struct wpas_dbus_priv *ctrl_iface; 3774 struct wpa_dbus_object_desc *obj_desc; 3775 struct network_handler_args *arg; 3776 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3777 3778 /* Do nothing if the control interface is not turned on */ 3779 if (wpa_s == NULL || wpa_s->global == NULL) 3780 return 0; 3781 3782 /* Make sure ssid is a persistent group */ 3783 if (ssid->disabled != 2 && !ssid->p2p_persistent_group) 3784 return -1; /* should we return w/o complaining? */ 3785 3786 ctrl_iface = wpa_s->global->dbus; 3787 if (ctrl_iface == NULL) 3788 return 0; 3789 3790 /* 3791 * Intentionally not coming up with different numbering scheme 3792 * for persistent groups. 3793 */ 3794 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3795 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 3796 wpa_s->dbus_new_path, ssid->id); 3797 3798 wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'", 3799 pgrp_obj_path); 3800 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3801 if (!obj_desc) { 3802 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create " 3803 "object description"); 3804 goto err; 3805 } 3806 3807 /* 3808 * Reusing the same context structure as that for networks 3809 * since these are represented using same data structure. 3810 */ 3811 /* allocate memory for handlers arguments */ 3812 arg = os_zalloc(sizeof(struct network_handler_args)); 3813 if (!arg) { 3814 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create " 3815 "arguments for method"); 3816 goto err; 3817 } 3818 3819 arg->wpa_s = wpa_s; 3820 arg->ssid = ssid; 3821 3822 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 3823 wpas_dbus_persistent_group_properties, 3824 NULL); 3825 3826 if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path, 3827 wpa_s->ifname, obj_desc)) 3828 goto err; 3829 3830 wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id); 3831 3832 return 0; 3833 3834 err: 3835 free_dbus_object_desc(obj_desc); 3836 return -1; 3837 } 3838 3839 3840 /** 3841 * wpas_dbus_unregister_persistent_group - Unregister a persistent_group 3842 * from dbus 3843 * @wpa_s: wpa_supplicant interface structure 3844 * @nid: network id 3845 * Returns: 0 on success, -1 on failure 3846 * 3847 * Unregisters persistent group representing object from dbus 3848 * 3849 * NOTE: There is a slight issue with the semantics here. While the 3850 * implementation simply means the persistent group is unloaded from memory, 3851 * it should not get interpreted as the group is actually being erased/removed 3852 * from persistent storage as well. 3853 */ 3854 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s, 3855 int nid) 3856 { 3857 struct wpas_dbus_priv *ctrl_iface; 3858 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3859 int ret; 3860 3861 /* Do nothing if the control interface is not turned on */ 3862 if (wpa_s == NULL || wpa_s->global == NULL || 3863 wpa_s->dbus_new_path == NULL) 3864 return 0; 3865 ctrl_iface = wpa_s->global->dbus; 3866 if (ctrl_iface == NULL) 3867 return 0; 3868 3869 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3870 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 3871 wpa_s->dbus_new_path, nid); 3872 3873 wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'", 3874 pgrp_obj_path); 3875 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path); 3876 3877 if (!ret) 3878 wpas_dbus_signal_persistent_group_removed(wpa_s, nid); 3879 3880 return ret; 3881 } 3882 3883 #endif /* CONFIG_P2P */ 3884