1 /* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc. 4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa (at) gmail.com> 5 * Copyright (c) 2009, Jouni Malinen <j (at) w1.fi> 6 * 7 * This software may be distributed under the terms of the BSD license. 8 * See README for more details. 9 */ 10 11 #include "includes.h" 12 13 #include "common.h" 14 #include "common/ieee802_11_defs.h" 15 #include "wps/wps.h" 16 #include "../config.h" 17 #include "../wpa_supplicant_i.h" 18 #include "../bss.h" 19 #include "../wpas_glue.h" 20 #include "dbus_new_helpers.h" 21 #include "dbus_dict_helpers.h" 22 #include "dbus_new.h" 23 #include "dbus_new_handlers.h" 24 #include "dbus_common_i.h" 25 #include "dbus_new_handlers_p2p.h" 26 #include "p2p/p2p.h" 27 28 #ifdef CONFIG_AP /* until needed by something else */ 29 30 /* 31 * NameOwnerChanged handling 32 * 33 * Some services we provide allow an application to register for 34 * a signal that it needs. While it can also unregister, we must 35 * be prepared for the case where the application simply crashes 36 * and thus doesn't clean up properly. The way to handle this in 37 * DBus is to register for the NameOwnerChanged signal which will 38 * signal an owner change to NULL if the peer closes the socket 39 * for whatever reason. 40 * 41 * Handle this signal via a filter function whenever necessary. 42 * The code below also handles refcounting in case in the future 43 * there will be multiple instances of this subscription scheme. 44 */ 45 static const char wpas_dbus_noc_filter_str[] = 46 "interface=org.freedesktop.DBus,member=NameOwnerChanged"; 47 48 49 static DBusHandlerResult noc_filter(DBusConnection *conn, 50 DBusMessage *message, void *data) 51 { 52 struct wpas_dbus_priv *priv = data; 53 54 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) 55 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 56 57 if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, 58 "NameOwnerChanged")) { 59 const char *name; 60 const char *prev_owner; 61 const char *new_owner; 62 DBusError derr; 63 struct wpa_supplicant *wpa_s; 64 65 dbus_error_init(&derr); 66 67 if (!dbus_message_get_args(message, &derr, 68 DBUS_TYPE_STRING, &name, 69 DBUS_TYPE_STRING, &prev_owner, 70 DBUS_TYPE_STRING, &new_owner, 71 DBUS_TYPE_INVALID)) { 72 /* Ignore this error */ 73 dbus_error_free(&derr); 74 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 75 } 76 77 for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next) 78 { 79 if (wpa_s->preq_notify_peer != NULL && 80 os_strcmp(name, wpa_s->preq_notify_peer) == 0 && 81 (new_owner == NULL || os_strlen(new_owner) == 0)) { 82 /* probe request owner disconnected */ 83 os_free(wpa_s->preq_notify_peer); 84 wpa_s->preq_notify_peer = NULL; 85 wpas_dbus_unsubscribe_noc(priv); 86 } 87 } 88 } 89 90 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 91 } 92 93 94 void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv) 95 { 96 priv->dbus_noc_refcnt++; 97 if (priv->dbus_noc_refcnt > 1) 98 return; 99 100 if (!dbus_connection_add_filter(priv->con, noc_filter, priv, NULL)) { 101 wpa_printf(MSG_ERROR, "dbus: failed to add filter"); 102 return; 103 } 104 105 dbus_bus_add_match(priv->con, wpas_dbus_noc_filter_str, NULL); 106 } 107 108 109 void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv) 110 { 111 priv->dbus_noc_refcnt--; 112 if (priv->dbus_noc_refcnt > 0) 113 return; 114 115 dbus_bus_remove_match(priv->con, wpas_dbus_noc_filter_str, NULL); 116 dbus_connection_remove_filter(priv->con, noc_filter, priv); 117 } 118 119 #endif /* CONFIG_AP */ 120 121 122 /** 123 * wpas_dbus_signal_interface - Send a interface related event signal 124 * @wpa_s: %wpa_supplicant network interface data 125 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved 126 * @properties: Whether to add second argument with object properties 127 * 128 * Notify listeners about event related with interface 129 */ 130 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s, 131 const char *sig_name, int properties) 132 { 133 struct wpas_dbus_priv *iface; 134 DBusMessage *msg; 135 DBusMessageIter iter; 136 137 iface = wpa_s->global->dbus; 138 139 /* Do nothing if the control interface is not turned on */ 140 if (iface == NULL) 141 return; 142 143 msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH, 144 WPAS_DBUS_NEW_INTERFACE, sig_name); 145 if (msg == NULL) 146 return; 147 148 dbus_message_iter_init_append(msg, &iter); 149 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 150 &wpa_s->dbus_new_path)) 151 goto err; 152 153 if (properties) { 154 if (!wpa_dbus_get_object_properties( 155 iface, wpa_s->dbus_new_path, 156 WPAS_DBUS_NEW_IFACE_INTERFACE, &iter)) 157 goto err; 158 } 159 160 dbus_connection_send(iface->con, msg, NULL); 161 dbus_message_unref(msg); 162 return; 163 164 err: 165 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 166 dbus_message_unref(msg); 167 } 168 169 170 /** 171 * wpas_dbus_signal_interface_added - Send a interface created signal 172 * @wpa_s: %wpa_supplicant network interface data 173 * 174 * Notify listeners about creating new interface 175 */ 176 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s) 177 { 178 wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE); 179 } 180 181 182 /** 183 * wpas_dbus_signal_interface_removed - Send a interface removed signal 184 * @wpa_s: %wpa_supplicant network interface data 185 * 186 * Notify listeners about removing interface 187 */ 188 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s) 189 { 190 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE); 191 192 } 193 194 195 /** 196 * wpas_dbus_signal_scan_done - send scan done signal 197 * @wpa_s: %wpa_supplicant network interface data 198 * @success: indicates if scanning succeed or failed 199 * 200 * Notify listeners about finishing a scan 201 */ 202 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success) 203 { 204 struct wpas_dbus_priv *iface; 205 DBusMessage *msg; 206 dbus_bool_t succ; 207 208 iface = wpa_s->global->dbus; 209 210 /* Do nothing if the control interface is not turned on */ 211 if (iface == NULL) 212 return; 213 214 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 215 WPAS_DBUS_NEW_IFACE_INTERFACE, 216 "ScanDone"); 217 if (msg == NULL) 218 return; 219 220 succ = success ? TRUE : FALSE; 221 if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ, 222 DBUS_TYPE_INVALID)) 223 dbus_connection_send(iface->con, msg, NULL); 224 else 225 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 226 dbus_message_unref(msg); 227 } 228 229 230 /** 231 * wpas_dbus_signal_blob - Send a BSS related event signal 232 * @wpa_s: %wpa_supplicant network interface data 233 * @bss_obj_path: BSS object path 234 * @sig_name: signal name - BSSAdded or BSSRemoved 235 * @properties: Whether to add second argument with object properties 236 * 237 * Notify listeners about event related with BSS 238 */ 239 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s, 240 const char *bss_obj_path, 241 const char *sig_name, int properties) 242 { 243 struct wpas_dbus_priv *iface; 244 DBusMessage *msg; 245 DBusMessageIter iter; 246 247 iface = wpa_s->global->dbus; 248 249 /* Do nothing if the control interface is not turned on */ 250 if (iface == NULL) 251 return; 252 253 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 254 WPAS_DBUS_NEW_IFACE_INTERFACE, 255 sig_name); 256 if (msg == NULL) 257 return; 258 259 dbus_message_iter_init_append(msg, &iter); 260 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 261 &bss_obj_path)) 262 goto err; 263 264 if (properties) { 265 if (!wpa_dbus_get_object_properties(iface, bss_obj_path, 266 WPAS_DBUS_NEW_IFACE_BSS, 267 &iter)) 268 goto err; 269 } 270 271 dbus_connection_send(iface->con, msg, NULL); 272 dbus_message_unref(msg); 273 return; 274 275 err: 276 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 277 dbus_message_unref(msg); 278 } 279 280 281 /** 282 * wpas_dbus_signal_bss_added - Send a BSS added signal 283 * @wpa_s: %wpa_supplicant network interface data 284 * @bss_obj_path: new BSS object path 285 * 286 * Notify listeners about adding new BSS 287 */ 288 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s, 289 const char *bss_obj_path) 290 { 291 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE); 292 } 293 294 295 /** 296 * wpas_dbus_signal_bss_removed - Send a BSS removed signal 297 * @wpa_s: %wpa_supplicant network interface data 298 * @bss_obj_path: BSS object path 299 * 300 * Notify listeners about removing BSS 301 */ 302 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s, 303 const char *bss_obj_path) 304 { 305 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE); 306 } 307 308 309 /** 310 * wpas_dbus_signal_blob - Send a blob related event signal 311 * @wpa_s: %wpa_supplicant network interface data 312 * @name: blob name 313 * @sig_name: signal name - BlobAdded or BlobRemoved 314 * 315 * Notify listeners about event related with blob 316 */ 317 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s, 318 const char *name, const char *sig_name) 319 { 320 struct wpas_dbus_priv *iface; 321 DBusMessage *msg; 322 323 iface = wpa_s->global->dbus; 324 325 /* Do nothing if the control interface is not turned on */ 326 if (iface == NULL) 327 return; 328 329 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 330 WPAS_DBUS_NEW_IFACE_INTERFACE, 331 sig_name); 332 if (msg == NULL) 333 return; 334 335 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, 336 DBUS_TYPE_INVALID)) 337 dbus_connection_send(iface->con, msg, NULL); 338 else 339 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 340 dbus_message_unref(msg); 341 } 342 343 344 /** 345 * wpas_dbus_signal_blob_added - Send a blob added signal 346 * @wpa_s: %wpa_supplicant network interface data 347 * @name: blob name 348 * 349 * Notify listeners about adding a new blob 350 */ 351 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s, 352 const char *name) 353 { 354 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded"); 355 } 356 357 358 /** 359 * wpas_dbus_signal_blob_removed - Send a blob removed signal 360 * @wpa_s: %wpa_supplicant network interface data 361 * @name: blob name 362 * 363 * Notify listeners about removing blob 364 */ 365 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s, 366 const char *name) 367 { 368 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved"); 369 } 370 371 372 /** 373 * wpas_dbus_signal_network - Send a network related event signal 374 * @wpa_s: %wpa_supplicant network interface data 375 * @id: new network id 376 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected 377 * @properties: determines if add second argument with object properties 378 * 379 * Notify listeners about event related with configured network 380 */ 381 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s, 382 int id, const char *sig_name, 383 int properties) 384 { 385 struct wpas_dbus_priv *iface; 386 DBusMessage *msg; 387 DBusMessageIter iter; 388 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 389 390 iface = wpa_s->global->dbus; 391 392 /* Do nothing if the control interface is not turned on */ 393 if (iface == NULL) 394 return; 395 396 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 397 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 398 wpa_s->dbus_new_path, id); 399 400 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 401 WPAS_DBUS_NEW_IFACE_INTERFACE, 402 sig_name); 403 if (msg == NULL) 404 return; 405 406 dbus_message_iter_init_append(msg, &iter); 407 path = net_obj_path; 408 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 409 &path)) 410 goto err; 411 412 if (properties) { 413 if (!wpa_dbus_get_object_properties( 414 iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK, 415 &iter)) 416 goto err; 417 } 418 419 dbus_connection_send(iface->con, msg, NULL); 420 421 dbus_message_unref(msg); 422 return; 423 424 err: 425 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 426 dbus_message_unref(msg); 427 } 428 429 430 /** 431 * wpas_dbus_signal_network_added - Send a network added signal 432 * @wpa_s: %wpa_supplicant network interface data 433 * @id: new network id 434 * 435 * Notify listeners about adding new network 436 */ 437 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s, 438 int id) 439 { 440 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE); 441 } 442 443 444 /** 445 * wpas_dbus_signal_network_removed - Send a network removed signal 446 * @wpa_s: %wpa_supplicant network interface data 447 * @id: network id 448 * 449 * Notify listeners about removing a network 450 */ 451 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s, 452 int id) 453 { 454 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE); 455 } 456 457 458 /** 459 * wpas_dbus_signal_network_selected - Send a network selected signal 460 * @wpa_s: %wpa_supplicant network interface data 461 * @id: network id 462 * 463 * Notify listeners about selecting a network 464 */ 465 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id) 466 { 467 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE); 468 } 469 470 471 /** 472 * wpas_dbus_signal_network_request - Indicate that additional information 473 * (EAP password, etc.) is required to complete the association to this SSID 474 * @wpa_s: %wpa_supplicant network interface data 475 * @rtype: The specific additional information required 476 * @default_text: Optional description of required information 477 * 478 * Request additional information or passwords to complete an association 479 * request. 480 */ 481 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s, 482 struct wpa_ssid *ssid, 483 enum wpa_ctrl_req_type rtype, 484 const char *default_txt) 485 { 486 struct wpas_dbus_priv *iface; 487 DBusMessage *msg; 488 DBusMessageIter iter; 489 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 490 const char *field, *txt = NULL, *net_ptr; 491 492 iface = wpa_s->global->dbus; 493 494 /* Do nothing if the control interface is not turned on */ 495 if (iface == NULL) 496 return; 497 498 field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt); 499 if (field == NULL) 500 return; 501 502 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 503 WPAS_DBUS_NEW_IFACE_INTERFACE, 504 "NetworkRequest"); 505 if (msg == NULL) 506 return; 507 508 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 509 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 510 wpa_s->dbus_new_path, ssid->id); 511 net_ptr = &net_obj_path[0]; 512 513 dbus_message_iter_init_append(msg, &iter); 514 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 515 &net_ptr)) 516 goto err; 517 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field)) 518 goto err; 519 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt)) 520 goto err; 521 522 dbus_connection_send(iface->con, msg, NULL); 523 dbus_message_unref(msg); 524 return; 525 526 err: 527 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 528 dbus_message_unref(msg); 529 } 530 531 532 /** 533 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes 534 * @wpa_s: %wpa_supplicant network interface data 535 * @ssid: configured network which Enabled property has changed 536 * 537 * Sends PropertyChanged signals containing new value of Enabled property 538 * for specified network 539 */ 540 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s, 541 struct wpa_ssid *ssid) 542 { 543 544 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 545 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 546 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 547 wpa_s->dbus_new_path, ssid->id); 548 549 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 550 WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled"); 551 } 552 553 554 #ifdef CONFIG_WPS 555 556 /** 557 * wpas_dbus_signal_wps_event_success - Signals Success WPS event 558 * @wpa_s: %wpa_supplicant network interface data 559 * 560 * Sends Event dbus signal with name "success" and empty dict as arguments 561 */ 562 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s) 563 { 564 565 DBusMessage *msg; 566 DBusMessageIter iter, dict_iter; 567 struct wpas_dbus_priv *iface; 568 char *key = "success"; 569 570 iface = wpa_s->global->dbus; 571 572 /* Do nothing if the control interface is not turned on */ 573 if (iface == NULL) 574 return; 575 576 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 577 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 578 if (msg == NULL) 579 return; 580 581 dbus_message_iter_init_append(msg, &iter); 582 583 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 584 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 585 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 586 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 587 else 588 dbus_connection_send(iface->con, msg, NULL); 589 590 dbus_message_unref(msg); 591 } 592 593 594 /** 595 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event 596 * @wpa_s: %wpa_supplicant network interface data 597 * 598 * Sends Event dbus signal with name "fail" and dictionary containing 599 * "msg field with fail message number (int32) as arguments 600 */ 601 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s, 602 struct wps_event_fail *fail) 603 { 604 605 DBusMessage *msg; 606 DBusMessageIter iter, dict_iter; 607 struct wpas_dbus_priv *iface; 608 char *key = "fail"; 609 610 iface = wpa_s->global->dbus; 611 612 /* Do nothing if the control interface is not turned on */ 613 if (iface == NULL) 614 return; 615 616 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 617 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 618 if (msg == NULL) 619 return; 620 621 dbus_message_iter_init_append(msg, &iter); 622 623 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 624 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 625 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) || 626 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 627 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 628 else 629 dbus_connection_send(iface->con, msg, NULL); 630 631 dbus_message_unref(msg); 632 } 633 634 635 /** 636 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event 637 * @wpa_s: %wpa_supplicant network interface data 638 * 639 * Sends Event dbus signal with name "m2d" and dictionary containing 640 * fields of wps_event_m2d structure. 641 */ 642 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s, 643 struct wps_event_m2d *m2d) 644 { 645 646 DBusMessage *msg; 647 DBusMessageIter iter, dict_iter; 648 struct wpas_dbus_priv *iface; 649 char *key = "m2d"; 650 651 iface = wpa_s->global->dbus; 652 653 /* Do nothing if the control interface is not turned on */ 654 if (iface == NULL) 655 return; 656 657 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 658 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 659 if (msg == NULL) 660 return; 661 662 dbus_message_iter_init_append(msg, &iter); 663 664 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 665 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 666 !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods", 667 m2d->config_methods) || 668 !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer", 669 (const char *) m2d->manufacturer, 670 m2d->manufacturer_len) || 671 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name", 672 (const char *) m2d->model_name, 673 m2d->model_name_len) || 674 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number", 675 (const char *) m2d->model_number, 676 m2d->model_number_len) || 677 !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number", 678 (const char *) 679 m2d->serial_number, 680 m2d->serial_number_len) || 681 !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name", 682 (const char *) m2d->dev_name, 683 m2d->dev_name_len) || 684 !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type", 685 (const char *) 686 m2d->primary_dev_type, 8) || 687 !wpa_dbus_dict_append_uint16(&dict_iter, "config_error", 688 m2d->config_error) || 689 !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id", 690 m2d->dev_password_id) || 691 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 692 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 693 else 694 dbus_connection_send(iface->con, msg, NULL); 695 696 dbus_message_unref(msg); 697 } 698 699 700 /** 701 * wpas_dbus_signal_wps_cred - Signals new credentials 702 * @wpa_s: %wpa_supplicant network interface data 703 * 704 * Sends signal with credentials in directory argument 705 */ 706 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s, 707 const struct wps_credential *cred) 708 { 709 DBusMessage *msg; 710 DBusMessageIter iter, dict_iter; 711 struct wpas_dbus_priv *iface; 712 char *auth_type[6]; /* we have six possible authorization types */ 713 int at_num = 0; 714 char *encr_type[4]; /* we have four possible encryption types */ 715 int et_num = 0; 716 717 iface = wpa_s->global->dbus; 718 719 /* Do nothing if the control interface is not turned on */ 720 if (iface == NULL) 721 return; 722 723 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 724 WPAS_DBUS_NEW_IFACE_WPS, 725 "Credentials"); 726 if (msg == NULL) 727 return; 728 729 dbus_message_iter_init_append(msg, &iter); 730 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) 731 goto nomem; 732 733 if (cred->auth_type & WPS_AUTH_OPEN) 734 auth_type[at_num++] = "open"; 735 if (cred->auth_type & WPS_AUTH_WPAPSK) 736 auth_type[at_num++] = "wpa-psk"; 737 if (cred->auth_type & WPS_AUTH_SHARED) 738 auth_type[at_num++] = "shared"; 739 if (cred->auth_type & WPS_AUTH_WPA) 740 auth_type[at_num++] = "wpa-eap"; 741 if (cred->auth_type & WPS_AUTH_WPA2) 742 auth_type[at_num++] = "wpa2-eap"; 743 if (cred->auth_type & WPS_AUTH_WPA2PSK) 744 auth_type[at_num++] = 745 "wpa2-psk"; 746 747 if (cred->encr_type & WPS_ENCR_NONE) 748 encr_type[et_num++] = "none"; 749 if (cred->encr_type & WPS_ENCR_WEP) 750 encr_type[et_num++] = "wep"; 751 if (cred->encr_type & WPS_ENCR_TKIP) 752 encr_type[et_num++] = "tkip"; 753 if (cred->encr_type & WPS_ENCR_AES) 754 encr_type[et_num++] = "aes"; 755 756 if (wpa_s->current_ssid) { 757 if (!wpa_dbus_dict_append_byte_array( 758 &dict_iter, "BSSID", 759 (const char *) wpa_s->current_ssid->bssid, 760 ETH_ALEN)) 761 goto nomem; 762 } 763 764 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID", 765 (const char *) cred->ssid, 766 cred->ssid_len) || 767 !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType", 768 (const char **) auth_type, 769 at_num) || 770 !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType", 771 (const char **) encr_type, 772 et_num) || 773 !wpa_dbus_dict_append_byte_array(&dict_iter, "Key", 774 (const char *) cred->key, 775 cred->key_len) || 776 !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex", 777 cred->key_idx) || 778 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 779 goto nomem; 780 781 dbus_connection_send(iface->con, msg, NULL); 782 783 nomem: 784 dbus_message_unref(msg); 785 } 786 787 #endif /* CONFIG_WPS */ 788 789 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s, 790 int depth, const char *subject, 791 const char *cert_hash, 792 const struct wpabuf *cert) 793 { 794 struct wpas_dbus_priv *iface; 795 DBusMessage *msg; 796 DBusMessageIter iter, dict_iter; 797 798 iface = wpa_s->global->dbus; 799 800 /* Do nothing if the control interface is not turned on */ 801 if (iface == NULL) 802 return; 803 804 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 805 WPAS_DBUS_NEW_IFACE_INTERFACE, 806 "Certification"); 807 if (msg == NULL) 808 return; 809 810 dbus_message_iter_init_append(msg, &iter); 811 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) 812 goto nomem; 813 814 if (!wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) || 815 !wpa_dbus_dict_append_string(&dict_iter, "subject", subject)) 816 goto nomem; 817 818 if (cert_hash && 819 !wpa_dbus_dict_append_string(&dict_iter, "cert_hash", cert_hash)) 820 goto nomem; 821 822 if (cert && 823 !wpa_dbus_dict_append_byte_array(&dict_iter, "cert", 824 wpabuf_head(cert), 825 wpabuf_len(cert))) 826 goto nomem; 827 828 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) 829 goto nomem; 830 831 dbus_connection_send(iface->con, msg, NULL); 832 833 nomem: 834 dbus_message_unref(msg); 835 } 836 837 838 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s, 839 const char *status, const char *parameter) 840 { 841 struct wpas_dbus_priv *iface; 842 DBusMessage *msg; 843 DBusMessageIter iter; 844 845 iface = wpa_s->global->dbus; 846 847 /* Do nothing if the control interface is not turned on */ 848 if (iface == NULL) 849 return; 850 851 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 852 WPAS_DBUS_NEW_IFACE_INTERFACE, 853 "EAP"); 854 if (msg == NULL) 855 return; 856 857 dbus_message_iter_init_append(msg, &iter); 858 859 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) 860 || 861 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, 862 ¶meter)) 863 goto nomem; 864 865 dbus_connection_send(iface->con, msg, NULL); 866 867 nomem: 868 dbus_message_unref(msg); 869 } 870 871 872 #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 { NULL, NULL, NULL, NULL, NULL } 1954 }; 1955 1956 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = { 1957 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE, 1958 { 1959 { "path", "o", ARG_OUT }, 1960 { "properties", "a{sv}", ARG_OUT }, 1961 END_ARGS 1962 } 1963 }, 1964 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE, 1965 { 1966 { "path", "o", ARG_OUT }, 1967 END_ARGS 1968 } 1969 }, 1970 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 1971 { 1972 { "path", "o", ARG_OUT }, 1973 { "field", "s", ARG_OUT }, 1974 { "text", "s", ARG_OUT }, 1975 END_ARGS 1976 } 1977 }, 1978 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 1979 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE, 1980 { 1981 { "properties", "a{sv}", ARG_OUT }, 1982 END_ARGS 1983 } 1984 }, 1985 { NULL, NULL, { END_ARGS } } 1986 }; 1987 1988 1989 /** 1990 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface 1991 * @global: Pointer to global data from wpa_supplicant_init() 1992 * Returns: 0 on success or -1 on failure 1993 * 1994 * Initialize the dbus control interface for wpa_supplicantand and start 1995 * receiving commands from external programs over the bus. 1996 */ 1997 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv) 1998 { 1999 struct wpa_dbus_object_desc *obj_desc; 2000 int ret; 2001 2002 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2003 if (!obj_desc) { 2004 wpa_printf(MSG_ERROR, "Not enough memory " 2005 "to create object description"); 2006 return -1; 2007 } 2008 2009 wpas_dbus_register(obj_desc, priv->global, NULL, 2010 wpas_dbus_global_methods, 2011 wpas_dbus_global_properties, 2012 wpas_dbus_global_signals); 2013 2014 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'", 2015 WPAS_DBUS_NEW_PATH); 2016 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH, 2017 WPAS_DBUS_NEW_SERVICE, 2018 obj_desc); 2019 if (ret < 0) 2020 free_dbus_object_desc(obj_desc); 2021 else 2022 priv->dbus_new_initialized = 1; 2023 2024 return ret; 2025 } 2026 2027 2028 /** 2029 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for 2030 * wpa_supplicant 2031 * @iface: Pointer to dbus private data from wpas_dbus_init() 2032 * 2033 * Deinitialize the dbus control interface that was initialized with 2034 * wpas_dbus_ctrl_iface_init(). 2035 */ 2036 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface) 2037 { 2038 if (!iface->dbus_new_initialized) 2039 return; 2040 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'", 2041 WPAS_DBUS_NEW_PATH); 2042 dbus_connection_unregister_object_path(iface->con, 2043 WPAS_DBUS_NEW_PATH); 2044 } 2045 2046 2047 static void wpa_dbus_free(void *ptr) 2048 { 2049 os_free(ptr); 2050 } 2051 2052 2053 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = { 2054 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}", 2055 wpas_dbus_getter_network_properties, 2056 wpas_dbus_setter_network_properties 2057 }, 2058 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b", 2059 wpas_dbus_getter_enabled, 2060 wpas_dbus_setter_enabled 2061 }, 2062 { NULL, NULL, NULL, NULL, NULL } 2063 }; 2064 2065 2066 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = { 2067 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2068 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK, 2069 { 2070 { "properties", "a{sv}", ARG_OUT }, 2071 END_ARGS 2072 } 2073 }, 2074 { NULL, NULL, { END_ARGS } } 2075 }; 2076 2077 2078 /** 2079 * wpas_dbus_register_network - Register a configured network with dbus 2080 * @wpa_s: wpa_supplicant interface structure 2081 * @ssid: network configuration data 2082 * Returns: 0 on success, -1 on failure 2083 * 2084 * Registers network representing object with dbus 2085 */ 2086 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s, 2087 struct wpa_ssid *ssid) 2088 { 2089 struct wpas_dbus_priv *ctrl_iface; 2090 struct wpa_dbus_object_desc *obj_desc; 2091 struct network_handler_args *arg; 2092 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2093 2094 #ifdef CONFIG_P2P 2095 /* 2096 * If it is a persistent group register it as such. 2097 * This is to handle cases where an interface is being initialized 2098 * with a list of networks read from config. 2099 */ 2100 if (network_is_persistent_group(ssid)) 2101 return wpas_dbus_register_persistent_group(wpa_s, ssid); 2102 #endif /* CONFIG_P2P */ 2103 2104 /* Do nothing if the control interface is not turned on */ 2105 if (wpa_s == NULL || wpa_s->global == NULL) 2106 return 0; 2107 ctrl_iface = wpa_s->global->dbus; 2108 if (ctrl_iface == NULL) 2109 return 0; 2110 2111 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2112 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2113 wpa_s->dbus_new_path, ssid->id); 2114 2115 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'", 2116 net_obj_path); 2117 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2118 if (!obj_desc) { 2119 wpa_printf(MSG_ERROR, "Not enough memory " 2120 "to create object description"); 2121 goto err; 2122 } 2123 2124 /* allocate memory for handlers arguments */ 2125 arg = os_zalloc(sizeof(struct network_handler_args)); 2126 if (!arg) { 2127 wpa_printf(MSG_ERROR, "Not enough memory " 2128 "to create arguments for method"); 2129 goto err; 2130 } 2131 2132 arg->wpa_s = wpa_s; 2133 arg->ssid = ssid; 2134 2135 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2136 wpas_dbus_network_properties, 2137 wpas_dbus_network_signals); 2138 2139 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path, 2140 wpa_s->ifname, obj_desc)) 2141 goto err; 2142 2143 wpas_dbus_signal_network_added(wpa_s, ssid->id); 2144 2145 return 0; 2146 2147 err: 2148 free_dbus_object_desc(obj_desc); 2149 return -1; 2150 } 2151 2152 2153 /** 2154 * wpas_dbus_unregister_network - Unregister a configured network from dbus 2155 * @wpa_s: wpa_supplicant interface structure 2156 * @nid: network id 2157 * Returns: 0 on success, -1 on failure 2158 * 2159 * Unregisters network representing object from dbus 2160 */ 2161 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid) 2162 { 2163 struct wpas_dbus_priv *ctrl_iface; 2164 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2165 int ret; 2166 #ifdef CONFIG_P2P 2167 struct wpa_ssid *ssid; 2168 2169 ssid = wpa_config_get_network(wpa_s->conf, nid); 2170 2171 /* If it is a persistent group unregister it as such */ 2172 if (ssid && network_is_persistent_group(ssid)) 2173 return wpas_dbus_unregister_persistent_group(wpa_s, nid); 2174 #endif /* CONFIG_P2P */ 2175 2176 /* Do nothing if the control interface is not turned on */ 2177 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL) 2178 return 0; 2179 ctrl_iface = wpa_s->global->dbus; 2180 if (ctrl_iface == NULL) 2181 return 0; 2182 2183 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2184 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2185 wpa_s->dbus_new_path, nid); 2186 2187 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'", 2188 net_obj_path); 2189 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path); 2190 2191 if (!ret) 2192 wpas_dbus_signal_network_removed(wpa_s, nid); 2193 2194 return ret; 2195 } 2196 2197 2198 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = { 2199 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2200 wpas_dbus_getter_bss_ssid, 2201 NULL 2202 }, 2203 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2204 wpas_dbus_getter_bss_bssid, 2205 NULL 2206 }, 2207 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b", 2208 wpas_dbus_getter_bss_privacy, 2209 NULL 2210 }, 2211 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s", 2212 wpas_dbus_getter_bss_mode, 2213 NULL 2214 }, 2215 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n", 2216 wpas_dbus_getter_bss_signal, 2217 NULL 2218 }, 2219 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q", 2220 wpas_dbus_getter_bss_frequency, 2221 NULL 2222 }, 2223 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au", 2224 wpas_dbus_getter_bss_rates, 2225 NULL 2226 }, 2227 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2228 wpas_dbus_getter_bss_wpa, 2229 NULL 2230 }, 2231 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2232 wpas_dbus_getter_bss_rsn, 2233 NULL 2234 }, 2235 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2236 wpas_dbus_getter_bss_ies, 2237 NULL 2238 }, 2239 { NULL, NULL, NULL, NULL, NULL } 2240 }; 2241 2242 2243 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = { 2244 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2245 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS, 2246 { 2247 { "properties", "a{sv}", ARG_OUT }, 2248 END_ARGS 2249 } 2250 }, 2251 { NULL, NULL, { END_ARGS } } 2252 }; 2253 2254 2255 /** 2256 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus 2257 * @wpa_s: wpa_supplicant interface structure 2258 * @bssid: scanned network bssid 2259 * @id: unique BSS identifier 2260 * Returns: 0 on success, -1 on failure 2261 * 2262 * Unregisters BSS representing object from dbus 2263 */ 2264 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s, 2265 u8 bssid[ETH_ALEN], unsigned int id) 2266 { 2267 struct wpas_dbus_priv *ctrl_iface; 2268 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2269 2270 /* Do nothing if the control interface is not turned on */ 2271 if (wpa_s == NULL || wpa_s->global == NULL) 2272 return 0; 2273 ctrl_iface = wpa_s->global->dbus; 2274 if (ctrl_iface == NULL) 2275 return 0; 2276 2277 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2278 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2279 wpa_s->dbus_new_path, id); 2280 2281 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'", 2282 bss_obj_path); 2283 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) { 2284 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s", 2285 bss_obj_path); 2286 return -1; 2287 } 2288 2289 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path); 2290 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 2291 2292 return 0; 2293 } 2294 2295 2296 /** 2297 * wpas_dbus_register_bss - Register a scanned BSS with dbus 2298 * @wpa_s: wpa_supplicant interface structure 2299 * @bssid: scanned network bssid 2300 * @id: unique BSS identifier 2301 * Returns: 0 on success, -1 on failure 2302 * 2303 * Registers BSS representing object with dbus 2304 */ 2305 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, 2306 u8 bssid[ETH_ALEN], unsigned int id) 2307 { 2308 struct wpas_dbus_priv *ctrl_iface; 2309 struct wpa_dbus_object_desc *obj_desc; 2310 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2311 struct bss_handler_args *arg; 2312 2313 /* Do nothing if the control interface is not turned on */ 2314 if (wpa_s == NULL || wpa_s->global == NULL) 2315 return 0; 2316 ctrl_iface = wpa_s->global->dbus; 2317 if (ctrl_iface == NULL) 2318 return 0; 2319 2320 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2321 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2322 wpa_s->dbus_new_path, id); 2323 2324 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2325 if (!obj_desc) { 2326 wpa_printf(MSG_ERROR, "Not enough memory " 2327 "to create object description"); 2328 goto err; 2329 } 2330 2331 arg = os_zalloc(sizeof(struct bss_handler_args)); 2332 if (!arg) { 2333 wpa_printf(MSG_ERROR, "Not enough memory " 2334 "to create arguments for handler"); 2335 goto err; 2336 } 2337 arg->wpa_s = wpa_s; 2338 arg->id = id; 2339 2340 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2341 wpas_dbus_bss_properties, 2342 wpas_dbus_bss_signals); 2343 2344 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'", 2345 bss_obj_path); 2346 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path, 2347 wpa_s->ifname, obj_desc)) { 2348 wpa_printf(MSG_ERROR, 2349 "Cannot register BSSID dbus object %s.", 2350 bss_obj_path); 2351 goto err; 2352 } 2353 2354 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path); 2355 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 2356 2357 return 0; 2358 2359 err: 2360 free_dbus_object_desc(obj_desc); 2361 return -1; 2362 } 2363 2364 2365 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { 2366 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE, 2367 (WPADBusMethodHandler) &wpas_dbus_handler_scan, 2368 { 2369 { "args", "a{sv}", ARG_IN }, 2370 END_ARGS 2371 } 2372 }, 2373 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 2374 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect, 2375 { 2376 END_ARGS 2377 } 2378 }, 2379 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2380 (WPADBusMethodHandler) &wpas_dbus_handler_add_network, 2381 { 2382 { "args", "a{sv}", ARG_IN }, 2383 { "path", "o", ARG_OUT }, 2384 END_ARGS 2385 } 2386 }, 2387 { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE, 2388 (WPADBusMethodHandler) &wpas_dbus_handler_reassociate, 2389 { 2390 END_ARGS 2391 } 2392 }, 2393 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2394 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network, 2395 { 2396 { "path", "o", ARG_IN }, 2397 END_ARGS 2398 } 2399 }, 2400 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE, 2401 (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks, 2402 { 2403 END_ARGS 2404 } 2405 }, 2406 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2407 (WPADBusMethodHandler) &wpas_dbus_handler_select_network, 2408 { 2409 { "path", "o", ARG_IN }, 2410 END_ARGS 2411 } 2412 }, 2413 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE, 2414 (WPADBusMethodHandler) &wpas_dbus_handler_network_reply, 2415 { 2416 { "path", "o", ARG_IN }, 2417 { "field", "s", ARG_IN }, 2418 { "value", "s", ARG_IN }, 2419 END_ARGS 2420 } 2421 }, 2422 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2423 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob, 2424 { 2425 { "name", "s", ARG_IN }, 2426 { "data", "ay", ARG_IN }, 2427 END_ARGS 2428 } 2429 }, 2430 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2431 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob, 2432 { 2433 { "name", "s", ARG_IN }, 2434 { "data", "ay", ARG_OUT }, 2435 END_ARGS 2436 } 2437 }, 2438 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2439 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob, 2440 { 2441 { "name", "s", ARG_IN }, 2442 END_ARGS 2443 } 2444 }, 2445 #ifdef CONFIG_WPS 2446 { "Start", WPAS_DBUS_NEW_IFACE_WPS, 2447 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start, 2448 { 2449 { "args", "a{sv}", ARG_IN }, 2450 { "output", "a{sv}", ARG_OUT }, 2451 END_ARGS 2452 } 2453 }, 2454 #endif /* CONFIG_WPS */ 2455 #ifdef CONFIG_P2P 2456 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2457 (WPADBusMethodHandler)wpas_dbus_handler_p2p_find, 2458 { 2459 { "args", "a{sv}", ARG_IN }, 2460 END_ARGS 2461 } 2462 }, 2463 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2464 (WPADBusMethodHandler)wpas_dbus_handler_p2p_stop_find, 2465 { 2466 END_ARGS 2467 } 2468 }, 2469 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2470 (WPADBusMethodHandler)wpas_dbus_handler_p2p_listen, 2471 { 2472 { "timeout", "i", ARG_IN }, 2473 END_ARGS 2474 } 2475 }, 2476 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2477 (WPADBusMethodHandler)wpas_dbus_handler_p2p_extendedlisten, 2478 { 2479 { "args", "a{sv}", ARG_IN }, 2480 END_ARGS 2481 } 2482 }, 2483 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2484 (WPADBusMethodHandler)wpas_dbus_handler_p2p_presence_request, 2485 { 2486 { "args", "a{sv}", ARG_IN }, 2487 END_ARGS 2488 } 2489 }, 2490 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2491 (WPADBusMethodHandler)wpas_dbus_handler_p2p_prov_disc_req, 2492 { 2493 { "peer", "o", ARG_IN }, 2494 { "config_method", "s", ARG_IN }, 2495 END_ARGS 2496 } 2497 }, 2498 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2499 (WPADBusMethodHandler)wpas_dbus_handler_p2p_connect, 2500 { 2501 { "args", "a{sv}", ARG_IN }, 2502 { "generated_pin", "s", ARG_OUT }, 2503 END_ARGS 2504 } 2505 }, 2506 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2507 (WPADBusMethodHandler)wpas_dbus_handler_p2p_group_add, 2508 { 2509 { "args", "a{sv}", ARG_IN }, 2510 END_ARGS 2511 } 2512 }, 2513 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2514 (WPADBusMethodHandler)wpas_dbus_handler_p2p_invite, 2515 { 2516 { "args", "a{sv}", ARG_IN }, 2517 END_ARGS 2518 } 2519 }, 2520 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2521 (WPADBusMethodHandler)wpas_dbus_handler_p2p_disconnect, 2522 { 2523 END_ARGS 2524 } 2525 }, 2526 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2527 (WPADBusMethodHandler)wpas_dbus_handler_p2p_rejectpeer, 2528 { 2529 { "peer", "o", ARG_IN }, 2530 END_ARGS 2531 } 2532 }, 2533 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2534 (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush, 2535 { 2536 END_ARGS 2537 } 2538 }, 2539 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2540 (WPADBusMethodHandler)wpas_dbus_handler_p2p_add_service, 2541 { 2542 { "args", "a{sv}", ARG_IN }, 2543 END_ARGS 2544 } 2545 }, 2546 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2547 (WPADBusMethodHandler)wpas_dbus_handler_p2p_delete_service, 2548 { 2549 { "args", "a{sv}", ARG_IN }, 2550 END_ARGS 2551 } 2552 }, 2553 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2554 (WPADBusMethodHandler)wpas_dbus_handler_p2p_flush_service, 2555 { 2556 END_ARGS 2557 } 2558 }, 2559 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2560 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req, 2561 { 2562 { "args", "a{sv}", ARG_IN }, 2563 END_ARGS 2564 } 2565 }, 2566 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2567 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_res, 2568 { 2569 { "args", "a{sv}", ARG_IN }, 2570 END_ARGS 2571 } 2572 }, 2573 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2574 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_cancel_req, 2575 { 2576 { "args", "t", ARG_IN }, 2577 END_ARGS 2578 } 2579 }, 2580 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2581 (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_update, 2582 { 2583 END_ARGS 2584 } 2585 }, 2586 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2587 (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external, 2588 { 2589 { "arg", "i", ARG_IN }, 2590 END_ARGS 2591 } 2592 }, 2593 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2594 (WPADBusMethodHandler)wpas_dbus_handler_p2p_serv_disc_external, 2595 { 2596 { "arg", "i", ARG_IN }, 2597 END_ARGS 2598 } 2599 }, 2600 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2601 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group, 2602 { 2603 { "args", "a{sv}", ARG_IN }, 2604 { "path", "o", ARG_OUT }, 2605 END_ARGS 2606 } 2607 }, 2608 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2609 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group, 2610 { 2611 { "path", "o", ARG_IN }, 2612 END_ARGS 2613 } 2614 }, 2615 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2616 (WPADBusMethodHandler) 2617 wpas_dbus_handler_remove_all_persistent_groups, 2618 { 2619 END_ARGS 2620 } 2621 }, 2622 #endif /* CONFIG_P2P */ 2623 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, 2624 (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss, 2625 { 2626 { "age", "u", ARG_IN }, 2627 END_ARGS 2628 } 2629 }, 2630 #ifdef CONFIG_AP 2631 { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 2632 (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq, 2633 { 2634 END_ARGS 2635 } 2636 }, 2637 { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 2638 (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq, 2639 { 2640 END_ARGS 2641 } 2642 }, 2643 #endif /* CONFIG_AP */ 2644 { NULL, NULL, NULL, { END_ARGS } } 2645 }; 2646 2647 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { 2648 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}", 2649 wpas_dbus_getter_capabilities, 2650 NULL 2651 }, 2652 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2653 wpas_dbus_getter_state, 2654 NULL 2655 }, 2656 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 2657 wpas_dbus_getter_scanning, 2658 NULL 2659 }, 2660 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2661 wpas_dbus_getter_ap_scan, 2662 wpas_dbus_setter_ap_scan 2663 }, 2664 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2665 wpas_dbus_getter_bss_expire_age, 2666 wpas_dbus_setter_bss_expire_age 2667 }, 2668 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2669 wpas_dbus_getter_bss_expire_count, 2670 wpas_dbus_setter_bss_expire_count 2671 }, 2672 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2673 wpas_dbus_getter_country, 2674 wpas_dbus_setter_country 2675 }, 2676 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2677 wpas_dbus_getter_ifname, 2678 NULL 2679 }, 2680 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2681 wpas_dbus_getter_driver, 2682 NULL 2683 }, 2684 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2685 wpas_dbus_getter_bridge_ifname, 2686 NULL 2687 }, 2688 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 2689 wpas_dbus_getter_current_bss, 2690 NULL 2691 }, 2692 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 2693 wpas_dbus_getter_current_network, 2694 NULL 2695 }, 2696 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 2697 wpas_dbus_getter_current_auth_mode, 2698 NULL 2699 }, 2700 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}", 2701 wpas_dbus_getter_blobs, 2702 NULL 2703 }, 2704 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 2705 wpas_dbus_getter_bsss, 2706 NULL 2707 }, 2708 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 2709 wpas_dbus_getter_networks, 2710 NULL 2711 }, 2712 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 2713 wpas_dbus_getter_fast_reauth, 2714 wpas_dbus_setter_fast_reauth 2715 }, 2716 { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 2717 wpas_dbus_getter_scan_interval, 2718 wpas_dbus_setter_scan_interval 2719 }, 2720 #ifdef CONFIG_WPS 2721 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b", 2722 wpas_dbus_getter_process_credentials, 2723 wpas_dbus_setter_process_credentials 2724 }, 2725 #endif /* CONFIG_WPS */ 2726 #ifdef CONFIG_P2P 2727 { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}", 2728 wpas_dbus_getter_p2p_device_config, 2729 wpas_dbus_setter_p2p_device_config 2730 }, 2731 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 2732 wpas_dbus_getter_p2p_peers, 2733 NULL 2734 }, 2735 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s", 2736 wpas_dbus_getter_p2p_role, 2737 NULL 2738 }, 2739 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 2740 wpas_dbus_getter_p2p_group, 2741 NULL 2742 }, 2743 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 2744 wpas_dbus_getter_p2p_peergo, 2745 NULL 2746 }, 2747 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 2748 wpas_dbus_getter_persistent_groups, 2749 NULL 2750 }, 2751 #endif /* CONFIG_P2P */ 2752 { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 2753 wpas_dbus_getter_disconnect_reason, 2754 NULL 2755 }, 2756 { NULL, NULL, NULL, NULL, NULL } 2757 }; 2758 2759 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { 2760 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE, 2761 { 2762 { "success", "b", ARG_OUT }, 2763 END_ARGS 2764 } 2765 }, 2766 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 2767 { 2768 { "path", "o", ARG_OUT }, 2769 { "properties", "a{sv}", ARG_OUT }, 2770 END_ARGS 2771 } 2772 }, 2773 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 2774 { 2775 { "path", "o", ARG_OUT }, 2776 END_ARGS 2777 } 2778 }, 2779 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 2780 { 2781 { "name", "s", ARG_OUT }, 2782 END_ARGS 2783 } 2784 }, 2785 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 2786 { 2787 { "name", "s", ARG_OUT }, 2788 END_ARGS 2789 } 2790 }, 2791 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 2792 { 2793 { "path", "o", ARG_OUT }, 2794 { "properties", "a{sv}", ARG_OUT }, 2795 END_ARGS 2796 } 2797 }, 2798 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 2799 { 2800 { "path", "o", ARG_OUT }, 2801 END_ARGS 2802 } 2803 }, 2804 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE, 2805 { 2806 { "path", "o", ARG_OUT }, 2807 END_ARGS 2808 } 2809 }, 2810 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2811 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE, 2812 { 2813 { "properties", "a{sv}", ARG_OUT }, 2814 END_ARGS 2815 } 2816 }, 2817 #ifdef CONFIG_WPS 2818 { "Event", WPAS_DBUS_NEW_IFACE_WPS, 2819 { 2820 { "name", "s", ARG_OUT }, 2821 { "args", "a{sv}", ARG_OUT }, 2822 END_ARGS 2823 } 2824 }, 2825 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS, 2826 { 2827 { "credentials", "a{sv}", ARG_OUT }, 2828 END_ARGS 2829 } 2830 }, 2831 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2832 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS, 2833 { 2834 { "properties", "a{sv}", ARG_OUT }, 2835 END_ARGS 2836 } 2837 }, 2838 #endif /* CONFIG_WPS */ 2839 #ifdef CONFIG_P2P 2840 { "P2PStateChanged", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2841 { 2842 { "states", "a{ss}", ARG_OUT }, 2843 END_ARGS 2844 } 2845 }, 2846 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2847 { 2848 { "path", "o", ARG_OUT }, 2849 { "properties", "a{sv}", ARG_OUT }, 2850 END_ARGS 2851 } 2852 }, 2853 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2854 { 2855 { "path", "o", ARG_OUT }, 2856 END_ARGS 2857 } 2858 }, 2859 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2860 { 2861 { "peer_object", "o", ARG_OUT }, 2862 { "pin", "s", ARG_OUT }, 2863 END_ARGS 2864 } 2865 }, 2866 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2867 { 2868 { "peer_object", "o", ARG_OUT }, 2869 { "pin", "s", ARG_OUT }, 2870 END_ARGS 2871 } 2872 }, 2873 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2874 { 2875 { "peer_object", "o", ARG_OUT }, 2876 END_ARGS 2877 } 2878 }, 2879 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2880 { 2881 { "peer_object", "o", ARG_OUT }, 2882 END_ARGS 2883 } 2884 }, 2885 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2886 { 2887 { "peer_object", "o", ARG_OUT }, 2888 END_ARGS 2889 } 2890 }, 2891 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2892 { 2893 { "peer_object", "o", ARG_OUT }, 2894 END_ARGS 2895 } 2896 }, 2897 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2898 { 2899 { "peer_object", "o", ARG_OUT }, 2900 { "status", "i", ARG_OUT }, 2901 END_ARGS 2902 } 2903 }, 2904 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2905 { 2906 { "properties", "a{sv}", ARG_OUT }, 2907 END_ARGS 2908 } 2909 }, 2910 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2911 { 2912 END_ARGS 2913 } 2914 }, 2915 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2916 { 2917 { "status", "i", ARG_OUT }, 2918 END_ARGS 2919 } 2920 }, 2921 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2922 { 2923 { "path", "o", ARG_OUT }, 2924 { "dev_passwd_id", "i", ARG_OUT }, 2925 END_ARGS 2926 } 2927 }, 2928 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2929 { 2930 { "invite_result", "a{sv}", ARG_OUT }, 2931 END_ARGS 2932 } 2933 }, 2934 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2935 { 2936 { "ifname", "s", ARG_OUT }, 2937 { "role", "s", ARG_OUT }, 2938 END_ARGS 2939 } 2940 }, 2941 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2942 { 2943 { "sd_request", "a{sv}", ARG_OUT }, 2944 END_ARGS 2945 } 2946 }, 2947 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2948 { 2949 { "sd_response", "a{sv}", ARG_OUT }, 2950 END_ARGS 2951 } 2952 }, 2953 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2954 { 2955 { "path", "o", ARG_OUT }, 2956 { "properties", "a{sv}", ARG_OUT }, 2957 END_ARGS 2958 } 2959 }, 2960 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2961 { 2962 { "path", "o", ARG_OUT }, 2963 END_ARGS 2964 } 2965 }, 2966 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2967 { 2968 { "name", "s", ARG_OUT }, 2969 { "args", "a{sv}", ARG_OUT }, 2970 END_ARGS 2971 } 2972 }, 2973 #endif /* CONFIG_P2P */ 2974 #ifdef CONFIG_AP 2975 { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 2976 { 2977 { "args", "a{sv}", ARG_OUT }, 2978 END_ARGS 2979 } 2980 }, 2981 #endif /* CONFIG_AP */ 2982 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE, 2983 { 2984 { "certification", "a{sv}", ARG_OUT }, 2985 END_ARGS 2986 } 2987 }, 2988 { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE, 2989 { 2990 { "status", "s", ARG_OUT }, 2991 { "parameter", "s", ARG_OUT }, 2992 END_ARGS 2993 } 2994 }, 2995 { NULL, NULL, { END_ARGS } } 2996 }; 2997 2998 2999 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s) 3000 { 3001 3002 struct wpa_dbus_object_desc *obj_desc = NULL; 3003 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus; 3004 int next; 3005 3006 /* Do nothing if the control interface is not turned on */ 3007 if (ctrl_iface == NULL) 3008 return 0; 3009 3010 /* Create and set the interface's object path */ 3011 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 3012 if (wpa_s->dbus_new_path == NULL) 3013 return -1; 3014 next = ctrl_iface->next_objid++; 3015 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX, 3016 WPAS_DBUS_NEW_PATH_INTERFACES "/%u", 3017 next); 3018 3019 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3020 if (!obj_desc) { 3021 wpa_printf(MSG_ERROR, "Not enough memory " 3022 "to create object description"); 3023 goto err; 3024 } 3025 3026 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods, 3027 wpas_dbus_interface_properties, 3028 wpas_dbus_interface_signals); 3029 3030 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", 3031 wpa_s->dbus_new_path); 3032 if (wpa_dbus_register_object_per_iface(ctrl_iface, 3033 wpa_s->dbus_new_path, 3034 wpa_s->ifname, obj_desc)) 3035 goto err; 3036 3037 wpas_dbus_signal_interface_added(wpa_s); 3038 3039 return 0; 3040 3041 err: 3042 os_free(wpa_s->dbus_new_path); 3043 wpa_s->dbus_new_path = NULL; 3044 free_dbus_object_desc(obj_desc); 3045 return -1; 3046 } 3047 3048 3049 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s) 3050 { 3051 struct wpas_dbus_priv *ctrl_iface; 3052 3053 /* Do nothing if the control interface is not turned on */ 3054 if (wpa_s == NULL || wpa_s->global == NULL) 3055 return 0; 3056 ctrl_iface = wpa_s->global->dbus; 3057 if (ctrl_iface == NULL) 3058 return 0; 3059 3060 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'", 3061 wpa_s->dbus_new_path); 3062 3063 #ifdef CONFIG_AP 3064 if (wpa_s->preq_notify_peer) { 3065 wpas_dbus_unsubscribe_noc(ctrl_iface); 3066 os_free(wpa_s->preq_notify_peer); 3067 wpa_s->preq_notify_peer = NULL; 3068 } 3069 #endif /* CONFIG_AP */ 3070 3071 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, 3072 wpa_s->dbus_new_path)) 3073 return -1; 3074 3075 wpas_dbus_signal_interface_removed(wpa_s); 3076 3077 os_free(wpa_s->dbus_new_path); 3078 wpa_s->dbus_new_path = NULL; 3079 3080 return 0; 3081 } 3082 3083 #ifdef CONFIG_P2P 3084 3085 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = { 3086 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 3087 wpas_dbus_getter_p2p_peer_device_name, 3088 NULL 3089 }, 3090 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 3091 wpas_dbus_getter_p2p_peer_primary_device_type, 3092 NULL 3093 }, 3094 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q", 3095 wpas_dbus_getter_p2p_peer_config_method, 3096 NULL 3097 }, 3098 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i", 3099 wpas_dbus_getter_p2p_peer_level, 3100 NULL 3101 }, 3102 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 3103 wpas_dbus_getter_p2p_peer_device_capability, 3104 NULL 3105 }, 3106 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 3107 wpas_dbus_getter_p2p_peer_group_capability, 3108 NULL 3109 }, 3110 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 3111 wpas_dbus_getter_p2p_peer_secondary_device_types, 3112 NULL 3113 }, 3114 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 3115 wpas_dbus_getter_p2p_peer_vendor_extension, 3116 NULL 3117 }, 3118 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 3119 wpas_dbus_getter_p2p_peer_ies, 3120 NULL 3121 }, 3122 { NULL, NULL, NULL, NULL, NULL } 3123 }; 3124 3125 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = { 3126 3127 { NULL, NULL, { END_ARGS } } 3128 }; 3129 3130 /** 3131 * wpas_dbus_signal_peer - Send a peer related event signal 3132 * @wpa_s: %wpa_supplicant network interface data 3133 * @dev: peer device object 3134 * @interface: name of the interface emitting this signal. 3135 * In case of peer objects, it would be emitted by either 3136 * the "interface object" or by "peer objects" 3137 * @sig_name: signal name - DeviceFound 3138 * 3139 * Notify listeners about event related with newly found p2p peer device 3140 */ 3141 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s, 3142 const u8 *dev_addr, const char *interface, 3143 const char *sig_name) 3144 { 3145 struct wpas_dbus_priv *iface; 3146 DBusMessage *msg; 3147 DBusMessageIter iter; 3148 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 3149 3150 iface = wpa_s->global->dbus; 3151 3152 /* Do nothing if the control interface is not turned on */ 3153 if (iface == NULL) 3154 return; 3155 3156 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3157 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 3158 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 3159 3160 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface, 3161 sig_name); 3162 if (msg == NULL) 3163 return; 3164 3165 dbus_message_iter_init_append(msg, &iter); 3166 path = peer_obj_path; 3167 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 3168 &path)) 3169 goto err; 3170 3171 dbus_connection_send(iface->con, msg, NULL); 3172 3173 dbus_message_unref(msg); 3174 return; 3175 3176 err: 3177 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 3178 dbus_message_unref(msg); 3179 } 3180 3181 3182 /** 3183 * wpas_dbus_signal_peer_found - Send a peer found signal 3184 * @wpa_s: %wpa_supplicant network interface data 3185 * @dev: peer device object 3186 * 3187 * Notify listeners about find a p2p peer device found 3188 */ 3189 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s, 3190 const u8 *dev_addr) 3191 { 3192 wpas_dbus_signal_peer(wpa_s, dev_addr, 3193 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3194 "DeviceFound"); 3195 } 3196 3197 /** 3198 * wpas_dbus_signal_peer_lost - Send a peer lost signal 3199 * @wpa_s: %wpa_supplicant network interface data 3200 * @dev: peer device object 3201 * 3202 * Notify listeners about lost a p2p peer device 3203 */ 3204 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s, 3205 const u8 *dev_addr) 3206 { 3207 wpas_dbus_signal_peer(wpa_s, dev_addr, 3208 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3209 "DeviceLost"); 3210 } 3211 3212 /** 3213 * wpas_dbus_register_peer - Register a discovered peer object with dbus 3214 * @wpa_s: wpa_supplicant interface structure 3215 * @ssid: network configuration data 3216 * Returns: 0 on success, -1 on failure 3217 * 3218 * Registers network representing object with dbus 3219 */ 3220 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr) 3221 { 3222 struct wpas_dbus_priv *ctrl_iface; 3223 struct wpa_dbus_object_desc *obj_desc; 3224 struct peer_handler_args *arg; 3225 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3226 3227 /* Do nothing if the control interface is not turned on */ 3228 if (wpa_s == NULL || wpa_s->global == NULL) 3229 return 0; 3230 3231 ctrl_iface = wpa_s->global->dbus; 3232 if (ctrl_iface == NULL) 3233 return 0; 3234 3235 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3236 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 3237 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 3238 3239 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'", 3240 peer_obj_path); 3241 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3242 if (!obj_desc) { 3243 wpa_printf(MSG_ERROR, "Not enough memory " 3244 "to create object description"); 3245 goto err; 3246 } 3247 3248 /* allocate memory for handlers arguments */ 3249 arg = os_zalloc(sizeof(struct peer_handler_args)); 3250 if (!arg) { 3251 wpa_printf(MSG_ERROR, "Not enough memory " 3252 "to create arguments for method"); 3253 goto err; 3254 } 3255 3256 arg->wpa_s = wpa_s; 3257 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN); 3258 3259 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, 3260 NULL, 3261 wpas_dbus_p2p_peer_properties, 3262 wpas_dbus_p2p_peer_signals); 3263 3264 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path, 3265 wpa_s->ifname, obj_desc)) 3266 goto err; 3267 3268 return 0; 3269 3270 err: 3271 free_dbus_object_desc(obj_desc); 3272 return -1; 3273 } 3274 3275 /** 3276 * wpas_dbus_unregister_peer - Unregister a peer object with dbus 3277 * @wpa_s: wpa_supplicant interface structure 3278 * @dev_addr: p2p device addr 3279 * Returns: 0 on success, -1 on failure 3280 * 3281 * Registers network representing object with dbus 3282 */ 3283 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s, 3284 const u8 *dev_addr) 3285 { 3286 struct wpas_dbus_priv *ctrl_iface; 3287 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3288 int ret; 3289 3290 /* Do nothing if the control interface is not turned on */ 3291 if (wpa_s == NULL || wpa_s->global == NULL || 3292 wpa_s->dbus_new_path == NULL) 3293 return 0; 3294 ctrl_iface = wpa_s->global->dbus; 3295 if (ctrl_iface == NULL) 3296 return 0; 3297 3298 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3299 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 3300 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 3301 3302 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'", 3303 peer_obj_path); 3304 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path); 3305 3306 return ret; 3307 } 3308 3309 3310 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = { 3311 { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao", 3312 wpas_dbus_getter_p2p_group_members, 3313 NULL 3314 }, 3315 { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o", 3316 wpas_dbus_getter_p2p_group, 3317 NULL 3318 }, 3319 { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", 3320 wpas_dbus_getter_p2p_role, 3321 NULL 3322 }, 3323 { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 3324 wpas_dbus_getter_p2p_group_ssid, 3325 NULL 3326 }, 3327 { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 3328 wpas_dbus_getter_p2p_group_bssid, 3329 NULL 3330 }, 3331 { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q", 3332 wpas_dbus_getter_p2p_group_frequency, 3333 NULL 3334 }, 3335 { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", 3336 wpas_dbus_getter_p2p_group_passphrase, 3337 NULL 3338 }, 3339 { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 3340 wpas_dbus_getter_p2p_group_psk, 3341 NULL 3342 }, 3343 { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay", 3344 wpas_dbus_getter_p2p_group_vendor_ext, 3345 wpas_dbus_setter_p2p_group_vendor_ext 3346 }, 3347 { NULL, NULL, NULL, NULL, NULL } 3348 }; 3349 3350 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = { 3351 { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP, 3352 { 3353 { "peer", "o", ARG_OUT }, 3354 END_ARGS 3355 } 3356 }, 3357 { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP, 3358 { 3359 { "peer", "o", ARG_OUT }, 3360 END_ARGS 3361 } 3362 }, 3363 { NULL, NULL, { END_ARGS } } 3364 }; 3365 3366 /** 3367 * wpas_dbus_register_p2p_group - Register a p2p group object with dbus 3368 * @wpa_s: wpa_supplicant interface structure 3369 * @ssid: SSID struct 3370 * Returns: 0 on success, -1 on failure 3371 * 3372 * Registers p2p group representing object with dbus 3373 */ 3374 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s, 3375 struct wpa_ssid *ssid) 3376 { 3377 struct wpas_dbus_priv *ctrl_iface; 3378 struct wpa_dbus_object_desc *obj_desc; 3379 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3380 3381 /* Do nothing if the control interface is not turned on */ 3382 if (wpa_s == NULL || wpa_s->global == NULL) 3383 return; 3384 3385 ctrl_iface = wpa_s->global->dbus; 3386 if (ctrl_iface == NULL) 3387 return; 3388 3389 if (wpa_s->dbus_groupobj_path) { 3390 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists", 3391 __func__, wpa_s->dbus_groupobj_path); 3392 return; 3393 } 3394 3395 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0) 3396 return; 3397 3398 wpa_s->dbus_groupobj_path = os_strdup(group_obj_path); 3399 if (wpa_s->dbus_groupobj_path == NULL) 3400 return; 3401 3402 wpa_printf(MSG_INFO, "dbus: Register group object '%s'", 3403 group_obj_path); 3404 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3405 if (!obj_desc) { 3406 wpa_printf(MSG_ERROR, "Not enough memory " 3407 "to create object description"); 3408 goto err; 3409 } 3410 3411 wpas_dbus_register(obj_desc, wpa_s, NULL, NULL, 3412 wpas_dbus_p2p_group_properties, 3413 wpas_dbus_p2p_group_signals); 3414 3415 if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path, 3416 wpa_s->ifname, obj_desc)) 3417 goto err; 3418 3419 return; 3420 3421 err: 3422 if (wpa_s->dbus_groupobj_path) { 3423 os_free(wpa_s->dbus_groupobj_path); 3424 wpa_s->dbus_groupobj_path = NULL; 3425 } 3426 3427 free_dbus_object_desc(obj_desc); 3428 } 3429 3430 /** 3431 * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus 3432 * @wpa_s: wpa_supplicant interface structure 3433 * @ssid: network name of the p2p group started 3434 */ 3435 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s, 3436 const struct wpa_ssid *ssid) 3437 { 3438 struct wpas_dbus_priv *ctrl_iface; 3439 3440 /* Do nothing if the control interface is not turned on */ 3441 if (wpa_s == NULL || wpa_s->global == NULL) 3442 return; 3443 3444 ctrl_iface = wpa_s->global->dbus; 3445 if (ctrl_iface == NULL) 3446 return; 3447 3448 if (!wpa_s->dbus_groupobj_path) { 3449 wpa_printf(MSG_DEBUG, 3450 "%s: Group object '%s' already unregistered", 3451 __func__, wpa_s->dbus_groupobj_path); 3452 return; 3453 } 3454 3455 wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'", 3456 wpa_s->dbus_groupobj_path); 3457 3458 wpa_dbus_unregister_object_per_iface(ctrl_iface, 3459 wpa_s->dbus_groupobj_path); 3460 3461 os_free(wpa_s->dbus_groupobj_path); 3462 wpa_s->dbus_groupobj_path = NULL; 3463 } 3464 3465 static const struct wpa_dbus_property_desc 3466 wpas_dbus_p2p_groupmember_properties[] = { 3467 { NULL, NULL, NULL, NULL, NULL } 3468 }; 3469 3470 /** 3471 * wpas_dbus_register_p2p_groupmember - Register a p2p groupmember 3472 * object with dbus 3473 * @wpa_s: wpa_supplicant interface structure 3474 * @p2p_if_addr: i/f addr of the device joining this group 3475 * 3476 * Registers p2p groupmember representing object with dbus 3477 */ 3478 void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s, 3479 const u8 *p2p_if_addr) 3480 { 3481 struct wpas_dbus_priv *ctrl_iface; 3482 struct wpa_dbus_object_desc *obj_desc = NULL; 3483 struct groupmember_handler_args *arg; 3484 char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3485 3486 /* Do nothing if the control interface is not turned on */ 3487 if (wpa_s == NULL || wpa_s->global == NULL) 3488 return; 3489 3490 ctrl_iface = wpa_s->global->dbus; 3491 if (ctrl_iface == NULL) 3492 return; 3493 3494 if (!wpa_s->dbus_groupobj_path) 3495 return; 3496 3497 os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3498 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR, 3499 wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr)); 3500 3501 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3502 if (!obj_desc) { 3503 wpa_printf(MSG_ERROR, "Not enough memory " 3504 "to create object description"); 3505 goto err; 3506 } 3507 3508 /* allocate memory for handlers arguments */ 3509 arg = os_zalloc(sizeof(struct groupmember_handler_args)); 3510 if (!arg) { 3511 wpa_printf(MSG_ERROR, "Not enough memory " 3512 "to create arguments for method"); 3513 goto err; 3514 } 3515 3516 arg->wpa_s = wpa_s; 3517 os_memcpy(arg->member_addr, p2p_if_addr, ETH_ALEN); 3518 3519 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 3520 wpas_dbus_p2p_groupmember_properties, NULL); 3521 3522 if (wpa_dbus_register_object_per_iface(ctrl_iface, groupmember_obj_path, 3523 wpa_s->ifname, obj_desc)) 3524 goto err; 3525 3526 wpa_printf(MSG_INFO, 3527 "dbus: Registered group member object '%s' successfully", 3528 groupmember_obj_path); 3529 return; 3530 3531 err: 3532 free_dbus_object_desc(obj_desc); 3533 } 3534 3535 /** 3536 * wpas_dbus_unregister_p2p_groupmember - Unregister a p2p groupmember 3537 * object with dbus 3538 * @wpa_s: wpa_supplicant interface structure 3539 * @p2p_if_addr: i/f addr of the device joining this group 3540 * 3541 * Unregisters p2p groupmember representing object with dbus 3542 */ 3543 void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s, 3544 const u8 *p2p_if_addr) 3545 { 3546 struct wpas_dbus_priv *ctrl_iface; 3547 char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3548 3549 /* Do nothing if the control interface is not turned on */ 3550 if (wpa_s == NULL || wpa_s->global == NULL) 3551 return; 3552 3553 ctrl_iface = wpa_s->global->dbus; 3554 if (ctrl_iface == NULL) 3555 return; 3556 3557 if (!wpa_s->dbus_groupobj_path) 3558 return; 3559 3560 os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3561 "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR, 3562 wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr)); 3563 3564 wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path); 3565 } 3566 3567 3568 static const struct wpa_dbus_property_desc 3569 wpas_dbus_persistent_group_properties[] = { 3570 { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}", 3571 wpas_dbus_getter_persistent_group_properties, 3572 wpas_dbus_setter_persistent_group_properties 3573 }, 3574 { NULL, NULL, NULL, NULL, NULL } 3575 }; 3576 3577 /* No signals intended for persistent group objects */ 3578 3579 /** 3580 * wpas_dbus_register_persistent_group - Register a configured(saved) 3581 * persistent group with dbus 3582 * @wpa_s: wpa_supplicant interface structure 3583 * @ssid: persistent group (still represented as a network within wpa) 3584 * configuration data 3585 * Returns: 0 on success, -1 on failure 3586 * 3587 * Registers a persistent group representing object with dbus. 3588 */ 3589 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s, 3590 struct wpa_ssid *ssid) 3591 { 3592 struct wpas_dbus_priv *ctrl_iface; 3593 struct wpa_dbus_object_desc *obj_desc; 3594 struct network_handler_args *arg; 3595 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3596 3597 /* Do nothing if the control interface is not turned on */ 3598 if (wpa_s == NULL || wpa_s->global == NULL) 3599 return 0; 3600 3601 /* Make sure ssid is a persistent group */ 3602 if (ssid->disabled != 2 && !ssid->p2p_persistent_group) 3603 return -1; /* should we return w/o complaining? */ 3604 3605 ctrl_iface = wpa_s->global->dbus; 3606 if (ctrl_iface == NULL) 3607 return 0; 3608 3609 /* 3610 * Intentionally not coming up with different numbering scheme 3611 * for persistent groups. 3612 */ 3613 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3614 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 3615 wpa_s->dbus_new_path, ssid->id); 3616 3617 wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'", 3618 pgrp_obj_path); 3619 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3620 if (!obj_desc) { 3621 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create " 3622 "object description"); 3623 goto err; 3624 } 3625 3626 /* 3627 * Reusing the same context structure as that for networks 3628 * since these are represented using same data structure. 3629 */ 3630 /* allocate memory for handlers arguments */ 3631 arg = os_zalloc(sizeof(struct network_handler_args)); 3632 if (!arg) { 3633 wpa_printf(MSG_ERROR, "dbus: Not enough memory to create " 3634 "arguments for method"); 3635 goto err; 3636 } 3637 3638 arg->wpa_s = wpa_s; 3639 arg->ssid = ssid; 3640 3641 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 3642 wpas_dbus_persistent_group_properties, 3643 NULL); 3644 3645 if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path, 3646 wpa_s->ifname, obj_desc)) 3647 goto err; 3648 3649 wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id); 3650 3651 return 0; 3652 3653 err: 3654 free_dbus_object_desc(obj_desc); 3655 return -1; 3656 } 3657 3658 3659 /** 3660 * wpas_dbus_unregister_persistent_group - Unregister a persistent_group 3661 * from dbus 3662 * @wpa_s: wpa_supplicant interface structure 3663 * @nid: network id 3664 * Returns: 0 on success, -1 on failure 3665 * 3666 * Unregisters persistent group representing object from dbus 3667 * 3668 * NOTE: There is a slight issue with the semantics here. While the 3669 * implementation simply means the persistent group is unloaded from memory, 3670 * it should not get interpreted as the group is actually being erased/removed 3671 * from persistent storage as well. 3672 */ 3673 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s, 3674 int nid) 3675 { 3676 struct wpas_dbus_priv *ctrl_iface; 3677 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3678 int ret; 3679 3680 /* Do nothing if the control interface is not turned on */ 3681 if (wpa_s == NULL || wpa_s->global == NULL || 3682 wpa_s->dbus_new_path == NULL) 3683 return 0; 3684 ctrl_iface = wpa_s->global->dbus; 3685 if (ctrl_iface == NULL) 3686 return 0; 3687 3688 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3689 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 3690 wpa_s->dbus_new_path, nid); 3691 3692 wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'", 3693 pgrp_obj_path); 3694 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path); 3695 3696 if (!ret) 3697 wpas_dbus_signal_persistent_group_removed(wpa_s, nid); 3698 3699 return ret; 3700 } 3701 3702 #endif /* CONFIG_P2P */ 3703