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