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