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