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 "ap/sta_info.h" 17 #include "../config.h" 18 #include "../wpa_supplicant_i.h" 19 #include "../bss.h" 20 #include "../wpas_glue.h" 21 #include "dbus_new_helpers.h" 22 #include "dbus_dict_helpers.h" 23 #include "dbus_new.h" 24 #include "dbus_new_handlers.h" 25 #include "dbus_common_i.h" 26 #include "dbus_new_handlers_p2p.h" 27 #include "p2p/p2p.h" 28 #include "../p2p_supplicant.h" 29 30 #ifdef CONFIG_AP /* until needed by something else */ 31 32 /* 33 * NameOwnerChanged handling 34 * 35 * Some services we provide allow an application to register for 36 * a signal that it needs. While it can also unregister, we must 37 * be prepared for the case where the application simply crashes 38 * and thus doesn't clean up properly. The way to handle this in 39 * DBus is to register for the NameOwnerChanged signal which will 40 * signal an owner change to NULL if the peer closes the socket 41 * for whatever reason. 42 * 43 * Handle this signal via a filter function whenever necessary. 44 * The code below also handles refcounting in case in the future 45 * there will be multiple instances of this subscription scheme. 46 */ 47 static const char wpas_dbus_noc_filter_str[] = 48 "interface=org.freedesktop.DBus,member=NameOwnerChanged"; 49 50 51 static DBusHandlerResult noc_filter(DBusConnection *conn, 52 DBusMessage *message, void *data) 53 { 54 struct wpas_dbus_priv *priv = data; 55 56 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) 57 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 58 59 if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, 60 "NameOwnerChanged")) { 61 const char *name; 62 const char *prev_owner; 63 const char *new_owner; 64 DBusError derr; 65 struct wpa_supplicant *wpa_s; 66 67 dbus_error_init(&derr); 68 69 if (!dbus_message_get_args(message, &derr, 70 DBUS_TYPE_STRING, &name, 71 DBUS_TYPE_STRING, &prev_owner, 72 DBUS_TYPE_STRING, &new_owner, 73 DBUS_TYPE_INVALID)) { 74 /* Ignore this error */ 75 dbus_error_free(&derr); 76 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 77 } 78 79 for (wpa_s = priv->global->ifaces; wpa_s; wpa_s = wpa_s->next) { 80 if (wpa_s->preq_notify_peer != NULL && 81 os_strcmp(name, wpa_s->preq_notify_peer) == 0 && 82 (new_owner == NULL || os_strlen(new_owner) == 0)) { 83 /* probe request owner disconnected */ 84 os_free(wpa_s->preq_notify_peer); 85 wpa_s->preq_notify_peer = NULL; 86 wpas_dbus_unsubscribe_noc(priv); 87 } 88 } 89 } 90 91 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 92 } 93 94 95 void wpas_dbus_subscribe_noc(struct wpas_dbus_priv *priv) 96 { 97 priv->dbus_noc_refcnt++; 98 if (priv->dbus_noc_refcnt > 1) 99 return; 100 101 if (!dbus_connection_add_filter(priv->con, noc_filter, priv, NULL)) { 102 wpa_printf(MSG_ERROR, "dbus: failed to add filter"); 103 return; 104 } 105 106 dbus_bus_add_match(priv->con, wpas_dbus_noc_filter_str, NULL); 107 } 108 109 110 void wpas_dbus_unsubscribe_noc(struct wpas_dbus_priv *priv) 111 { 112 priv->dbus_noc_refcnt--; 113 if (priv->dbus_noc_refcnt > 0) 114 return; 115 116 dbus_bus_remove_match(priv->con, wpas_dbus_noc_filter_str, NULL); 117 dbus_connection_remove_filter(priv->con, noc_filter, priv); 118 } 119 120 #endif /* CONFIG_AP */ 121 122 123 /** 124 * wpas_dbus_signal_interface - Send a interface related event signal 125 * @wpa_s: %wpa_supplicant network interface data 126 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved 127 * @properties: Whether to add second argument with object properties 128 * 129 * Notify listeners about event related with interface 130 */ 131 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s, 132 const char *sig_name, 133 dbus_bool_t properties) 134 { 135 struct wpas_dbus_priv *iface; 136 DBusMessage *msg; 137 DBusMessageIter iter; 138 139 iface = wpa_s->global->dbus; 140 141 /* Do nothing if the control interface is not turned on */ 142 if (iface == NULL || !wpa_s->dbus_new_path) 143 return; 144 145 msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH, 146 WPAS_DBUS_NEW_INTERFACE, sig_name); 147 if (msg == NULL) 148 return; 149 150 dbus_message_iter_init_append(msg, &iter); 151 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 152 &wpa_s->dbus_new_path) || 153 (properties && 154 !wpa_dbus_get_object_properties( 155 iface, wpa_s->dbus_new_path, 156 WPAS_DBUS_NEW_IFACE_INTERFACE, &iter))) 157 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 158 else 159 dbus_connection_send(iface->con, msg, NULL); 160 dbus_message_unref(msg); 161 } 162 163 164 /** 165 * wpas_dbus_signal_interface_added - Send a interface created signal 166 * @wpa_s: %wpa_supplicant network interface data 167 * 168 * Notify listeners about creating new interface 169 */ 170 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s) 171 { 172 wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE); 173 } 174 175 176 /** 177 * wpas_dbus_signal_interface_removed - Send a interface removed signal 178 * @wpa_s: %wpa_supplicant network interface data 179 * 180 * Notify listeners about removing interface 181 */ 182 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s) 183 { 184 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE); 185 186 } 187 188 189 /** 190 * wpas_dbus_signal_scan_done - send scan done signal 191 * @wpa_s: %wpa_supplicant network interface data 192 * @success: indicates if scanning succeed or failed 193 * 194 * Notify listeners about finishing a scan 195 */ 196 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success) 197 { 198 struct wpas_dbus_priv *iface; 199 DBusMessage *msg; 200 dbus_bool_t succ; 201 202 iface = wpa_s->global->dbus; 203 204 /* Do nothing if the control interface is not turned on */ 205 if (iface == NULL || !wpa_s->dbus_new_path) 206 return; 207 208 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 209 WPAS_DBUS_NEW_IFACE_INTERFACE, 210 "ScanDone"); 211 if (msg == NULL) 212 return; 213 214 succ = success ? TRUE : FALSE; 215 if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ, 216 DBUS_TYPE_INVALID)) 217 dbus_connection_send(iface->con, msg, NULL); 218 else 219 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 220 dbus_message_unref(msg); 221 } 222 223 224 /** 225 * wpas_dbus_signal_bss - Send a BSS related event signal 226 * @wpa_s: %wpa_supplicant network interface data 227 * @bss_obj_path: BSS object path 228 * @sig_name: signal name - BSSAdded or BSSRemoved 229 * @properties: Whether to add second argument with object properties 230 * 231 * Notify listeners about event related with BSS 232 */ 233 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s, 234 const char *bss_obj_path, 235 const char *sig_name, dbus_bool_t properties) 236 { 237 struct wpas_dbus_priv *iface; 238 DBusMessage *msg; 239 DBusMessageIter iter; 240 241 iface = wpa_s->global->dbus; 242 243 /* Do nothing if the control interface is not turned on */ 244 if (iface == NULL || !wpa_s->dbus_new_path) 245 return; 246 247 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 248 WPAS_DBUS_NEW_IFACE_INTERFACE, 249 sig_name); 250 if (msg == NULL) 251 return; 252 253 dbus_message_iter_init_append(msg, &iter); 254 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 255 &bss_obj_path) || 256 (properties && 257 !wpa_dbus_get_object_properties(iface, bss_obj_path, 258 WPAS_DBUS_NEW_IFACE_BSS, 259 &iter))) 260 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 261 else 262 dbus_connection_send(iface->con, msg, NULL); 263 dbus_message_unref(msg); 264 } 265 266 267 /** 268 * wpas_dbus_signal_bss_added - Send a BSS added signal 269 * @wpa_s: %wpa_supplicant network interface data 270 * @bss_obj_path: new BSS object path 271 * 272 * Notify listeners about adding new BSS 273 */ 274 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s, 275 const char *bss_obj_path) 276 { 277 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE); 278 } 279 280 281 /** 282 * wpas_dbus_signal_bss_removed - Send a BSS removed signal 283 * @wpa_s: %wpa_supplicant network interface data 284 * @bss_obj_path: BSS object path 285 * 286 * Notify listeners about removing BSS 287 */ 288 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s, 289 const char *bss_obj_path) 290 { 291 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE); 292 } 293 294 295 /** 296 * wpas_dbus_signal_blob - Send a blob related event signal 297 * @wpa_s: %wpa_supplicant network interface data 298 * @name: blob name 299 * @sig_name: signal name - BlobAdded or BlobRemoved 300 * 301 * Notify listeners about event related with blob 302 */ 303 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s, 304 const char *name, const char *sig_name) 305 { 306 struct wpas_dbus_priv *iface; 307 DBusMessage *msg; 308 309 iface = wpa_s->global->dbus; 310 311 /* Do nothing if the control interface is not turned on */ 312 if (iface == NULL || !wpa_s->dbus_new_path) 313 return; 314 315 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 316 WPAS_DBUS_NEW_IFACE_INTERFACE, 317 sig_name); 318 if (msg == NULL) 319 return; 320 321 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, 322 DBUS_TYPE_INVALID)) 323 dbus_connection_send(iface->con, msg, NULL); 324 else 325 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 326 dbus_message_unref(msg); 327 } 328 329 330 /** 331 * wpas_dbus_signal_blob_added - Send a blob added signal 332 * @wpa_s: %wpa_supplicant network interface data 333 * @name: blob name 334 * 335 * Notify listeners about adding a new blob 336 */ 337 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s, 338 const char *name) 339 { 340 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded"); 341 } 342 343 344 /** 345 * wpas_dbus_signal_blob_removed - Send a blob removed signal 346 * @wpa_s: %wpa_supplicant network interface data 347 * @name: blob name 348 * 349 * Notify listeners about removing blob 350 */ 351 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s, 352 const char *name) 353 { 354 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved"); 355 } 356 357 358 /** 359 * wpas_dbus_signal_network - Send a network related event signal 360 * @wpa_s: %wpa_supplicant network interface data 361 * @id: new network id 362 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected 363 * @properties: determines if add second argument with object properties 364 * 365 * Notify listeners about event related with configured network 366 */ 367 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s, 368 int id, const char *sig_name, 369 dbus_bool_t properties) 370 { 371 struct wpas_dbus_priv *iface; 372 DBusMessage *msg; 373 DBusMessageIter iter; 374 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 375 376 iface = wpa_s->global->dbus; 377 378 /* Do nothing if the control interface is not turned on */ 379 if (iface == NULL || !wpa_s->dbus_new_path) 380 return; 381 382 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 383 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 384 wpa_s->dbus_new_path, id); 385 386 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 387 WPAS_DBUS_NEW_IFACE_INTERFACE, 388 sig_name); 389 if (msg == NULL) 390 return; 391 392 dbus_message_iter_init_append(msg, &iter); 393 path = net_obj_path; 394 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 395 &path) || 396 (properties && 397 !wpa_dbus_get_object_properties( 398 iface, net_obj_path, WPAS_DBUS_NEW_IFACE_NETWORK, 399 &iter))) 400 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 401 else 402 dbus_connection_send(iface->con, msg, NULL); 403 dbus_message_unref(msg); 404 } 405 406 407 /** 408 * wpas_dbus_signal_network_added - Send a network added signal 409 * @wpa_s: %wpa_supplicant network interface data 410 * @id: new network id 411 * 412 * Notify listeners about adding new network 413 */ 414 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s, 415 int id) 416 { 417 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE); 418 } 419 420 421 /** 422 * wpas_dbus_signal_network_removed - Send a network removed signal 423 * @wpa_s: %wpa_supplicant network interface data 424 * @id: network id 425 * 426 * Notify listeners about removing a network 427 */ 428 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s, 429 int id) 430 { 431 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE); 432 } 433 434 435 /** 436 * wpas_dbus_signal_network_selected - Send a network selected signal 437 * @wpa_s: %wpa_supplicant network interface data 438 * @id: network id 439 * 440 * Notify listeners about selecting a network 441 */ 442 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id) 443 { 444 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE); 445 } 446 447 448 /** 449 * wpas_dbus_signal_network_request - Indicate that additional information 450 * (EAP password, etc.) is required to complete the association to this SSID 451 * @wpa_s: %wpa_supplicant network interface data 452 * @rtype: The specific additional information required 453 * @default_text: Optional description of required information 454 * 455 * Request additional information or passwords to complete an association 456 * request. 457 */ 458 void wpas_dbus_signal_network_request(struct wpa_supplicant *wpa_s, 459 struct wpa_ssid *ssid, 460 enum wpa_ctrl_req_type rtype, 461 const char *default_txt) 462 { 463 struct wpas_dbus_priv *iface; 464 DBusMessage *msg; 465 DBusMessageIter iter; 466 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 467 const char *field, *txt = NULL, *net_ptr; 468 469 iface = wpa_s->global->dbus; 470 471 /* Do nothing if the control interface is not turned on */ 472 if (iface == NULL || !wpa_s->dbus_new_path) 473 return; 474 475 field = wpa_supplicant_ctrl_req_to_string(rtype, default_txt, &txt); 476 if (field == NULL) 477 return; 478 479 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 480 WPAS_DBUS_NEW_IFACE_INTERFACE, 481 "NetworkRequest"); 482 if (msg == NULL) 483 return; 484 485 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 486 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 487 wpa_s->dbus_new_path, ssid->id); 488 net_ptr = &net_obj_path[0]; 489 490 dbus_message_iter_init_append(msg, &iter); 491 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 492 &net_ptr) || 493 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &field) || 494 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &txt)) 495 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 496 else 497 dbus_connection_send(iface->con, msg, NULL); 498 dbus_message_unref(msg); 499 } 500 501 502 /** 503 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes 504 * @wpa_s: %wpa_supplicant network interface data 505 * @ssid: configured network which Enabled property has changed 506 * 507 * Sends PropertyChanged signals containing new value of Enabled property 508 * for specified network 509 */ 510 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s, 511 struct wpa_ssid *ssid) 512 { 513 514 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 515 516 if (!wpa_s->dbus_new_path) 517 return; 518 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 519 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 520 wpa_s->dbus_new_path, ssid->id); 521 522 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 523 WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled"); 524 } 525 526 527 #ifdef CONFIG_WPS 528 529 /** 530 * wpas_dbus_signal_wps_event_pbc_overlap - Signals PBC overlap WPS event 531 * @wpa_s: %wpa_supplicant network interface data 532 * 533 * Sends Event dbus signal with name "pbc-overlap" and empty dict as arguments 534 */ 535 void wpas_dbus_signal_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s) 536 { 537 538 DBusMessage *msg; 539 DBusMessageIter iter, dict_iter; 540 struct wpas_dbus_priv *iface; 541 char *key = "pbc-overlap"; 542 543 iface = wpa_s->global->dbus; 544 545 /* Do nothing if the control interface is not turned on */ 546 if (iface == NULL || !wpa_s->dbus_new_path) 547 return; 548 549 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 550 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 551 if (msg == NULL) 552 return; 553 554 dbus_message_iter_init_append(msg, &iter); 555 556 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 557 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 558 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 559 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 560 else 561 dbus_connection_send(iface->con, msg, NULL); 562 563 dbus_message_unref(msg); 564 } 565 566 567 /** 568 * wpas_dbus_signal_wps_event_success - Signals Success WPS event 569 * @wpa_s: %wpa_supplicant network interface data 570 * 571 * Sends Event dbus signal with name "success" and empty dict as arguments 572 */ 573 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s) 574 { 575 576 DBusMessage *msg; 577 DBusMessageIter iter, dict_iter; 578 struct wpas_dbus_priv *iface; 579 char *key = "success"; 580 581 iface = wpa_s->global->dbus; 582 583 /* Do nothing if the control interface is not turned on */ 584 if (iface == NULL || !wpa_s->dbus_new_path) 585 return; 586 587 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 588 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 589 if (msg == NULL) 590 return; 591 592 dbus_message_iter_init_append(msg, &iter); 593 594 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 595 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 596 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 597 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 598 else 599 dbus_connection_send(iface->con, msg, NULL); 600 601 dbus_message_unref(msg); 602 } 603 604 605 /** 606 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event 607 * @wpa_s: %wpa_supplicant network interface data 608 * @fail: WPS failure information 609 * 610 * Sends Event dbus signal with name "fail" and dictionary containing 611 * "msg field with fail message number (int32) as arguments 612 */ 613 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s, 614 struct wps_event_fail *fail) 615 { 616 617 DBusMessage *msg; 618 DBusMessageIter iter, dict_iter; 619 struct wpas_dbus_priv *iface; 620 char *key = "fail"; 621 622 iface = wpa_s->global->dbus; 623 624 /* Do nothing if the control interface is not turned on */ 625 if (iface == NULL || !wpa_s->dbus_new_path) 626 return; 627 628 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 629 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 630 if (msg == NULL) 631 return; 632 633 dbus_message_iter_init_append(msg, &iter); 634 635 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 636 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 637 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) || 638 !wpa_dbus_dict_append_int32(&dict_iter, "config_error", 639 fail->config_error) || 640 !wpa_dbus_dict_append_int32(&dict_iter, "error_indication", 641 fail->error_indication) || 642 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 643 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 644 else 645 dbus_connection_send(iface->con, msg, NULL); 646 647 dbus_message_unref(msg); 648 } 649 650 651 /** 652 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event 653 * @wpa_s: %wpa_supplicant network interface data 654 * @m2d: M2D event data information 655 * 656 * Sends Event dbus signal with name "m2d" and dictionary containing 657 * fields of wps_event_m2d structure. 658 */ 659 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s, 660 struct wps_event_m2d *m2d) 661 { 662 663 DBusMessage *msg; 664 DBusMessageIter iter, dict_iter; 665 struct wpas_dbus_priv *iface; 666 char *key = "m2d"; 667 668 iface = wpa_s->global->dbus; 669 670 /* Do nothing if the control interface is not turned on */ 671 if (iface == NULL || !wpa_s->dbus_new_path) 672 return; 673 674 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 675 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 676 if (msg == NULL) 677 return; 678 679 dbus_message_iter_init_append(msg, &iter); 680 681 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 682 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 683 !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods", 684 m2d->config_methods) || 685 !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer", 686 (const char *) m2d->manufacturer, 687 m2d->manufacturer_len) || 688 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name", 689 (const char *) m2d->model_name, 690 m2d->model_name_len) || 691 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number", 692 (const char *) m2d->model_number, 693 m2d->model_number_len) || 694 !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number", 695 (const char *) 696 m2d->serial_number, 697 m2d->serial_number_len) || 698 !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name", 699 (const char *) m2d->dev_name, 700 m2d->dev_name_len) || 701 !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type", 702 (const char *) 703 m2d->primary_dev_type, 8) || 704 !wpa_dbus_dict_append_uint16(&dict_iter, "config_error", 705 m2d->config_error) || 706 !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id", 707 m2d->dev_password_id) || 708 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 709 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 710 else 711 dbus_connection_send(iface->con, msg, NULL); 712 713 dbus_message_unref(msg); 714 } 715 716 717 /** 718 * wpas_dbus_signal_wps_cred - Signals new credentials 719 * @wpa_s: %wpa_supplicant network interface data 720 * @cred: WPS Credential information 721 * 722 * Sends signal with credentials in directory argument 723 */ 724 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s, 725 const struct wps_credential *cred) 726 { 727 DBusMessage *msg; 728 DBusMessageIter iter, dict_iter; 729 struct wpas_dbus_priv *iface; 730 char *auth_type[5]; /* we have five possible authentication types */ 731 int at_num = 0; 732 char *encr_type[3]; /* we have three possible encryption types */ 733 int et_num = 0; 734 735 iface = wpa_s->global->dbus; 736 737 /* Do nothing if the control interface is not turned on */ 738 if (iface == NULL || !wpa_s->dbus_new_path) 739 return; 740 741 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 742 WPAS_DBUS_NEW_IFACE_WPS, 743 "Credentials"); 744 if (msg == NULL) 745 return; 746 747 dbus_message_iter_init_append(msg, &iter); 748 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) 749 goto nomem; 750 751 if (cred->auth_type & WPS_AUTH_OPEN) 752 auth_type[at_num++] = "open"; 753 if (cred->auth_type & WPS_AUTH_WPAPSK) 754 auth_type[at_num++] = "wpa-psk"; 755 if (cred->auth_type & WPS_AUTH_WPA) 756 auth_type[at_num++] = "wpa-eap"; 757 if (cred->auth_type & WPS_AUTH_WPA2) 758 auth_type[at_num++] = "wpa2-eap"; 759 if (cred->auth_type & WPS_AUTH_WPA2PSK) 760 auth_type[at_num++] = "wpa2-psk"; 761 762 if (cred->encr_type & WPS_ENCR_NONE) 763 encr_type[et_num++] = "none"; 764 if (cred->encr_type & WPS_ENCR_TKIP) 765 encr_type[et_num++] = "tkip"; 766 if (cred->encr_type & WPS_ENCR_AES) 767 encr_type[et_num++] = "aes"; 768 769 if ((wpa_s->current_ssid && 770 !wpa_dbus_dict_append_byte_array( 771 &dict_iter, "BSSID", 772 (const char *) wpa_s->current_ssid->bssid, ETH_ALEN)) || 773 !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID", 774 (const char *) cred->ssid, 775 cred->ssid_len) || 776 !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType", 777 (const char **) auth_type, 778 at_num) || 779 !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType", 780 (const char **) encr_type, 781 et_num) || 782 !wpa_dbus_dict_append_byte_array(&dict_iter, "Key", 783 (const char *) cred->key, 784 cred->key_len) || 785 !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex", 786 cred->key_idx) || 787 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 788 goto nomem; 789 790 dbus_connection_send(iface->con, msg, NULL); 791 792 nomem: 793 dbus_message_unref(msg); 794 } 795 796 #endif /* CONFIG_WPS */ 797 798 799 #ifdef CONFIG_MESH 800 801 void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s, 802 struct wpa_ssid *ssid) 803 { 804 struct wpas_dbus_priv *iface; 805 DBusMessage *msg; 806 DBusMessageIter iter, dict_iter; 807 808 iface = wpa_s->global->dbus; 809 810 /* Do nothing if the control interface is not turned on */ 811 if (!iface || !wpa_s->dbus_new_path) 812 return; 813 814 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 815 WPAS_DBUS_NEW_IFACE_MESH, 816 "MeshGroupStarted"); 817 if (!msg) 818 return; 819 820 dbus_message_iter_init_append(msg, &iter); 821 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 822 !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID", 823 (const char *) ssid->ssid, 824 ssid->ssid_len) || 825 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 826 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 827 else 828 dbus_connection_send(iface->con, msg, NULL); 829 dbus_message_unref(msg); 830 } 831 832 833 void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s, 834 const u8 *meshid, u8 meshid_len, 835 int reason) 836 { 837 struct wpas_dbus_priv *iface; 838 DBusMessage *msg; 839 DBusMessageIter iter, dict_iter; 840 841 iface = wpa_s->global->dbus; 842 843 /* Do nothing if the control interface is not turned on */ 844 if (!iface || !wpa_s->dbus_new_path) 845 return; 846 847 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 848 WPAS_DBUS_NEW_IFACE_MESH, 849 "MeshGroupRemoved"); 850 if (!msg) 851 return; 852 853 dbus_message_iter_init_append(msg, &iter); 854 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 855 !wpa_dbus_dict_append_byte_array(&dict_iter, "SSID", 856 (const char *) meshid, 857 meshid_len) || 858 !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason", 859 reason) || 860 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 861 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 862 else 863 dbus_connection_send(iface->con, msg, NULL); 864 dbus_message_unref(msg); 865 } 866 867 868 void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s, 869 const u8 *peer_addr) 870 { 871 struct wpas_dbus_priv *iface; 872 DBusMessage *msg; 873 DBusMessageIter iter, dict_iter; 874 875 iface = wpa_s->global->dbus; 876 877 /* Do nothing if the control interface is not turned on */ 878 if (!iface || !wpa_s->dbus_new_path) 879 return; 880 881 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 882 WPAS_DBUS_NEW_IFACE_MESH, 883 "MeshPeerConnected"); 884 if (!msg) 885 return; 886 887 dbus_message_iter_init_append(msg, &iter); 888 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 889 !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress", 890 (const char *) peer_addr, 891 ETH_ALEN) || 892 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 893 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 894 else 895 dbus_connection_send(iface->con, msg, NULL); 896 dbus_message_unref(msg); 897 } 898 899 900 void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, 901 const u8 *peer_addr, int reason) 902 { 903 struct wpas_dbus_priv *iface; 904 DBusMessage *msg; 905 DBusMessageIter iter, dict_iter; 906 907 iface = wpa_s->global->dbus; 908 909 /* Do nothing if the control interface is not turned on */ 910 if (!iface || !wpa_s->dbus_new_path) 911 return; 912 913 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 914 WPAS_DBUS_NEW_IFACE_MESH, 915 "MeshPeerDisconnected"); 916 if (!msg) 917 return; 918 919 dbus_message_iter_init_append(msg, &iter); 920 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 921 !wpa_dbus_dict_append_byte_array(&dict_iter, "PeerAddress", 922 (const char *) peer_addr, 923 ETH_ALEN) || 924 !wpa_dbus_dict_append_int32(&dict_iter, "DisconnectReason", 925 reason) || 926 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 927 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 928 else 929 dbus_connection_send(iface->con, msg, NULL); 930 dbus_message_unref(msg); 931 } 932 933 #endif /* CONFIG_MESH */ 934 935 936 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s, 937 int depth, const char *subject, 938 const char *altsubject[], 939 int num_altsubject, 940 const char *cert_hash, 941 const struct wpabuf *cert) 942 { 943 struct wpas_dbus_priv *iface; 944 DBusMessage *msg; 945 DBusMessageIter iter, dict_iter; 946 947 iface = wpa_s->global->dbus; 948 949 /* Do nothing if the control interface is not turned on */ 950 if (iface == NULL || !wpa_s->dbus_new_path) 951 return; 952 953 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 954 WPAS_DBUS_NEW_IFACE_INTERFACE, 955 "Certification"); 956 if (msg == NULL) 957 return; 958 959 dbus_message_iter_init_append(msg, &iter); 960 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 961 !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) || 962 !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) || 963 (altsubject && num_altsubject && 964 !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject", 965 altsubject, num_altsubject)) || 966 (cert_hash && 967 !wpa_dbus_dict_append_string(&dict_iter, "cert_hash", 968 cert_hash)) || 969 (cert && 970 !wpa_dbus_dict_append_byte_array(&dict_iter, "cert", 971 wpabuf_head(cert), 972 wpabuf_len(cert))) || 973 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 974 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 975 else 976 dbus_connection_send(iface->con, msg, NULL); 977 dbus_message_unref(msg); 978 } 979 980 981 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s, 982 const char *status, const char *parameter) 983 { 984 struct wpas_dbus_priv *iface; 985 DBusMessage *msg; 986 DBusMessageIter iter; 987 988 iface = wpa_s->global->dbus; 989 990 /* Do nothing if the control interface is not turned on */ 991 if (iface == NULL || !wpa_s->dbus_new_path) 992 return; 993 994 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 995 WPAS_DBUS_NEW_IFACE_INTERFACE, 996 "EAP"); 997 if (msg == NULL) 998 return; 999 1000 dbus_message_iter_init_append(msg, &iter); 1001 1002 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) || 1003 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, 1004 ¶meter)) 1005 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1006 else 1007 dbus_connection_send(iface->con, msg, NULL); 1008 dbus_message_unref(msg); 1009 } 1010 1011 1012 /** 1013 * wpas_dbus_signal_sta - Send a station related event signal 1014 * @wpa_s: %wpa_supplicant network interface data 1015 * @sta: station mac address 1016 * @sig_name: signal name - StaAuthorized or StaDeauthorized 1017 * 1018 * Notify listeners about event related with station 1019 */ 1020 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s, 1021 const u8 *sta, const char *sig_name) 1022 { 1023 struct wpas_dbus_priv *iface; 1024 DBusMessage *msg; 1025 char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX]; 1026 char *dev_mac; 1027 1028 os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta)); 1029 dev_mac = sta_mac; 1030 1031 iface = wpa_s->global->dbus; 1032 1033 /* Do nothing if the control interface is not turned on */ 1034 if (iface == NULL || !wpa_s->dbus_new_path) 1035 return; 1036 1037 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1038 WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name); 1039 if (msg == NULL) 1040 return; 1041 1042 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac, 1043 DBUS_TYPE_INVALID)) 1044 dbus_connection_send(iface->con, msg, NULL); 1045 else 1046 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1047 dbus_message_unref(msg); 1048 1049 wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'", 1050 sta_mac, sig_name); 1051 } 1052 1053 1054 /** 1055 * wpas_dbus_signal_sta_authorized - Send a STA authorized signal 1056 * @wpa_s: %wpa_supplicant network interface data 1057 * @sta: station mac address 1058 * 1059 * Notify listeners a new station has been authorized 1060 */ 1061 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s, 1062 const u8 *sta) 1063 { 1064 wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized"); 1065 } 1066 1067 1068 /** 1069 * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal 1070 * @wpa_s: %wpa_supplicant network interface data 1071 * @sta: station mac address 1072 * 1073 * Notify listeners a station has been deauthorized 1074 */ 1075 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s, 1076 const u8 *sta) 1077 { 1078 wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized"); 1079 } 1080 1081 1082 /** 1083 * wpas_dbus_signal_station - Send an event signal related to a station object 1084 * @wpa_s: %wpa_supplicant network interface data 1085 * @station_obj_path: Station object path 1086 * @sig_name: signal name - StationAdded or StationRemoved 1087 * @properties: Whether to add second argument with object properties 1088 * 1089 * Notify listeners about event related with station. 1090 */ 1091 static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s, 1092 const char *station_obj_path, 1093 const char *sig_name, 1094 dbus_bool_t properties) 1095 { 1096 struct wpas_dbus_priv *iface; 1097 DBusMessage *msg; 1098 DBusMessageIter iter; 1099 1100 iface = wpa_s->global->dbus; 1101 1102 /* Do nothing if the control interface is not turned on */ 1103 if (!iface || !wpa_s->dbus_new_path) 1104 return; 1105 1106 wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name); 1107 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1108 WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name); 1109 if (!msg) 1110 return; 1111 1112 dbus_message_iter_init_append(msg, &iter); 1113 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1114 &station_obj_path) || 1115 (properties && 1116 !wpa_dbus_get_object_properties(iface, station_obj_path, 1117 WPAS_DBUS_NEW_IFACE_STA, 1118 &iter))) 1119 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1120 else 1121 dbus_connection_send(iface->con, msg, NULL); 1122 dbus_message_unref(msg); 1123 } 1124 1125 1126 /** 1127 * wpas_dbus_signal_station_added - Send a Station added signal 1128 * @wpa_s: %wpa_supplicant network interface data 1129 * @station_obj_path: new Station object path 1130 * 1131 * Notify listeners about adding new Station 1132 */ 1133 static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s, 1134 const char *station_obj_path) 1135 { 1136 wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE); 1137 } 1138 1139 1140 /** 1141 * wpas_dbus_signal_station_removed - Send a Station removed signal 1142 * @wpa_s: %wpa_supplicant network interface data 1143 * @station_obj_path: Station object path 1144 * 1145 * Notify listeners about removing Station 1146 */ 1147 static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s, 1148 const char *station_obj_path) 1149 { 1150 wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved", 1151 FALSE); 1152 } 1153 1154 1155 #ifdef CONFIG_P2P 1156 1157 /** 1158 * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed 1159 * @wpa_s: %wpa_supplicant network interface data 1160 * @role: role of this device (client or GO) 1161 * Sends signal with i/f name and role as string arguments 1162 */ 1163 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s, 1164 const char *role) 1165 { 1166 DBusMessage *msg; 1167 DBusMessageIter iter, dict_iter; 1168 struct wpas_dbus_priv *iface = wpa_s->global->dbus; 1169 struct wpa_supplicant *parent; 1170 1171 /* Do nothing if the control interface is not turned on */ 1172 if (iface == NULL) 1173 return; 1174 1175 parent = wpa_s->parent; 1176 if (parent->p2p_mgmt) 1177 parent = parent->parent; 1178 1179 if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path || 1180 !parent->dbus_new_path) 1181 return; 1182 1183 msg = dbus_message_new_signal(parent->dbus_new_path, 1184 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1185 "GroupFinished"); 1186 if (msg == NULL) 1187 return; 1188 1189 dbus_message_iter_init_append(msg, &iter); 1190 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1191 !wpa_dbus_dict_append_object_path(&dict_iter, 1192 "interface_object", 1193 wpa_s->dbus_new_path) || 1194 !wpa_dbus_dict_append_string(&dict_iter, "role", role) || 1195 !wpa_dbus_dict_append_object_path(&dict_iter, "group_object", 1196 wpa_s->dbus_groupobj_path) || 1197 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 1198 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1199 else 1200 dbus_connection_send(iface->con, msg, NULL); 1201 dbus_message_unref(msg); 1202 } 1203 1204 1205 /** 1206 * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events 1207 * 1208 * @dev_addr - who sent the request or responded to our request. 1209 * @request - Will be 1 if request, 0 for response. 1210 * @status - valid only in case of response 1211 * @config_methods - wps config methods 1212 * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method 1213 * 1214 * Sends following provision discovery related events: 1215 * ProvisionDiscoveryRequestDisplayPin 1216 * ProvisionDiscoveryResponseDisplayPin 1217 * ProvisionDiscoveryRequestEnterPin 1218 * ProvisionDiscoveryResponseEnterPin 1219 * ProvisionDiscoveryPBCRequest 1220 * ProvisionDiscoveryPBCResponse 1221 * 1222 * TODO:: 1223 * ProvisionDiscoveryFailure (timeout case) 1224 */ 1225 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s, 1226 const u8 *dev_addr, int request, 1227 enum p2p_prov_disc_status status, 1228 u16 config_methods, 1229 unsigned int generated_pin) 1230 { 1231 DBusMessage *msg; 1232 DBusMessageIter iter; 1233 struct wpas_dbus_priv *iface; 1234 char *_signal; 1235 int add_pin = 0; 1236 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1237 int error_ret = 1; 1238 char pin[9], *p_pin = NULL; 1239 1240 iface = wpa_s->global->dbus; 1241 1242 /* Do nothing if the control interface is not turned on */ 1243 if (iface == NULL) 1244 return; 1245 1246 if (wpa_s->p2p_mgmt) 1247 wpa_s = wpa_s->parent; 1248 if (!wpa_s->dbus_new_path) 1249 return; 1250 1251 if (request || !status) { 1252 if (config_methods & WPS_CONFIG_DISPLAY) 1253 _signal = request ? 1254 "ProvisionDiscoveryRequestDisplayPin" : 1255 "ProvisionDiscoveryResponseEnterPin"; 1256 else if (config_methods & WPS_CONFIG_KEYPAD) 1257 _signal = request ? 1258 "ProvisionDiscoveryRequestEnterPin" : 1259 "ProvisionDiscoveryResponseDisplayPin"; 1260 else if (config_methods & WPS_CONFIG_PUSHBUTTON) 1261 _signal = request ? "ProvisionDiscoveryPBCRequest" : 1262 "ProvisionDiscoveryPBCResponse"; 1263 else 1264 return; /* Unknown or un-supported method */ 1265 } else { 1266 /* Explicit check for failure response */ 1267 _signal = "ProvisionDiscoveryFailure"; 1268 } 1269 1270 add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) || 1271 (!request && !status && 1272 (config_methods & WPS_CONFIG_KEYPAD))); 1273 1274 if (add_pin) { 1275 os_snprintf(pin, sizeof(pin), "%08d", generated_pin); 1276 p_pin = pin; 1277 } 1278 1279 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1280 WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal); 1281 if (msg == NULL) 1282 return; 1283 1284 /* Check if this is a known peer */ 1285 if (!p2p_peer_known(wpa_s->global->p2p, dev_addr)) 1286 goto error; 1287 1288 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1289 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1290 COMPACT_MACSTR, 1291 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 1292 1293 path = peer_obj_path; 1294 1295 dbus_message_iter_init_append(msg, &iter); 1296 1297 if (!dbus_message_iter_append_basic(&iter, 1298 DBUS_TYPE_OBJECT_PATH, 1299 &path)) 1300 goto error; 1301 1302 if (!request && status) 1303 /* Attach status to ProvisionDiscoveryFailure */ 1304 error_ret = !dbus_message_iter_append_basic(&iter, 1305 DBUS_TYPE_INT32, 1306 &status); 1307 else 1308 error_ret = (add_pin && 1309 !dbus_message_iter_append_basic(&iter, 1310 DBUS_TYPE_STRING, 1311 &p_pin)); 1312 1313 error: 1314 if (!error_ret) 1315 dbus_connection_send(iface->con, msg, NULL); 1316 else 1317 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1318 1319 dbus_message_unref(msg); 1320 } 1321 1322 1323 /** 1324 * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX 1325 * @wpa_s: %wpa_supplicant network interface data 1326 * @src: Source address of the message triggering this notification 1327 * @dev_passwd_id: WPS Device Password Id 1328 * @go_intent: Peer's GO Intent value 1329 * 1330 * Sends signal to notify that a peer P2P Device is requesting group owner 1331 * negotiation with us. 1332 */ 1333 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s, 1334 const u8 *src, u16 dev_passwd_id, 1335 u8 go_intent) 1336 { 1337 DBusMessage *msg; 1338 DBusMessageIter iter; 1339 struct wpas_dbus_priv *iface; 1340 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1341 1342 iface = wpa_s->global->dbus; 1343 1344 /* Do nothing if the control interface is not turned on */ 1345 if (iface == NULL) 1346 return; 1347 1348 if (wpa_s->p2p_mgmt) 1349 wpa_s = wpa_s->parent; 1350 if (!wpa_s->dbus_new_path) 1351 return; 1352 1353 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1354 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 1355 wpa_s->dbus_new_path, MAC2STR(src)); 1356 path = peer_obj_path; 1357 1358 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1359 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1360 "GONegotiationRequest"); 1361 if (msg == NULL) 1362 return; 1363 1364 dbus_message_iter_init_append(msg, &iter); 1365 1366 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1367 &path) || 1368 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16, 1369 &dev_passwd_id) || 1370 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE, 1371 &go_intent)) 1372 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1373 else 1374 dbus_connection_send(iface->con, msg, NULL); 1375 1376 dbus_message_unref(msg); 1377 } 1378 1379 1380 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s, 1381 const struct wpa_ssid *ssid, 1382 char *group_obj_path) 1383 { 1384 char group_name[3]; 1385 1386 if (!wpa_s->dbus_new_path || 1387 os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)) 1388 return -1; 1389 1390 os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2); 1391 group_name[2] = '\0'; 1392 1393 os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1394 "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s", 1395 wpa_s->dbus_new_path, group_name); 1396 1397 return 0; 1398 } 1399 1400 1401 struct group_changed_data { 1402 struct wpa_supplicant *wpa_s; 1403 struct p2p_peer_info *info; 1404 }; 1405 1406 1407 static int match_group_where_peer_is_client(struct p2p_group *group, 1408 void *user_data) 1409 { 1410 struct group_changed_data *data = user_data; 1411 const struct p2p_group_config *cfg; 1412 struct wpa_supplicant *wpa_s_go; 1413 1414 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr)) 1415 return 1; 1416 1417 cfg = p2p_group_get_config(group); 1418 1419 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid, 1420 cfg->ssid_len); 1421 if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) { 1422 wpas_dbus_signal_peer_groups_changed( 1423 data->wpa_s->p2pdev, data->info->p2p_device_addr); 1424 return 0; 1425 } 1426 1427 return 1; 1428 } 1429 1430 1431 static void signal_peer_groups_changed(struct p2p_peer_info *info, 1432 void *user_data) 1433 { 1434 struct group_changed_data *data = user_data; 1435 struct wpa_supplicant *wpa_s_go; 1436 1437 wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s, 1438 info->p2p_device_addr); 1439 if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) { 1440 wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev, 1441 info->p2p_device_addr); 1442 return; 1443 } 1444 1445 data->info = info; 1446 p2p_loop_on_all_groups(data->wpa_s->global->p2p, 1447 match_group_where_peer_is_client, data); 1448 data->info = NULL; 1449 } 1450 1451 1452 static void peer_groups_changed(struct wpa_supplicant *wpa_s) 1453 { 1454 struct group_changed_data data; 1455 1456 os_memset(&data, 0, sizeof(data)); 1457 data.wpa_s = wpa_s; 1458 1459 p2p_loop_on_known_peers(wpa_s->global->p2p, 1460 signal_peer_groups_changed, &data); 1461 } 1462 1463 1464 /** 1465 * wpas_dbus_signal_p2p_group_started - Signals P2P group has 1466 * started. Emitted when a group is successfully started 1467 * irrespective of the role (client/GO) of the current device 1468 * 1469 * @wpa_s: %wpa_supplicant network interface data 1470 * @client: this device is P2P client 1471 * @persistent: 0 - non persistent group, 1 - persistent group 1472 * @ip: When group role is client, it contains local IP address, netmask, and 1473 * GO's IP address, if assigned; otherwise, NULL 1474 */ 1475 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s, 1476 int client, int persistent, 1477 const u8 *ip) 1478 { 1479 DBusMessage *msg; 1480 DBusMessageIter iter, dict_iter; 1481 struct wpas_dbus_priv *iface; 1482 struct wpa_supplicant *parent; 1483 1484 parent = wpa_s->parent; 1485 if (parent->p2p_mgmt) 1486 parent = parent->parent; 1487 1488 iface = parent->global->dbus; 1489 1490 /* Do nothing if the control interface is not turned on */ 1491 if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path) 1492 return; 1493 1494 if (wpa_s->dbus_groupobj_path == NULL) 1495 return; 1496 1497 /* New interface has been created for this group */ 1498 msg = dbus_message_new_signal(parent->dbus_new_path, 1499 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1500 "GroupStarted"); 1501 if (msg == NULL) 1502 return; 1503 1504 dbus_message_iter_init_append(msg, &iter); 1505 /* 1506 * In case the device supports creating a separate interface the 1507 * DBus client will need to know the object path for the interface 1508 * object this group was created on, so include it here. 1509 */ 1510 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1511 !wpa_dbus_dict_append_object_path(&dict_iter, 1512 "interface_object", 1513 wpa_s->dbus_new_path) || 1514 !wpa_dbus_dict_append_string(&dict_iter, "role", 1515 client ? "client" : "GO") || 1516 !wpa_dbus_dict_append_bool(&dict_iter, "persistent", persistent) || 1517 !wpa_dbus_dict_append_object_path(&dict_iter, "group_object", 1518 wpa_s->dbus_groupobj_path) || 1519 (ip && 1520 (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr", 1521 (char *) ip, 4) || 1522 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask", 1523 (char *) ip + 4, 4) || 1524 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo", 1525 (char *) ip + 8, 4))) || 1526 !wpa_dbus_dict_close_write(&iter, &dict_iter)) { 1527 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1528 } else { 1529 dbus_connection_send(iface->con, msg, NULL); 1530 if (client) 1531 peer_groups_changed(wpa_s); 1532 } 1533 dbus_message_unref(msg); 1534 } 1535 1536 1537 /** 1538 * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal 1539 * @wpa_s: %wpa_supplicant network interface data 1540 * @res: Result of the GO Neg Request 1541 */ 1542 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s, 1543 struct p2p_go_neg_results *res) 1544 { 1545 DBusMessage *msg; 1546 DBusMessageIter iter, dict_iter; 1547 DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array; 1548 struct wpas_dbus_priv *iface; 1549 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1550 dbus_int32_t freqs[P2P_MAX_CHANNELS]; 1551 dbus_int32_t *f_array = freqs; 1552 1553 1554 iface = wpa_s->global->dbus; 1555 1556 if (wpa_s->p2p_mgmt) 1557 wpa_s = wpa_s->parent; 1558 1559 os_memset(freqs, 0, sizeof(freqs)); 1560 /* Do nothing if the control interface is not turned on */ 1561 if (iface == NULL || !wpa_s->dbus_new_path) 1562 return; 1563 1564 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1565 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 1566 wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr)); 1567 path = peer_obj_path; 1568 1569 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1570 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1571 res->status ? "GONegotiationFailure" : 1572 "GONegotiationSuccess"); 1573 if (msg == NULL) 1574 return; 1575 1576 dbus_message_iter_init_append(msg, &iter); 1577 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1578 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object", 1579 path) || 1580 !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status)) 1581 goto err; 1582 1583 if (!res->status) { 1584 int i = 0; 1585 int freq_list_num = 0; 1586 1587 if ((res->role_go && 1588 !wpa_dbus_dict_append_string(&dict_iter, "passphrase", 1589 res->passphrase)) || 1590 !wpa_dbus_dict_append_string(&dict_iter, "role_go", 1591 res->role_go ? "GO" : 1592 "client") || 1593 !wpa_dbus_dict_append_int32(&dict_iter, "frequency", 1594 res->freq) || 1595 !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid", 1596 (const char *) res->ssid, 1597 res->ssid_len) || 1598 !wpa_dbus_dict_append_byte_array(&dict_iter, 1599 "peer_device_addr", 1600 (const char *) 1601 res->peer_device_addr, 1602 ETH_ALEN) || 1603 !wpa_dbus_dict_append_byte_array(&dict_iter, 1604 "peer_interface_addr", 1605 (const char *) 1606 res->peer_interface_addr, 1607 ETH_ALEN) || 1608 !wpa_dbus_dict_append_string(&dict_iter, "wps_method", 1609 p2p_wps_method_text( 1610 res->wps_method))) 1611 goto err; 1612 1613 for (i = 0; i < P2P_MAX_CHANNELS; i++) { 1614 if (res->freq_list[i]) { 1615 freqs[i] = res->freq_list[i]; 1616 freq_list_num++; 1617 } 1618 } 1619 1620 if (!wpa_dbus_dict_begin_array(&dict_iter, 1621 "frequency_list", 1622 DBUS_TYPE_INT32_AS_STRING, 1623 &iter_dict_entry, 1624 &iter_dict_val, 1625 &iter_dict_array) || 1626 !dbus_message_iter_append_fixed_array(&iter_dict_array, 1627 DBUS_TYPE_INT32, 1628 &f_array, 1629 freq_list_num) || 1630 !wpa_dbus_dict_end_array(&dict_iter, 1631 &iter_dict_entry, 1632 &iter_dict_val, 1633 &iter_dict_array) || 1634 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group", 1635 res->persistent_group) || 1636 !wpa_dbus_dict_append_uint32(&dict_iter, 1637 "peer_config_timeout", 1638 res->peer_config_timeout)) 1639 goto err; 1640 } 1641 1642 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) 1643 goto err; 1644 1645 dbus_connection_send(iface->con, msg, NULL); 1646 err: 1647 dbus_message_unref(msg); 1648 } 1649 1650 1651 /** 1652 * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal 1653 * @wpa_s: %wpa_supplicant network interface data 1654 * @status: Status of invitation process 1655 * @bssid: Basic Service Set Identifier 1656 */ 1657 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s, 1658 int status, const u8 *bssid) 1659 { 1660 DBusMessage *msg; 1661 DBusMessageIter iter, dict_iter; 1662 struct wpas_dbus_priv *iface; 1663 1664 wpa_printf(MSG_DEBUG, "%s", __func__); 1665 1666 iface = wpa_s->global->dbus; 1667 /* Do nothing if the control interface is not turned on */ 1668 if (iface == NULL) 1669 return; 1670 1671 if (wpa_s->p2p_mgmt) 1672 wpa_s = wpa_s->parent; 1673 if (!wpa_s->dbus_new_path) 1674 return; 1675 1676 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1677 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1678 "InvitationResult"); 1679 1680 if (msg == NULL) 1681 return; 1682 1683 dbus_message_iter_init_append(msg, &iter); 1684 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1685 !wpa_dbus_dict_append_int32(&dict_iter, "status", status) || 1686 (bssid && 1687 !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID", 1688 (const char *) bssid, 1689 ETH_ALEN)) || 1690 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 1691 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1692 else 1693 dbus_connection_send(iface->con, msg, NULL); 1694 dbus_message_unref(msg); 1695 } 1696 1697 1698 /** 1699 * 1700 * Method to emit a signal for a peer joining the group. 1701 * The signal will carry path to the group member object 1702 * constructed using p2p i/f addr used for connecting. 1703 * 1704 * @wpa_s: %wpa_supplicant network interface data 1705 * @peer_addr: P2P Device Address of the peer joining the group 1706 */ 1707 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s, 1708 const u8 *peer_addr) 1709 { 1710 struct wpas_dbus_priv *iface; 1711 DBusMessage *msg; 1712 DBusMessageIter iter; 1713 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1714 struct wpa_supplicant *parent; 1715 1716 iface = wpa_s->global->dbus; 1717 1718 /* Do nothing if the control interface is not turned on */ 1719 if (iface == NULL) 1720 return; 1721 1722 if (!wpa_s->dbus_groupobj_path) 1723 return; 1724 1725 parent = wpa_s->parent; 1726 if (parent->p2p_mgmt) 1727 parent = parent->parent; 1728 if (!parent->dbus_new_path) 1729 return; 1730 1731 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1732 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1733 COMPACT_MACSTR, 1734 parent->dbus_new_path, MAC2STR(peer_addr)); 1735 1736 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path, 1737 WPAS_DBUS_NEW_IFACE_P2P_GROUP, 1738 "PeerJoined"); 1739 if (msg == NULL) 1740 return; 1741 1742 dbus_message_iter_init_append(msg, &iter); 1743 path = peer_obj_path; 1744 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1745 &path)) { 1746 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1747 } else { 1748 dbus_connection_send(iface->con, msg, NULL); 1749 wpas_dbus_signal_peer_groups_changed(parent, peer_addr); 1750 } 1751 dbus_message_unref(msg); 1752 } 1753 1754 1755 /** 1756 * 1757 * Method to emit a signal for a peer disconnecting the group. 1758 * The signal will carry path to the group member object 1759 * constructed using the P2P Device Address of the peer. 1760 * 1761 * @wpa_s: %wpa_supplicant network interface data 1762 * @peer_addr: P2P Device Address of the peer joining the group 1763 */ 1764 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s, 1765 const u8 *peer_addr) 1766 { 1767 struct wpas_dbus_priv *iface; 1768 DBusMessage *msg; 1769 DBusMessageIter iter; 1770 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1771 struct wpa_supplicant *parent; 1772 1773 iface = wpa_s->global->dbus; 1774 1775 /* Do nothing if the control interface is not turned on */ 1776 if (iface == NULL) 1777 return; 1778 1779 if (!wpa_s->dbus_groupobj_path) 1780 return; 1781 1782 parent = wpa_s->parent; 1783 if (parent->p2p_mgmt) 1784 parent = parent->parent; 1785 if (!parent->dbus_new_path) 1786 return; 1787 1788 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1789 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1790 COMPACT_MACSTR, 1791 parent->dbus_new_path, MAC2STR(peer_addr)); 1792 1793 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path, 1794 WPAS_DBUS_NEW_IFACE_P2P_GROUP, 1795 "PeerDisconnected"); 1796 if (msg == NULL) 1797 return; 1798 1799 dbus_message_iter_init_append(msg, &iter); 1800 path = peer_obj_path; 1801 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1802 &path)) { 1803 wpa_printf(MSG_ERROR, 1804 "dbus: Failed to construct PeerDisconnected signal"); 1805 } else { 1806 dbus_connection_send(iface->con, msg, NULL); 1807 wpas_dbus_signal_peer_groups_changed(parent, peer_addr); 1808 } 1809 dbus_message_unref(msg); 1810 } 1811 1812 1813 /** 1814 * 1815 * Method to emit a signal for a service discovery request. 1816 * The signal will carry station address, frequency, dialog token, 1817 * update indicator and it tlvs 1818 * 1819 * @wpa_s: %wpa_supplicant network interface data 1820 * @sa: station addr (p2p i/f) of the peer 1821 * @dialog_token: service discovery request dialog token 1822 * @update_indic: service discovery request update indicator 1823 * @tlvs: service discovery request genrated byte array of tlvs 1824 * @tlvs_len: service discovery request tlvs length 1825 */ 1826 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, 1827 int freq, const u8 *sa, u8 dialog_token, 1828 u16 update_indic, const u8 *tlvs, 1829 size_t tlvs_len) 1830 { 1831 DBusMessage *msg; 1832 DBusMessageIter iter, dict_iter; 1833 struct wpas_dbus_priv *iface; 1834 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1835 1836 iface = wpa_s->global->dbus; 1837 1838 /* Do nothing if the control interface is not turned on */ 1839 if (iface == NULL) 1840 return; 1841 1842 if (wpa_s->p2p_mgmt) 1843 wpa_s = wpa_s->parent; 1844 if (!wpa_s->dbus_new_path) 1845 return; 1846 1847 /* Check if this is a known peer */ 1848 if (!p2p_peer_known(wpa_s->global->p2p, sa)) 1849 return; 1850 1851 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1852 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1853 "ServiceDiscoveryRequest"); 1854 if (msg == NULL) 1855 return; 1856 1857 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1858 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1859 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa)); 1860 1861 path = peer_obj_path; 1862 1863 dbus_message_iter_init_append(msg, &iter); 1864 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1865 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object", 1866 path) || 1867 !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) || 1868 !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token", 1869 dialog_token) || 1870 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator", 1871 update_indic) || 1872 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs", 1873 (const char *) tlvs, 1874 tlvs_len) || 1875 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 1876 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1877 else 1878 dbus_connection_send(iface->con, msg, NULL); 1879 dbus_message_unref(msg); 1880 } 1881 1882 1883 /** 1884 * 1885 * Method to emit a signal for a service discovery response. 1886 * The signal will carry station address, update indicator and it 1887 * tlvs 1888 * 1889 * @wpa_s: %wpa_supplicant network interface data 1890 * @sa: station addr (p2p i/f) of the peer 1891 * @update_indic: service discovery request update indicator 1892 * @tlvs: service discovery request genrated byte array of tlvs 1893 * @tlvs_len: service discovery request tlvs length 1894 */ 1895 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s, 1896 const u8 *sa, u16 update_indic, 1897 const u8 *tlvs, size_t tlvs_len) 1898 { 1899 DBusMessage *msg; 1900 DBusMessageIter iter, dict_iter; 1901 struct wpas_dbus_priv *iface; 1902 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1903 1904 iface = wpa_s->global->dbus; 1905 1906 /* Do nothing if the control interface is not turned on */ 1907 if (iface == NULL) 1908 return; 1909 1910 if (wpa_s->p2p_mgmt) 1911 wpa_s = wpa_s->parent; 1912 if (!wpa_s->dbus_new_path) 1913 return; 1914 1915 /* Check if this is a known peer */ 1916 if (!p2p_peer_known(wpa_s->global->p2p, sa)) 1917 return; 1918 1919 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1920 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1921 "ServiceDiscoveryResponse"); 1922 if (msg == NULL) 1923 return; 1924 1925 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1926 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1927 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa)); 1928 1929 path = peer_obj_path; 1930 1931 dbus_message_iter_init_append(msg, &iter); 1932 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1933 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object", 1934 path) || 1935 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator", 1936 update_indic) || 1937 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs", 1938 (const char *) tlvs, 1939 tlvs_len) || 1940 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 1941 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1942 else 1943 dbus_connection_send(iface->con, msg, NULL); 1944 dbus_message_unref(msg); 1945 } 1946 1947 1948 /** 1949 * wpas_dbus_signal_persistent_group - Send a persistent group related 1950 * event signal 1951 * @wpa_s: %wpa_supplicant network interface data 1952 * @id: new persistent group id 1953 * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved 1954 * @properties: determines if add second argument with object properties 1955 * 1956 * Notify listeners about an event related to persistent groups. 1957 */ 1958 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s, 1959 int id, const char *sig_name, 1960 dbus_bool_t properties) 1961 { 1962 struct wpas_dbus_priv *iface; 1963 DBusMessage *msg; 1964 DBusMessageIter iter; 1965 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1966 1967 iface = wpa_s->global->dbus; 1968 1969 /* Do nothing if the control interface is not turned on */ 1970 if (iface == NULL) 1971 return; 1972 1973 if (wpa_s->p2p_mgmt) 1974 wpa_s = wpa_s->parent; 1975 if (!wpa_s->dbus_new_path) 1976 return; 1977 1978 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1979 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 1980 wpa_s->dbus_new_path, id); 1981 1982 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1983 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1984 sig_name); 1985 if (msg == NULL) 1986 return; 1987 1988 dbus_message_iter_init_append(msg, &iter); 1989 path = pgrp_obj_path; 1990 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1991 &path) || 1992 (properties && 1993 !wpa_dbus_get_object_properties( 1994 iface, pgrp_obj_path, 1995 WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter))) 1996 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1997 else 1998 dbus_connection_send(iface->con, msg, NULL); 1999 2000 dbus_message_unref(msg); 2001 } 2002 2003 2004 /** 2005 * wpas_dbus_signal_persistent_group_added - Send a persistent_group 2006 * added signal 2007 * @wpa_s: %wpa_supplicant network interface data 2008 * @id: new persistent group id 2009 * 2010 * Notify listeners about addition of a new persistent group. 2011 */ 2012 static void wpas_dbus_signal_persistent_group_added( 2013 struct wpa_supplicant *wpa_s, int id) 2014 { 2015 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded", 2016 TRUE); 2017 } 2018 2019 2020 /** 2021 * wpas_dbus_signal_persistent_group_removed - Send a persistent_group 2022 * removed signal 2023 * @wpa_s: %wpa_supplicant network interface data 2024 * @id: persistent group id 2025 * 2026 * Notify listeners about removal of a persistent group. 2027 */ 2028 static void wpas_dbus_signal_persistent_group_removed( 2029 struct wpa_supplicant *wpa_s, int id) 2030 { 2031 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved", 2032 FALSE); 2033 } 2034 2035 2036 /** 2037 * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event 2038 * @wpa_s: %wpa_supplicant network interface data 2039 * @fail: WPS failure information 2040 * 2041 * Sends Event dbus signal with name "fail" and dictionary containing 2042 * "msg" field with fail message number (int32) as arguments 2043 */ 2044 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s, 2045 struct wps_event_fail *fail) 2046 { 2047 2048 DBusMessage *msg; 2049 DBusMessageIter iter, dict_iter; 2050 struct wpas_dbus_priv *iface; 2051 char *key = "fail"; 2052 2053 iface = wpa_s->global->dbus; 2054 2055 /* Do nothing if the control interface is not turned on */ 2056 if (iface == NULL) 2057 return; 2058 2059 if (wpa_s->p2p_mgmt) 2060 wpa_s = wpa_s->parent; 2061 2062 if (!wpa_s->dbus_new_path) 2063 return; 2064 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2065 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2066 "WpsFailed"); 2067 if (msg == NULL) 2068 return; 2069 2070 dbus_message_iter_init_append(msg, &iter); 2071 2072 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 2073 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 2074 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) || 2075 !wpa_dbus_dict_append_int16(&dict_iter, "config_error", 2076 fail->config_error) || 2077 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 2078 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 2079 else 2080 dbus_connection_send(iface->con, msg, NULL); 2081 2082 dbus_message_unref(msg); 2083 } 2084 2085 2086 /** 2087 * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event 2088 * @wpa_s: %wpa_supplicant network interface data 2089 * @reason: indicates the reason code for group formation failure 2090 * 2091 * Sends Event dbus signal and string reason code when available. 2092 */ 2093 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s, 2094 const char *reason) 2095 { 2096 DBusMessage *msg; 2097 struct wpas_dbus_priv *iface; 2098 2099 iface = wpa_s->global->dbus; 2100 2101 /* Do nothing if the control interface is not turned on */ 2102 if (iface == NULL) 2103 return; 2104 2105 if (wpa_s->p2p_mgmt) 2106 wpa_s = wpa_s->parent; 2107 2108 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2109 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2110 "GroupFormationFailure"); 2111 if (msg == NULL) 2112 return; 2113 2114 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason, 2115 DBUS_TYPE_INVALID)) 2116 dbus_connection_send(iface->con, msg, NULL); 2117 else 2118 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 2119 2120 dbus_message_unref(msg); 2121 } 2122 2123 2124 /** 2125 * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal 2126 * @wpa_s: %wpa_supplicant network interface data 2127 * @sa: Source address of the Invitation Request 2128 * @dev_add: GO Device Address 2129 * @bssid: P2P Group BSSID or %NULL if not received 2130 * @id: Persistent group id or %0 if not persistent group 2131 * @op_freq: Operating frequency for the group 2132 */ 2133 2134 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s, 2135 const u8 *sa, const u8 *dev_addr, 2136 const u8 *bssid, int id, 2137 int op_freq) 2138 { 2139 DBusMessage *msg; 2140 DBusMessageIter iter, dict_iter; 2141 struct wpas_dbus_priv *iface; 2142 2143 iface = wpa_s->global->dbus; 2144 2145 /* Do nothing if the control interface is not turned on */ 2146 if (iface == NULL) 2147 return; 2148 2149 if (wpa_s->p2p_mgmt) 2150 wpa_s = wpa_s->parent; 2151 2152 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2153 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2154 "InvitationReceived"); 2155 if (msg == NULL) 2156 return; 2157 2158 dbus_message_iter_init_append(msg, &iter); 2159 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 2160 (sa && 2161 !wpa_dbus_dict_append_byte_array(&dict_iter, "sa", 2162 (const char *) sa, ETH_ALEN)) || 2163 (dev_addr && 2164 !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr", 2165 (const char *) dev_addr, 2166 ETH_ALEN)) || 2167 (bssid && 2168 !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid", 2169 (const char *) bssid, 2170 ETH_ALEN)) || 2171 (id && 2172 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) || 2173 !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) || 2174 !wpa_dbus_dict_close_write(&iter, &dict_iter)) { 2175 dbus_message_unref(msg); 2176 return; 2177 } 2178 2179 dbus_connection_send(iface->con, msg, NULL); 2180 dbus_message_unref(msg); 2181 } 2182 2183 2184 #endif /* CONFIG_P2P */ 2185 2186 2187 /** 2188 * wpas_dbus_signal_prop_changed - Signals change of property 2189 * @wpa_s: %wpa_supplicant network interface data 2190 * @property: indicates which property has changed 2191 * 2192 * Sends PropertyChanged signals with path, interface and arguments 2193 * depending on which property has changed. 2194 */ 2195 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, 2196 enum wpas_dbus_prop property) 2197 { 2198 char *prop; 2199 dbus_bool_t flush; 2200 2201 if (wpa_s->dbus_new_path == NULL) 2202 return; /* Skip signal since D-Bus setup is not yet ready */ 2203 2204 flush = FALSE; 2205 switch (property) { 2206 case WPAS_DBUS_PROP_AP_SCAN: 2207 prop = "ApScan"; 2208 break; 2209 case WPAS_DBUS_PROP_SCANNING: 2210 prop = "Scanning"; 2211 break; 2212 case WPAS_DBUS_PROP_STATE: 2213 prop = "State"; 2214 break; 2215 case WPAS_DBUS_PROP_CURRENT_BSS: 2216 prop = "CurrentBSS"; 2217 break; 2218 case WPAS_DBUS_PROP_CURRENT_NETWORK: 2219 prop = "CurrentNetwork"; 2220 break; 2221 case WPAS_DBUS_PROP_BSSS: 2222 prop = "BSSs"; 2223 break; 2224 case WPAS_DBUS_PROP_STATIONS: 2225 prop = "Stations"; 2226 break; 2227 case WPAS_DBUS_PROP_CURRENT_AUTH_MODE: 2228 prop = "CurrentAuthMode"; 2229 break; 2230 case WPAS_DBUS_PROP_DISCONNECT_REASON: 2231 prop = "DisconnectReason"; 2232 flush = TRUE; 2233 break; 2234 case WPAS_DBUS_PROP_AUTH_STATUS_CODE: 2235 prop = "AuthStatusCode"; 2236 flush = TRUE; 2237 break; 2238 case WPAS_DBUS_PROP_ASSOC_STATUS_CODE: 2239 prop = "AssocStatusCode"; 2240 flush = TRUE; 2241 break; 2242 case WPAS_DBUS_PROP_ROAM_TIME: 2243 prop = "RoamTime"; 2244 break; 2245 case WPAS_DBUS_PROP_ROAM_COMPLETE: 2246 prop = "RoamComplete"; 2247 break; 2248 case WPAS_DBUS_PROP_SESSION_LENGTH: 2249 prop = "SessionLength"; 2250 break; 2251 case WPAS_DBUS_PROP_BSS_TM_STATUS: 2252 prop = "BSSTMStatus"; 2253 break; 2254 default: 2255 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 2256 __func__, property); 2257 return; 2258 } 2259 2260 wpa_dbus_mark_property_changed(wpa_s->global->dbus, 2261 wpa_s->dbus_new_path, 2262 WPAS_DBUS_NEW_IFACE_INTERFACE, prop); 2263 if (flush) { 2264 wpa_dbus_flush_object_changed_properties( 2265 wpa_s->global->dbus->con, wpa_s->dbus_new_path); 2266 } 2267 } 2268 2269 2270 /** 2271 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property 2272 * @wpa_s: %wpa_supplicant network interface data 2273 * @property: indicates which property has changed 2274 * @id: unique BSS identifier 2275 * 2276 * Sends PropertyChanged signals with path, interface, and arguments depending 2277 * on which property has changed. 2278 */ 2279 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s, 2280 enum wpas_dbus_bss_prop property, 2281 unsigned int id) 2282 { 2283 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 2284 char *prop; 2285 2286 if (!wpa_s->dbus_new_path) 2287 return; 2288 2289 switch (property) { 2290 case WPAS_DBUS_BSS_PROP_SIGNAL: 2291 prop = "Signal"; 2292 break; 2293 case WPAS_DBUS_BSS_PROP_FREQ: 2294 prop = "Frequency"; 2295 break; 2296 case WPAS_DBUS_BSS_PROP_MODE: 2297 prop = "Mode"; 2298 break; 2299 case WPAS_DBUS_BSS_PROP_PRIVACY: 2300 prop = "Privacy"; 2301 break; 2302 case WPAS_DBUS_BSS_PROP_RATES: 2303 prop = "Rates"; 2304 break; 2305 case WPAS_DBUS_BSS_PROP_WPA: 2306 prop = "WPA"; 2307 break; 2308 case WPAS_DBUS_BSS_PROP_RSN: 2309 prop = "RSN"; 2310 break; 2311 case WPAS_DBUS_BSS_PROP_WPS: 2312 prop = "WPS"; 2313 break; 2314 case WPAS_DBUS_BSS_PROP_IES: 2315 prop = "IEs"; 2316 break; 2317 case WPAS_DBUS_BSS_PROP_AGE: 2318 prop = "Age"; 2319 break; 2320 default: 2321 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 2322 __func__, property); 2323 return; 2324 } 2325 2326 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 2327 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2328 wpa_s->dbus_new_path, id); 2329 2330 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 2331 WPAS_DBUS_NEW_IFACE_BSS, prop); 2332 } 2333 2334 2335 /** 2336 * wpas_dbus_sta_signal_prop_changed - Signals change of STA property 2337 * @wpa_s: %wpa_supplicant network interface data 2338 * @property: indicates which property has changed 2339 * @address: unique BSS identifier 2340 * 2341 * Sends PropertyChanged signals with path, interface, and arguments depending 2342 * on which property has changed. 2343 */ 2344 void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s, 2345 enum wpas_dbus_bss_prop property, 2346 u8 address[ETH_ALEN]) 2347 { 2348 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 2349 char *prop; 2350 2351 switch (property) { 2352 case WPAS_DBUS_STA_PROP_ADDRESS: 2353 prop = "Address"; 2354 break; 2355 default: 2356 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 2357 __func__, property); 2358 return; 2359 } 2360 2361 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 2362 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, 2363 wpa_s->dbus_new_path, MAC2STR(address)); 2364 2365 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 2366 WPAS_DBUS_NEW_IFACE_STA, prop); 2367 } 2368 2369 2370 /** 2371 * wpas_dbus_signal_debug_level_changed - Signals change of debug param 2372 * @global: wpa_global structure 2373 * 2374 * Sends PropertyChanged signals informing that debug level has changed. 2375 */ 2376 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global) 2377 { 2378 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2379 WPAS_DBUS_NEW_INTERFACE, 2380 "DebugLevel"); 2381 } 2382 2383 2384 /** 2385 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param 2386 * @global: wpa_global structure 2387 * 2388 * Sends PropertyChanged signals informing that debug timestamp has changed. 2389 */ 2390 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global) 2391 { 2392 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2393 WPAS_DBUS_NEW_INTERFACE, 2394 "DebugTimestamp"); 2395 } 2396 2397 2398 /** 2399 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param 2400 * @global: wpa_global structure 2401 * 2402 * Sends PropertyChanged signals informing that debug show_keys has changed. 2403 */ 2404 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global) 2405 { 2406 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2407 WPAS_DBUS_NEW_INTERFACE, 2408 "DebugShowKeys"); 2409 } 2410 2411 2412 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc, 2413 void *priv, 2414 WPADBusArgumentFreeFunction priv_free, 2415 const struct wpa_dbus_method_desc *methods, 2416 const struct wpa_dbus_property_desc *properties, 2417 const struct wpa_dbus_signal_desc *signals) 2418 { 2419 int n; 2420 2421 obj_desc->user_data = priv; 2422 obj_desc->user_data_free_func = priv_free; 2423 obj_desc->methods = methods; 2424 obj_desc->properties = properties; 2425 obj_desc->signals = signals; 2426 2427 for (n = 0; properties && properties->dbus_property; properties++) 2428 n++; 2429 2430 obj_desc->prop_changed_flags = os_zalloc(n); 2431 if (!obj_desc->prop_changed_flags) 2432 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers", 2433 __func__); 2434 } 2435 2436 2437 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = { 2438 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE, 2439 (WPADBusMethodHandler) wpas_dbus_handler_create_interface, 2440 { 2441 { "args", "a{sv}", ARG_IN }, 2442 { "path", "o", ARG_OUT }, 2443 END_ARGS 2444 } 2445 }, 2446 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE, 2447 (WPADBusMethodHandler) wpas_dbus_handler_remove_interface, 2448 { 2449 { "path", "o", ARG_IN }, 2450 END_ARGS 2451 } 2452 }, 2453 { "GetInterface", WPAS_DBUS_NEW_INTERFACE, 2454 (WPADBusMethodHandler) wpas_dbus_handler_get_interface, 2455 { 2456 { "ifname", "s", ARG_IN }, 2457 { "path", "o", ARG_OUT }, 2458 END_ARGS 2459 } 2460 }, 2461 { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE, 2462 (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect, 2463 { 2464 END_ARGS 2465 } 2466 }, 2467 { NULL, NULL, NULL, { END_ARGS } } 2468 }; 2469 2470 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = { 2471 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s", 2472 wpas_dbus_getter_debug_level, 2473 wpas_dbus_setter_debug_level, 2474 NULL 2475 }, 2476 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b", 2477 wpas_dbus_getter_debug_timestamp, 2478 wpas_dbus_setter_debug_timestamp, 2479 NULL 2480 }, 2481 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b", 2482 wpas_dbus_getter_debug_show_keys, 2483 wpas_dbus_setter_debug_show_keys, 2484 NULL 2485 }, 2486 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao", 2487 wpas_dbus_getter_interfaces, 2488 NULL, 2489 NULL 2490 }, 2491 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as", 2492 wpas_dbus_getter_eap_methods, 2493 NULL, 2494 NULL 2495 }, 2496 { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as", 2497 wpas_dbus_getter_global_capabilities, 2498 NULL, 2499 NULL 2500 }, 2501 #ifdef CONFIG_WIFI_DISPLAY 2502 { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay", 2503 wpas_dbus_getter_global_wfd_ies, 2504 wpas_dbus_setter_global_wfd_ies, 2505 NULL 2506 }, 2507 #endif /* CONFIG_WIFI_DISPLAY */ 2508 { NULL, NULL, NULL, NULL, NULL, NULL } 2509 }; 2510 2511 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = { 2512 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE, 2513 { 2514 { "path", "o", ARG_OUT }, 2515 { "properties", "a{sv}", ARG_OUT }, 2516 END_ARGS 2517 } 2518 }, 2519 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE, 2520 { 2521 { "path", "o", ARG_OUT }, 2522 END_ARGS 2523 } 2524 }, 2525 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2526 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE, 2527 { 2528 { "properties", "a{sv}", ARG_OUT }, 2529 END_ARGS 2530 } 2531 }, 2532 { NULL, NULL, { END_ARGS } } 2533 }; 2534 2535 2536 static char * uscore_to_dbus(const char *uscore) 2537 { 2538 const char *p = uscore; 2539 char *str, *s; 2540 dbus_bool_t last_was_uscore = TRUE; 2541 2542 s = str = os_zalloc(os_strlen(uscore) + 1); 2543 if (!str) 2544 return NULL; 2545 while (p && *p) { 2546 if (*p == '_') { 2547 last_was_uscore = TRUE; 2548 } else { 2549 *s++ = last_was_uscore ? toupper(*p) : *p; 2550 last_was_uscore = FALSE; 2551 } 2552 p++; 2553 } 2554 2555 return str; 2556 } 2557 2558 2559 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv); 2560 2561 2562 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv) 2563 { 2564 int idx = priv->globals_start; 2565 2566 /* Free all allocated property values */ 2567 while (priv->all_interface_properties[idx].dbus_property) 2568 os_free((char *) 2569 priv->all_interface_properties[idx++].dbus_property); 2570 os_free((char *) priv->all_interface_properties); 2571 } 2572 2573 2574 /** 2575 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface 2576 * @global: Pointer to global data from wpa_supplicant_init() 2577 * Returns: 0 on success or -1 on failure 2578 * 2579 * Initialize the dbus control interface for wpa_supplicant and start 2580 * receiving commands from external programs over the bus. 2581 */ 2582 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv) 2583 { 2584 struct wpa_dbus_object_desc *obj_desc; 2585 int ret; 2586 2587 ret = wpa_dbus_ctrl_iface_props_init(priv); 2588 if (ret < 0) { 2589 wpa_printf(MSG_ERROR, 2590 "dbus: Not enough memory to init interface properties"); 2591 return -1; 2592 } 2593 2594 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2595 if (!obj_desc) { 2596 wpa_printf(MSG_ERROR, 2597 "Not enough memory to create object description"); 2598 goto error; 2599 } 2600 2601 wpas_dbus_register(obj_desc, priv->global, NULL, 2602 wpas_dbus_global_methods, 2603 wpas_dbus_global_properties, 2604 wpas_dbus_global_signals); 2605 2606 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'", 2607 WPAS_DBUS_NEW_PATH); 2608 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH, 2609 WPAS_DBUS_NEW_SERVICE, 2610 obj_desc); 2611 if (ret < 0) { 2612 free_dbus_object_desc(obj_desc); 2613 goto error; 2614 } 2615 2616 priv->dbus_new_initialized = 1; 2617 return 0; 2618 2619 error: 2620 wpa_dbus_ctrl_iface_props_deinit(priv); 2621 return -1; 2622 } 2623 2624 2625 /** 2626 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for 2627 * wpa_supplicant 2628 * @priv: Pointer to dbus private data from wpas_dbus_init() 2629 * 2630 * Deinitialize the dbus control interface that was initialized with 2631 * wpas_dbus_ctrl_iface_init(). 2632 */ 2633 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv) 2634 { 2635 if (!priv->dbus_new_initialized) 2636 return; 2637 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'", 2638 WPAS_DBUS_NEW_PATH); 2639 dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH); 2640 wpa_dbus_ctrl_iface_props_deinit(priv); 2641 } 2642 2643 2644 static void wpa_dbus_free(void *ptr) 2645 { 2646 os_free(ptr); 2647 } 2648 2649 2650 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = { 2651 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}", 2652 wpas_dbus_getter_network_properties, 2653 wpas_dbus_setter_network_properties, 2654 NULL 2655 }, 2656 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b", 2657 wpas_dbus_getter_enabled, 2658 wpas_dbus_setter_enabled, 2659 NULL 2660 }, 2661 { NULL, NULL, NULL, NULL, NULL, NULL } 2662 }; 2663 2664 2665 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = { 2666 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2667 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK, 2668 { 2669 { "properties", "a{sv}", ARG_OUT }, 2670 END_ARGS 2671 } 2672 }, 2673 { NULL, NULL, { END_ARGS } } 2674 }; 2675 2676 2677 /** 2678 * wpas_dbus_register_network - Register a configured network with dbus 2679 * @wpa_s: wpa_supplicant interface structure 2680 * @ssid: network configuration data 2681 * Returns: 0 on success, -1 on failure 2682 * 2683 * Registers network representing object with dbus 2684 */ 2685 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s, 2686 struct wpa_ssid *ssid) 2687 { 2688 struct wpas_dbus_priv *ctrl_iface; 2689 struct wpa_dbus_object_desc *obj_desc; 2690 struct network_handler_args *arg; 2691 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2692 2693 #ifdef CONFIG_P2P 2694 /* 2695 * If it is a persistent group register it as such. 2696 * This is to handle cases where an interface is being initialized 2697 * with a list of networks read from config. 2698 */ 2699 if (network_is_persistent_group(ssid)) 2700 return wpas_dbus_register_persistent_group(wpa_s, ssid); 2701 #endif /* CONFIG_P2P */ 2702 2703 /* Do nothing if the control interface is not turned on */ 2704 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 2705 return 0; 2706 ctrl_iface = wpa_s->global->dbus; 2707 if (ctrl_iface == NULL) 2708 return 0; 2709 2710 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2711 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2712 wpa_s->dbus_new_path, ssid->id); 2713 2714 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'", 2715 net_obj_path); 2716 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2717 if (!obj_desc) { 2718 wpa_printf(MSG_ERROR, 2719 "Not enough memory to create object description"); 2720 goto err; 2721 } 2722 2723 /* allocate memory for handlers arguments */ 2724 arg = os_zalloc(sizeof(struct network_handler_args)); 2725 if (!arg) { 2726 wpa_printf(MSG_ERROR, 2727 "Not enough memory to create arguments for method"); 2728 goto err; 2729 } 2730 2731 arg->wpa_s = wpa_s; 2732 arg->ssid = ssid; 2733 2734 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2735 wpas_dbus_network_properties, 2736 wpas_dbus_network_signals); 2737 2738 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path, 2739 wpa_s->ifname, obj_desc)) 2740 goto err; 2741 2742 wpas_dbus_signal_network_added(wpa_s, ssid->id); 2743 2744 return 0; 2745 2746 err: 2747 free_dbus_object_desc(obj_desc); 2748 return -1; 2749 } 2750 2751 2752 /** 2753 * wpas_dbus_unregister_network - Unregister a configured network from dbus 2754 * @wpa_s: wpa_supplicant interface structure 2755 * @nid: network id 2756 * Returns: 0 on success, -1 on failure 2757 * 2758 * Unregisters network representing object from dbus 2759 */ 2760 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid) 2761 { 2762 struct wpas_dbus_priv *ctrl_iface; 2763 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2764 int ret; 2765 #ifdef CONFIG_P2P 2766 struct wpa_ssid *ssid; 2767 2768 ssid = wpa_config_get_network(wpa_s->conf, nid); 2769 2770 /* If it is a persistent group unregister it as such */ 2771 if (ssid && network_is_persistent_group(ssid)) 2772 return wpas_dbus_unregister_persistent_group(wpa_s, nid); 2773 #endif /* CONFIG_P2P */ 2774 2775 /* Do nothing if the control interface is not turned on */ 2776 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL) 2777 return 0; 2778 ctrl_iface = wpa_s->global->dbus; 2779 if (ctrl_iface == NULL) 2780 return 0; 2781 2782 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2783 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2784 wpa_s->dbus_new_path, nid); 2785 2786 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'", 2787 net_obj_path); 2788 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path); 2789 2790 if (!ret) 2791 wpas_dbus_signal_network_removed(wpa_s, nid); 2792 2793 return ret; 2794 } 2795 2796 2797 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = { 2798 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2799 wpas_dbus_getter_bss_ssid, 2800 NULL, 2801 NULL 2802 }, 2803 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2804 wpas_dbus_getter_bss_bssid, 2805 NULL, 2806 NULL 2807 }, 2808 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b", 2809 wpas_dbus_getter_bss_privacy, 2810 NULL, 2811 NULL 2812 }, 2813 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s", 2814 wpas_dbus_getter_bss_mode, 2815 NULL, 2816 NULL 2817 }, 2818 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n", 2819 wpas_dbus_getter_bss_signal, 2820 NULL, 2821 NULL 2822 }, 2823 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q", 2824 wpas_dbus_getter_bss_frequency, 2825 NULL, 2826 NULL 2827 }, 2828 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au", 2829 wpas_dbus_getter_bss_rates, 2830 NULL, 2831 NULL 2832 }, 2833 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2834 wpas_dbus_getter_bss_wpa, 2835 NULL, 2836 NULL 2837 }, 2838 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2839 wpas_dbus_getter_bss_rsn, 2840 NULL, 2841 NULL 2842 }, 2843 { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2844 wpas_dbus_getter_bss_wps, 2845 NULL, 2846 NULL 2847 }, 2848 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2849 wpas_dbus_getter_bss_ies, 2850 NULL, 2851 NULL 2852 }, 2853 { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u", 2854 wpas_dbus_getter_bss_age, 2855 NULL, 2856 NULL 2857 }, 2858 { 2859 "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2860 wpas_dbus_getter_roam_time, 2861 NULL, 2862 NULL 2863 }, 2864 { 2865 "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 2866 wpas_dbus_getter_roam_complete, 2867 NULL, 2868 NULL 2869 }, 2870 { 2871 "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2872 wpas_dbus_getter_session_length, 2873 NULL, 2874 NULL 2875 }, 2876 { 2877 "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 2878 wpas_dbus_getter_bss_tm_status, 2879 NULL, 2880 NULL 2881 }, 2882 { NULL, NULL, NULL, NULL, NULL, NULL } 2883 }; 2884 2885 2886 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = { 2887 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2888 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS, 2889 { 2890 { "properties", "a{sv}", ARG_OUT }, 2891 END_ARGS 2892 } 2893 }, 2894 { NULL, NULL, { END_ARGS } } 2895 }; 2896 2897 2898 /** 2899 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus 2900 * @wpa_s: wpa_supplicant interface structure 2901 * @bssid: scanned network bssid 2902 * @id: unique BSS identifier 2903 * Returns: 0 on success, -1 on failure 2904 * 2905 * Unregisters BSS representing object from dbus 2906 */ 2907 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s, 2908 u8 bssid[ETH_ALEN], unsigned int id) 2909 { 2910 struct wpas_dbus_priv *ctrl_iface; 2911 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2912 2913 /* Do nothing if the control interface is not turned on */ 2914 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 2915 return 0; 2916 ctrl_iface = wpa_s->global->dbus; 2917 if (ctrl_iface == NULL) 2918 return 0; 2919 2920 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2921 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2922 wpa_s->dbus_new_path, id); 2923 2924 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'", 2925 bss_obj_path); 2926 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) { 2927 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s", 2928 bss_obj_path); 2929 return -1; 2930 } 2931 2932 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path); 2933 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 2934 2935 return 0; 2936 } 2937 2938 2939 /** 2940 * wpas_dbus_register_bss - Register a scanned BSS with dbus 2941 * @wpa_s: wpa_supplicant interface structure 2942 * @bssid: scanned network bssid 2943 * @id: unique BSS identifier 2944 * Returns: 0 on success, -1 on failure 2945 * 2946 * Registers BSS representing object with dbus 2947 */ 2948 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, 2949 u8 bssid[ETH_ALEN], unsigned int id) 2950 { 2951 struct wpas_dbus_priv *ctrl_iface; 2952 struct wpa_dbus_object_desc *obj_desc; 2953 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2954 struct bss_handler_args *arg; 2955 2956 /* Do nothing if the control interface is not turned on */ 2957 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 2958 return 0; 2959 ctrl_iface = wpa_s->global->dbus; 2960 if (ctrl_iface == NULL) 2961 return 0; 2962 2963 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2964 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2965 wpa_s->dbus_new_path, id); 2966 2967 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2968 if (!obj_desc) { 2969 wpa_printf(MSG_ERROR, 2970 "Not enough memory to create object description"); 2971 goto err; 2972 } 2973 2974 arg = os_zalloc(sizeof(struct bss_handler_args)); 2975 if (!arg) { 2976 wpa_printf(MSG_ERROR, 2977 "Not enough memory to create arguments for handler"); 2978 goto err; 2979 } 2980 arg->wpa_s = wpa_s; 2981 arg->id = id; 2982 2983 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2984 wpas_dbus_bss_properties, 2985 wpas_dbus_bss_signals); 2986 2987 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'", 2988 bss_obj_path); 2989 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path, 2990 wpa_s->ifname, obj_desc)) { 2991 wpa_printf(MSG_ERROR, 2992 "Cannot register BSSID dbus object %s.", 2993 bss_obj_path); 2994 goto err; 2995 } 2996 2997 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path); 2998 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 2999 3000 return 0; 3001 3002 err: 3003 free_dbus_object_desc(obj_desc); 3004 return -1; 3005 } 3006 3007 3008 static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = { 3009 { "Address", WPAS_DBUS_NEW_IFACE_STA, "ay", 3010 wpas_dbus_getter_sta_address, 3011 NULL, NULL 3012 }, 3013 { "AID", WPAS_DBUS_NEW_IFACE_STA, "q", 3014 wpas_dbus_getter_sta_aid, 3015 NULL, NULL 3016 }, 3017 { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q", 3018 wpas_dbus_getter_sta_caps, 3019 NULL, NULL 3020 }, 3021 { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t", 3022 wpas_dbus_getter_sta_rx_packets, 3023 NULL, NULL 3024 }, 3025 { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t", 3026 wpas_dbus_getter_sta_tx_packets, 3027 NULL, NULL 3028 }, 3029 { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t", 3030 wpas_dbus_getter_sta_rx_bytes, 3031 NULL, NULL 3032 }, 3033 { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t", 3034 wpas_dbus_getter_sta_tx_bytes, 3035 NULL, NULL 3036 }, 3037 { NULL, NULL, NULL, NULL, NULL, NULL } 3038 }; 3039 3040 3041 static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = { 3042 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3043 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA, 3044 { 3045 { "properties", "a{sv}", ARG_OUT }, 3046 END_ARGS 3047 } 3048 }, 3049 { NULL, NULL, { END_ARGS } } 3050 }; 3051 3052 3053 /** 3054 * wpas_dbus_unregister_sta - Unregister a connected station from dbus 3055 * @wpa_s: wpa_supplicant interface structure 3056 * @sta: station MAC address 3057 * Returns: 0 on success, -1 on failure 3058 * 3059 * Unregisters STA representing object from dbus. 3060 */ 3061 int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta) 3062 { 3063 struct wpas_dbus_priv *ctrl_iface; 3064 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3065 3066 /* Do nothing if the control interface is not turned on */ 3067 if (!wpa_s || !wpa_s->global) 3068 return 0; 3069 ctrl_iface = wpa_s->global->dbus; 3070 if (!ctrl_iface) 3071 return 0; 3072 3073 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3074 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, 3075 wpa_s->dbus_new_path, MAC2STR(sta)); 3076 3077 wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'", 3078 station_obj_path); 3079 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, 3080 station_obj_path)) { 3081 wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s", 3082 station_obj_path); 3083 return -1; 3084 } 3085 3086 wpas_dbus_signal_station_removed(wpa_s, station_obj_path); 3087 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS); 3088 3089 return 0; 3090 } 3091 3092 3093 /** 3094 * wpas_dbus_register_sta - Register a connected station with dbus 3095 * @wpa_s: wpa_supplicant interface structure 3096 * @sta: station MAC address 3097 * Returns: 0 on success, -1 on failure 3098 * 3099 * Registers STA representing object with dbus. 3100 */ 3101 int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta) 3102 { 3103 struct wpas_dbus_priv *ctrl_iface; 3104 struct wpa_dbus_object_desc *obj_desc; 3105 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3106 struct sta_handler_args *arg; 3107 3108 /* Do nothing if the control interface is not turned on */ 3109 if (!wpa_s || !wpa_s->global) 3110 return 0; 3111 ctrl_iface = wpa_s->global->dbus; 3112 if (!ctrl_iface) 3113 return 0; 3114 3115 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3116 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, 3117 wpa_s->dbus_new_path, MAC2STR(sta)); 3118 3119 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3120 if (!obj_desc) { 3121 wpa_printf(MSG_ERROR, 3122 "Not enough memory to create object description"); 3123 goto err; 3124 } 3125 3126 arg = os_zalloc(sizeof(struct sta_handler_args)); 3127 if (!arg) { 3128 wpa_printf(MSG_ERROR, 3129 "Not enough memory to create arguments for handler"); 3130 goto err; 3131 } 3132 arg->wpa_s = wpa_s; 3133 arg->sta = sta; 3134 3135 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 3136 wpas_dbus_sta_properties, wpas_dbus_sta_signals); 3137 3138 wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'", 3139 station_obj_path); 3140 if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path, 3141 wpa_s->ifname, obj_desc)) { 3142 wpa_printf(MSG_ERROR, 3143 "Cannot register STA dbus object %s", 3144 station_obj_path); 3145 goto err; 3146 } 3147 3148 wpas_dbus_signal_station_added(wpa_s, station_obj_path); 3149 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS); 3150 3151 return 0; 3152 3153 err: 3154 free_dbus_object_desc(obj_desc); 3155 return -1; 3156 } 3157 3158 3159 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { 3160 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE, 3161 (WPADBusMethodHandler) wpas_dbus_handler_scan, 3162 { 3163 { "args", "a{sv}", ARG_IN }, 3164 END_ARGS 3165 } 3166 }, 3167 { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE, 3168 (WPADBusMethodHandler) wpas_dbus_handler_signal_poll, 3169 { 3170 { "args", "a{sv}", ARG_OUT }, 3171 END_ARGS 3172 } 3173 }, 3174 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 3175 (WPADBusMethodHandler) wpas_dbus_handler_disconnect, 3176 { 3177 END_ARGS 3178 } 3179 }, 3180 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 3181 (WPADBusMethodHandler) wpas_dbus_handler_add_network, 3182 { 3183 { "args", "a{sv}", ARG_IN }, 3184 { "path", "o", ARG_OUT }, 3185 END_ARGS 3186 } 3187 }, 3188 { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE, 3189 (WPADBusMethodHandler) wpas_dbus_handler_reassociate, 3190 { 3191 END_ARGS 3192 } 3193 }, 3194 { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE, 3195 (WPADBusMethodHandler) wpas_dbus_handler_reattach, 3196 { 3197 END_ARGS 3198 } 3199 }, 3200 { "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 3201 (WPADBusMethodHandler) wpas_dbus_handler_reconnect, 3202 { 3203 END_ARGS 3204 } 3205 }, 3206 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 3207 (WPADBusMethodHandler) wpas_dbus_handler_remove_network, 3208 { 3209 { "path", "o", ARG_IN }, 3210 END_ARGS 3211 } 3212 }, 3213 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE, 3214 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks, 3215 { 3216 END_ARGS 3217 } 3218 }, 3219 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 3220 (WPADBusMethodHandler) wpas_dbus_handler_select_network, 3221 { 3222 { "path", "o", ARG_IN }, 3223 END_ARGS 3224 } 3225 }, 3226 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE, 3227 (WPADBusMethodHandler) wpas_dbus_handler_network_reply, 3228 { 3229 { "path", "o", ARG_IN }, 3230 { "field", "s", ARG_IN }, 3231 { "value", "s", ARG_IN }, 3232 END_ARGS 3233 } 3234 }, 3235 #ifndef CONFIG_NO_CONFIG_BLOBS 3236 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 3237 (WPADBusMethodHandler) wpas_dbus_handler_add_blob, 3238 { 3239 { "name", "s", ARG_IN }, 3240 { "data", "ay", ARG_IN }, 3241 END_ARGS 3242 } 3243 }, 3244 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 3245 (WPADBusMethodHandler) wpas_dbus_handler_get_blob, 3246 { 3247 { "name", "s", ARG_IN }, 3248 { "data", "ay", ARG_OUT }, 3249 END_ARGS 3250 } 3251 }, 3252 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 3253 (WPADBusMethodHandler) wpas_dbus_handler_remove_blob, 3254 { 3255 { "name", "s", ARG_IN }, 3256 END_ARGS 3257 } 3258 }, 3259 #endif /* CONFIG_NO_CONFIG_BLOBS */ 3260 { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, 3261 (WPADBusMethodHandler) 3262 wpas_dbus_handler_set_pkcs11_engine_and_module_path, 3263 { 3264 { "pkcs11_engine_path", "s", ARG_IN }, 3265 { "pkcs11_module_path", "s", ARG_IN }, 3266 END_ARGS 3267 } 3268 }, 3269 #ifdef CONFIG_WPS 3270 { "Start", WPAS_DBUS_NEW_IFACE_WPS, 3271 (WPADBusMethodHandler) wpas_dbus_handler_wps_start, 3272 { 3273 { "args", "a{sv}", ARG_IN }, 3274 { "output", "a{sv}", ARG_OUT }, 3275 END_ARGS 3276 } 3277 }, 3278 { "Cancel", WPAS_DBUS_NEW_IFACE_WPS, 3279 (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel, 3280 { 3281 END_ARGS 3282 } 3283 }, 3284 #endif /* CONFIG_WPS */ 3285 #ifdef CONFIG_P2P 3286 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3287 (WPADBusMethodHandler) wpas_dbus_handler_p2p_find, 3288 { 3289 { "args", "a{sv}", ARG_IN }, 3290 END_ARGS 3291 } 3292 }, 3293 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3294 (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find, 3295 { 3296 END_ARGS 3297 } 3298 }, 3299 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3300 (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen, 3301 { 3302 { "timeout", "i", ARG_IN }, 3303 END_ARGS 3304 } 3305 }, 3306 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3307 (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten, 3308 { 3309 { "args", "a{sv}", ARG_IN }, 3310 END_ARGS 3311 } 3312 }, 3313 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3314 (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request, 3315 { 3316 { "args", "a{sv}", ARG_IN }, 3317 END_ARGS 3318 } 3319 }, 3320 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3321 (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req, 3322 { 3323 { "peer", "o", ARG_IN }, 3324 { "config_method", "s", ARG_IN }, 3325 END_ARGS 3326 } 3327 }, 3328 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3329 (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect, 3330 { 3331 { "args", "a{sv}", ARG_IN }, 3332 { "generated_pin", "s", ARG_OUT }, 3333 END_ARGS 3334 } 3335 }, 3336 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3337 (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add, 3338 { 3339 { "args", "a{sv}", ARG_IN }, 3340 END_ARGS 3341 } 3342 }, 3343 { "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3344 (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel, 3345 { 3346 END_ARGS 3347 } 3348 }, 3349 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3350 (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite, 3351 { 3352 { "args", "a{sv}", ARG_IN }, 3353 END_ARGS 3354 } 3355 }, 3356 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3357 (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect, 3358 { 3359 END_ARGS 3360 } 3361 }, 3362 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3363 (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer, 3364 { 3365 { "peer", "o", ARG_IN }, 3366 END_ARGS 3367 } 3368 }, 3369 { "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3370 (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client, 3371 { 3372 { "args", "a{sv}", ARG_IN }, 3373 END_ARGS 3374 } 3375 }, 3376 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3377 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush, 3378 { 3379 END_ARGS 3380 } 3381 }, 3382 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3383 (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service, 3384 { 3385 { "args", "a{sv}", ARG_IN }, 3386 END_ARGS 3387 } 3388 }, 3389 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3390 (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service, 3391 { 3392 { "args", "a{sv}", ARG_IN }, 3393 END_ARGS 3394 } 3395 }, 3396 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3397 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service, 3398 { 3399 END_ARGS 3400 } 3401 }, 3402 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3403 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req, 3404 { 3405 { "args", "a{sv}", ARG_IN }, 3406 { "ref", "t", ARG_OUT }, 3407 END_ARGS 3408 } 3409 }, 3410 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3411 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res, 3412 { 3413 { "args", "a{sv}", ARG_IN }, 3414 END_ARGS 3415 } 3416 }, 3417 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3418 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req, 3419 { 3420 { "args", "t", ARG_IN }, 3421 END_ARGS 3422 } 3423 }, 3424 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3425 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update, 3426 { 3427 END_ARGS 3428 } 3429 }, 3430 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3431 (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external, 3432 { 3433 { "arg", "i", ARG_IN }, 3434 END_ARGS 3435 } 3436 }, 3437 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3438 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group, 3439 { 3440 { "args", "a{sv}", ARG_IN }, 3441 { "path", "o", ARG_OUT }, 3442 END_ARGS 3443 } 3444 }, 3445 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3446 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group, 3447 { 3448 { "path", "o", ARG_IN }, 3449 END_ARGS 3450 } 3451 }, 3452 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3453 (WPADBusMethodHandler) 3454 wpas_dbus_handler_remove_all_persistent_groups, 3455 { 3456 END_ARGS 3457 } 3458 }, 3459 #endif /* CONFIG_P2P */ 3460 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, 3461 (WPADBusMethodHandler) wpas_dbus_handler_flush_bss, 3462 { 3463 { "age", "u", ARG_IN }, 3464 END_ARGS 3465 } 3466 }, 3467 #ifdef CONFIG_AP 3468 { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 3469 (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq, 3470 { 3471 END_ARGS 3472 } 3473 }, 3474 { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 3475 (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq, 3476 { 3477 END_ARGS 3478 } 3479 }, 3480 #endif /* CONFIG_AP */ 3481 { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE, 3482 (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff, 3483 { 3484 END_ARGS 3485 } 3486 }, 3487 { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE, 3488 (WPADBusMethodHandler) wpas_dbus_handler_eap_logon, 3489 { 3490 END_ARGS 3491 } 3492 }, 3493 #ifdef CONFIG_AUTOSCAN 3494 { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE, 3495 (WPADBusMethodHandler) wpas_dbus_handler_autoscan, 3496 { 3497 { "arg", "s", ARG_IN }, 3498 END_ARGS 3499 } 3500 }, 3501 #endif /* CONFIG_AUTOSCAN */ 3502 #ifdef CONFIG_TDLS 3503 { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE, 3504 (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover, 3505 { 3506 { "peer_address", "s", ARG_IN }, 3507 END_ARGS 3508 } 3509 }, 3510 { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE, 3511 (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup, 3512 { 3513 { "peer_address", "s", ARG_IN }, 3514 END_ARGS 3515 } 3516 }, 3517 { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, 3518 (WPADBusMethodHandler) wpas_dbus_handler_tdls_status, 3519 { 3520 { "peer_address", "s", ARG_IN }, 3521 { "status", "s", ARG_OUT }, 3522 END_ARGS 3523 } 3524 }, 3525 { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE, 3526 (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown, 3527 { 3528 { "peer_address", "s", ARG_IN }, 3529 END_ARGS 3530 } 3531 }, 3532 { "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE, 3533 (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch, 3534 { 3535 { "args", "a{sv}", ARG_IN }, 3536 END_ARGS 3537 } 3538 }, 3539 { "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE, 3540 (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch, 3541 { 3542 { "peer_address", "s", ARG_IN }, 3543 END_ARGS 3544 } 3545 }, 3546 #endif /* CONFIG_TDLS */ 3547 { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE, 3548 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add, 3549 { 3550 { "frame_id", "i", ARG_IN }, 3551 { "ielems", "ay", ARG_IN }, 3552 END_ARGS 3553 } 3554 }, 3555 { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE, 3556 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get, 3557 { 3558 { "frame_id", "i", ARG_IN }, 3559 { "ielems", "ay", ARG_OUT }, 3560 END_ARGS 3561 } 3562 }, 3563 { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE, 3564 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove, 3565 { 3566 { "frame_id", "i", ARG_IN }, 3567 { "ielems", "ay", ARG_IN }, 3568 END_ARGS 3569 } 3570 }, 3571 #ifndef CONFIG_NO_CONFIG_WRITE 3572 { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE, 3573 (WPADBusMethodHandler) wpas_dbus_handler_save_config, 3574 { 3575 END_ARGS 3576 } 3577 }, 3578 #endif /* CONFIG_NO_CONFIG_WRITE */ 3579 { "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE, 3580 (WPADBusMethodHandler) wpas_dbus_handler_abort_scan, 3581 { 3582 END_ARGS 3583 } 3584 }, 3585 { NULL, NULL, NULL, { END_ARGS } } 3586 }; 3587 3588 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { 3589 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}", 3590 wpas_dbus_getter_capabilities, 3591 NULL, 3592 NULL 3593 }, 3594 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3595 wpas_dbus_getter_state, 3596 NULL, 3597 NULL 3598 }, 3599 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 3600 wpas_dbus_getter_scanning, 3601 NULL, 3602 NULL 3603 }, 3604 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3605 wpas_dbus_getter_ap_scan, 3606 wpas_dbus_setter_ap_scan, 3607 NULL 3608 }, 3609 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3610 wpas_dbus_getter_bss_expire_age, 3611 wpas_dbus_setter_bss_expire_age, 3612 NULL 3613 }, 3614 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3615 wpas_dbus_getter_bss_expire_count, 3616 wpas_dbus_setter_bss_expire_count, 3617 NULL 3618 }, 3619 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3620 wpas_dbus_getter_country, 3621 wpas_dbus_setter_country, 3622 NULL 3623 }, 3624 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3625 wpas_dbus_getter_ifname, 3626 NULL, 3627 NULL 3628 }, 3629 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3630 wpas_dbus_getter_driver, 3631 NULL, 3632 NULL 3633 }, 3634 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3635 wpas_dbus_getter_bridge_ifname, 3636 NULL, 3637 NULL 3638 }, 3639 { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3640 wpas_dbus_getter_config_file, 3641 NULL, 3642 NULL 3643 }, 3644 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 3645 wpas_dbus_getter_current_bss, 3646 NULL, 3647 NULL 3648 }, 3649 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 3650 wpas_dbus_getter_current_network, 3651 NULL, 3652 NULL 3653 }, 3654 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3655 wpas_dbus_getter_current_auth_mode, 3656 NULL, 3657 NULL 3658 }, 3659 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}", 3660 wpas_dbus_getter_blobs, 3661 NULL, 3662 NULL 3663 }, 3664 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 3665 wpas_dbus_getter_bsss, 3666 NULL, 3667 NULL 3668 }, 3669 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 3670 wpas_dbus_getter_networks, 3671 NULL, 3672 NULL 3673 }, 3674 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 3675 wpas_dbus_getter_fast_reauth, 3676 wpas_dbus_setter_fast_reauth, 3677 NULL 3678 }, 3679 { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3680 wpas_dbus_getter_scan_interval, 3681 wpas_dbus_setter_scan_interval, 3682 NULL 3683 }, 3684 { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3685 wpas_dbus_getter_pkcs11_engine_path, 3686 NULL, 3687 NULL 3688 }, 3689 { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3690 wpas_dbus_getter_pkcs11_module_path, 3691 NULL, 3692 NULL 3693 }, 3694 #ifdef CONFIG_WPS 3695 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b", 3696 wpas_dbus_getter_process_credentials, 3697 wpas_dbus_setter_process_credentials, 3698 NULL 3699 }, 3700 { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s", 3701 wpas_dbus_getter_config_methods, 3702 wpas_dbus_setter_config_methods, 3703 NULL 3704 }, 3705 { 3706 "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s", 3707 wpas_dbus_getter_wps_device_name, 3708 wpas_dbus_setter_wps_device_name, 3709 NULL 3710 }, 3711 { 3712 "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s", 3713 wpas_dbus_getter_wps_manufacturer, 3714 wpas_dbus_setter_wps_manufacturer, 3715 NULL 3716 }, 3717 { 3718 "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s", 3719 wpas_dbus_getter_wps_device_model_name, 3720 wpas_dbus_setter_wps_device_model_name, 3721 NULL 3722 }, 3723 { 3724 "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s", 3725 wpas_dbus_getter_wps_device_model_number, 3726 wpas_dbus_setter_wps_device_model_number, 3727 NULL 3728 }, 3729 { 3730 "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s", 3731 wpas_dbus_getter_wps_device_serial_number, 3732 wpas_dbus_setter_wps_device_serial_number, 3733 NULL 3734 }, 3735 { 3736 "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay", 3737 wpas_dbus_getter_wps_device_device_type, 3738 wpas_dbus_setter_wps_device_device_type, 3739 NULL 3740 }, 3741 #endif /* CONFIG_WPS */ 3742 #ifdef CONFIG_P2P 3743 { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}", 3744 wpas_dbus_getter_p2p_device_config, 3745 wpas_dbus_setter_p2p_device_config, 3746 NULL 3747 }, 3748 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 3749 wpas_dbus_getter_p2p_peers, 3750 NULL, 3751 NULL 3752 }, 3753 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s", 3754 wpas_dbus_getter_p2p_role, 3755 NULL, 3756 NULL 3757 }, 3758 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 3759 wpas_dbus_getter_p2p_group, 3760 NULL, 3761 NULL 3762 }, 3763 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 3764 wpas_dbus_getter_p2p_peergo, 3765 NULL, 3766 NULL 3767 }, 3768 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 3769 wpas_dbus_getter_persistent_groups, 3770 NULL, 3771 NULL 3772 }, 3773 #endif /* CONFIG_P2P */ 3774 { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3775 wpas_dbus_getter_disconnect_reason, 3776 NULL, 3777 NULL 3778 }, 3779 { "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3780 wpas_dbus_getter_auth_status_code, 3781 NULL, 3782 NULL 3783 }, 3784 { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3785 wpas_dbus_getter_assoc_status_code, 3786 NULL, 3787 NULL 3788 }, 3789 #ifdef CONFIG_MESH 3790 { "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay", 3791 wpas_dbus_getter_mesh_peers, 3792 NULL, 3793 NULL 3794 }, 3795 { "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay", 3796 wpas_dbus_getter_mesh_group, 3797 NULL, 3798 NULL 3799 }, 3800 #endif /* CONFIG_MESH */ 3801 { "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 3802 wpas_dbus_getter_stas, 3803 NULL, 3804 NULL 3805 }, 3806 { NULL, NULL, NULL, NULL, NULL, NULL } 3807 }; 3808 3809 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { 3810 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE, 3811 { 3812 { "success", "b", ARG_OUT }, 3813 END_ARGS 3814 } 3815 }, 3816 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3817 { 3818 { "path", "o", ARG_OUT }, 3819 { "properties", "a{sv}", ARG_OUT }, 3820 END_ARGS 3821 } 3822 }, 3823 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3824 { 3825 { "path", "o", ARG_OUT }, 3826 END_ARGS 3827 } 3828 }, 3829 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3830 { 3831 { "name", "s", ARG_OUT }, 3832 END_ARGS 3833 } 3834 }, 3835 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3836 { 3837 { "name", "s", ARG_OUT }, 3838 END_ARGS 3839 } 3840 }, 3841 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3842 { 3843 { "path", "o", ARG_OUT }, 3844 { "properties", "a{sv}", ARG_OUT }, 3845 END_ARGS 3846 } 3847 }, 3848 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3849 { 3850 { "path", "o", ARG_OUT }, 3851 END_ARGS 3852 } 3853 }, 3854 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE, 3855 { 3856 { "path", "o", ARG_OUT }, 3857 END_ARGS 3858 } 3859 }, 3860 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3861 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE, 3862 { 3863 { "properties", "a{sv}", ARG_OUT }, 3864 END_ARGS 3865 } 3866 }, 3867 #ifdef CONFIG_WPS 3868 { "Event", WPAS_DBUS_NEW_IFACE_WPS, 3869 { 3870 { "name", "s", ARG_OUT }, 3871 { "args", "a{sv}", ARG_OUT }, 3872 END_ARGS 3873 } 3874 }, 3875 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS, 3876 { 3877 { "credentials", "a{sv}", ARG_OUT }, 3878 END_ARGS 3879 } 3880 }, 3881 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3882 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS, 3883 { 3884 { "properties", "a{sv}", ARG_OUT }, 3885 END_ARGS 3886 } 3887 }, 3888 #endif /* CONFIG_WPS */ 3889 #ifdef CONFIG_P2P 3890 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3891 { 3892 { "path", "o", ARG_OUT }, 3893 END_ARGS 3894 } 3895 }, 3896 { "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3897 { 3898 { "path", "o", ARG_OUT }, 3899 { "properties", "a{sv}", ARG_OUT }, 3900 END_ARGS 3901 } 3902 }, 3903 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3904 { 3905 { "path", "o", ARG_OUT }, 3906 END_ARGS 3907 } 3908 }, 3909 { "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3910 { 3911 END_ARGS 3912 } 3913 }, 3914 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3915 { 3916 { "peer_object", "o", ARG_OUT }, 3917 { "pin", "s", ARG_OUT }, 3918 END_ARGS 3919 } 3920 }, 3921 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3922 { 3923 { "peer_object", "o", ARG_OUT }, 3924 { "pin", "s", ARG_OUT }, 3925 END_ARGS 3926 } 3927 }, 3928 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3929 { 3930 { "peer_object", "o", ARG_OUT }, 3931 END_ARGS 3932 } 3933 }, 3934 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3935 { 3936 { "peer_object", "o", ARG_OUT }, 3937 END_ARGS 3938 } 3939 }, 3940 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3941 { 3942 { "peer_object", "o", ARG_OUT }, 3943 END_ARGS 3944 } 3945 }, 3946 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3947 { 3948 { "peer_object", "o", ARG_OUT }, 3949 END_ARGS 3950 } 3951 }, 3952 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3953 { 3954 { "peer_object", "o", ARG_OUT }, 3955 { "status", "i", ARG_OUT }, 3956 END_ARGS 3957 } 3958 }, 3959 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3960 { 3961 { "properties", "a{sv}", ARG_OUT }, 3962 END_ARGS 3963 } 3964 }, 3965 { "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3966 { 3967 { "reason", "s", ARG_OUT }, 3968 END_ARGS 3969 } 3970 }, 3971 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3972 { 3973 { "properties", "a{sv}", ARG_OUT }, 3974 END_ARGS 3975 } 3976 }, 3977 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3978 { 3979 { "properties", "a{sv}", ARG_OUT }, 3980 END_ARGS 3981 } 3982 }, 3983 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3984 { 3985 { "path", "o", ARG_OUT }, 3986 { "dev_passwd_id", "q", ARG_OUT }, 3987 { "device_go_intent", "y", ARG_OUT }, 3988 END_ARGS 3989 } 3990 }, 3991 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3992 { 3993 { "invite_result", "a{sv}", ARG_OUT }, 3994 END_ARGS 3995 } 3996 }, 3997 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3998 { 3999 { "properties", "a{sv}", ARG_OUT }, 4000 END_ARGS 4001 } 4002 }, 4003 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4004 { 4005 { "sd_request", "a{sv}", ARG_OUT }, 4006 END_ARGS 4007 } 4008 }, 4009 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4010 { 4011 { "sd_response", "a{sv}", ARG_OUT }, 4012 END_ARGS 4013 } 4014 }, 4015 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4016 { 4017 { "path", "o", ARG_OUT }, 4018 { "properties", "a{sv}", ARG_OUT }, 4019 END_ARGS 4020 } 4021 }, 4022 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4023 { 4024 { "path", "o", ARG_OUT }, 4025 END_ARGS 4026 } 4027 }, 4028 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4029 { 4030 { "name", "s", ARG_OUT }, 4031 { "args", "a{sv}", ARG_OUT }, 4032 END_ARGS 4033 } 4034 }, 4035 { "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4036 { 4037 { "properties", "a{sv}", ARG_OUT }, 4038 END_ARGS 4039 } 4040 }, 4041 #endif /* CONFIG_P2P */ 4042 #ifdef CONFIG_AP 4043 { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 4044 { 4045 { "args", "a{sv}", ARG_OUT }, 4046 END_ARGS 4047 } 4048 }, 4049 #endif /* CONFIG_AP */ 4050 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE, 4051 { 4052 { "certification", "a{sv}", ARG_OUT }, 4053 END_ARGS 4054 } 4055 }, 4056 { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE, 4057 { 4058 { "status", "s", ARG_OUT }, 4059 { "parameter", "s", ARG_OUT }, 4060 END_ARGS 4061 } 4062 }, 4063 { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE, 4064 { 4065 { "name", "s", ARG_OUT }, 4066 END_ARGS 4067 } 4068 }, 4069 { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE, 4070 { 4071 { "name", "s", ARG_OUT }, 4072 END_ARGS 4073 } 4074 }, 4075 { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 4076 { 4077 { "path", "o", ARG_OUT }, 4078 { "properties", "a{sv}", ARG_OUT }, 4079 END_ARGS 4080 } 4081 }, 4082 { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 4083 { 4084 { "path", "o", ARG_OUT }, 4085 END_ARGS 4086 } 4087 }, 4088 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 4089 { 4090 { "path", "o", ARG_OUT }, 4091 { "field", "s", ARG_OUT }, 4092 { "text", "s", ARG_OUT }, 4093 END_ARGS 4094 } 4095 }, 4096 #ifdef CONFIG_MESH 4097 { "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH, 4098 { 4099 { "args", "a{sv}", ARG_OUT }, 4100 END_ARGS 4101 } 4102 }, 4103 { "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH, 4104 { 4105 { "args", "a{sv}", ARG_OUT }, 4106 END_ARGS 4107 } 4108 }, 4109 { "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH, 4110 { 4111 { "args", "a{sv}", ARG_OUT }, 4112 END_ARGS 4113 } 4114 }, 4115 { "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH, 4116 { 4117 { "args", "a{sv}", ARG_OUT }, 4118 END_ARGS 4119 } 4120 }, 4121 #endif /* CONFIG_MESH */ 4122 { NULL, NULL, { END_ARGS } } 4123 }; 4124 4125 4126 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv) 4127 { 4128 size_t all_size; 4129 unsigned int i, j, count, num_const, num_globals; 4130 const char *global_name; 4131 static const char * const ignored_globals[] = { 4132 "bss_expiration_age", "bss_expiration_scan_count", 4133 "ap_scan", "country", "fast_reauth", 4134 "pkcs11_engine_path", "pkcs11_module_path" 4135 }; 4136 4137 /* wpas_dbus_interface_properties terminates with a NULL element */ 4138 num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1; 4139 4140 num_globals = wpa_config_get_num_global_field_names(); 4141 priv->globals_start = num_const; 4142 4143 /* allocate enough for all properties + terminating NULL element */ 4144 all_size = (num_globals + num_const + 1) * 4145 sizeof(wpas_dbus_interface_properties[0]); 4146 priv->all_interface_properties = os_zalloc(all_size); 4147 if (!priv->all_interface_properties) { 4148 wpa_printf(MSG_ERROR, 4149 "dbus: Not enough memory for interface properties"); 4150 return -1; 4151 } 4152 4153 /* Copy constant interface properties to the start of the array */ 4154 os_memcpy(priv->all_interface_properties, 4155 wpas_dbus_interface_properties, 4156 sizeof(wpas_dbus_interface_properties)); 4157 4158 /* Dynamically construct interface global properties */ 4159 for (i = 0, count = num_const; i < num_globals; i++) { 4160 struct wpa_dbus_property_desc *desc; 4161 int no_var = 0; 4162 4163 /* ignore globals that are actually just methods */ 4164 global_name = wpa_config_get_global_field_name(i, &no_var); 4165 if (no_var) 4166 continue; 4167 /* Ignore fields already explicitly exposed */ 4168 for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) { 4169 if (os_strcmp(global_name, ignored_globals[j]) == 0) 4170 break; 4171 } 4172 if (j < ARRAY_SIZE(ignored_globals)) 4173 continue; 4174 4175 desc = &priv->all_interface_properties[count++]; 4176 desc->dbus_property = uscore_to_dbus(global_name); 4177 if (!desc->dbus_property) { 4178 wpa_printf(MSG_ERROR, 4179 "dbus: Not enough memory for D-Bus property name"); 4180 goto error; 4181 } 4182 desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE; 4183 desc->type = "s"; 4184 desc->getter = wpas_dbus_getter_iface_global; 4185 desc->setter = wpas_dbus_setter_iface_global; 4186 desc->data = global_name; 4187 } 4188 4189 return 0; 4190 4191 error: 4192 wpa_dbus_ctrl_iface_props_deinit(priv); 4193 return -1; 4194 } 4195 4196 4197 /** 4198 * wpas_dbus_register_interface - Register an interface with D-Bus 4199 * @wpa_s: wpa_supplicant interface structure 4200 * Returns: 0 on success, -1 on failure 4201 */ 4202 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s) 4203 { 4204 struct wpa_dbus_object_desc *obj_desc = NULL; 4205 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus; 4206 int next; 4207 4208 /* Do nothing if the control interface is not turned on */ 4209 if (ctrl_iface == NULL) 4210 return 0; 4211 4212 /* Create and set the interface's object path */ 4213 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 4214 if (wpa_s->dbus_new_path == NULL) 4215 return -1; 4216 next = ctrl_iface->next_objid++; 4217 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX, 4218 WPAS_DBUS_NEW_PATH_INTERFACES "/%u", 4219 next); 4220 4221 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 4222 if (!obj_desc) { 4223 wpa_printf(MSG_ERROR, 4224 "Not enough memory to create object description"); 4225 goto err; 4226 } 4227 4228 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods, 4229 ctrl_iface->all_interface_properties, 4230 wpas_dbus_interface_signals); 4231 4232 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", 4233 wpa_s->dbus_new_path); 4234 if (wpa_dbus_register_object_per_iface(ctrl_iface, 4235 wpa_s->dbus_new_path, 4236 wpa_s->ifname, obj_desc)) 4237 goto err; 4238 4239 wpas_dbus_signal_interface_added(wpa_s); 4240 4241 return 0; 4242 4243 err: 4244 os_free(wpa_s->dbus_new_path); 4245 wpa_s->dbus_new_path = NULL; 4246 free_dbus_object_desc(obj_desc); 4247 return -1; 4248 } 4249 4250 4251 /** 4252 * wpas_dbus_unregister_interface - Unregister the interface from D-Bus 4253 * @wpa_s: wpa_supplicant interface structure 4254 * Returns: 0 on success, -1 on failure 4255 */ 4256 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s) 4257 { 4258 struct wpas_dbus_priv *ctrl_iface; 4259 4260 /* Do nothing if the control interface is not turned on */ 4261 if (wpa_s == NULL || wpa_s->global == NULL) 4262 return 0; 4263 ctrl_iface = wpa_s->global->dbus; 4264 if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL) 4265 return 0; 4266 4267 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'", 4268 wpa_s->dbus_new_path); 4269 4270 #ifdef CONFIG_AP 4271 if (wpa_s->preq_notify_peer) { 4272 wpas_dbus_unsubscribe_noc(ctrl_iface); 4273 os_free(wpa_s->preq_notify_peer); 4274 wpa_s->preq_notify_peer = NULL; 4275 } 4276 #endif /* CONFIG_AP */ 4277 4278 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, 4279 wpa_s->dbus_new_path)) 4280 return -1; 4281 4282 wpas_dbus_signal_interface_removed(wpa_s); 4283 4284 os_free(wpa_s->dbus_new_path); 4285 wpa_s->dbus_new_path = NULL; 4286 4287 return 0; 4288 } 4289 4290 #ifdef CONFIG_P2P 4291 4292 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = { 4293 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4294 wpas_dbus_getter_p2p_peer_device_name, 4295 NULL, 4296 NULL 4297 }, 4298 { "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4299 wpas_dbus_getter_p2p_peer_manufacturer, 4300 NULL, 4301 NULL 4302 }, 4303 { "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4304 wpas_dbus_getter_p2p_peer_modelname, 4305 NULL, 4306 NULL 4307 }, 4308 { "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4309 wpas_dbus_getter_p2p_peer_modelnumber, 4310 NULL, 4311 NULL 4312 }, 4313 { "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4314 wpas_dbus_getter_p2p_peer_serialnumber, 4315 NULL, 4316 NULL 4317 }, 4318 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4319 wpas_dbus_getter_p2p_peer_primary_device_type, 4320 NULL, 4321 NULL 4322 }, 4323 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q", 4324 wpas_dbus_getter_p2p_peer_config_method, 4325 NULL, 4326 NULL 4327 }, 4328 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i", 4329 wpas_dbus_getter_p2p_peer_level, 4330 NULL, 4331 NULL 4332 }, 4333 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 4334 wpas_dbus_getter_p2p_peer_device_capability, 4335 NULL, 4336 NULL 4337 }, 4338 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 4339 wpas_dbus_getter_p2p_peer_group_capability, 4340 NULL, 4341 NULL 4342 }, 4343 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 4344 wpas_dbus_getter_p2p_peer_secondary_device_types, 4345 NULL, 4346 NULL 4347 }, 4348 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 4349 wpas_dbus_getter_p2p_peer_vendor_extension, 4350 NULL, 4351 NULL 4352 }, 4353 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4354 wpas_dbus_getter_p2p_peer_ies, 4355 NULL, 4356 NULL 4357 }, 4358 { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4359 wpas_dbus_getter_p2p_peer_device_address, 4360 NULL, 4361 NULL 4362 }, 4363 { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao", 4364 wpas_dbus_getter_p2p_peer_groups, 4365 NULL, 4366 NULL 4367 }, 4368 { "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4369 wpas_dbus_getter_p2p_peer_vsie, 4370 NULL, 4371 NULL 4372 }, 4373 { NULL, NULL, NULL, NULL, NULL, NULL } 4374 }; 4375 4376 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = { 4377 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 4378 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER, 4379 { 4380 { "properties", "a{sv}", ARG_OUT }, 4381 END_ARGS 4382 } 4383 }, 4384 { NULL, NULL, { END_ARGS } } 4385 }; 4386 4387 /** 4388 * wpas_dbus_signal_peer - Send a peer related event signal 4389 * @wpa_s: %wpa_supplicant network interface data 4390 * @dev: peer device object 4391 * @interface: name of the interface emitting this signal. 4392 * In case of peer objects, it would be emitted by either 4393 * the "interface object" or by "peer objects" 4394 * @sig_name: signal name - DeviceFound 4395 * @properties: Whether to add a second argument with object properties 4396 * 4397 * Notify listeners about event related with p2p peer device 4398 */ 4399 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s, 4400 const u8 *dev_addr, const char *interface, 4401 const char *sig_name, dbus_bool_t properties) 4402 { 4403 struct wpas_dbus_priv *iface; 4404 DBusMessage *msg; 4405 DBusMessageIter iter; 4406 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 4407 4408 if (wpa_s->p2p_mgmt) 4409 wpa_s = wpa_s->parent; 4410 4411 iface = wpa_s->global->dbus; 4412 4413 /* Do nothing if the control interface is not turned on */ 4414 if (iface == NULL || !wpa_s->dbus_new_path) 4415 return; 4416 4417 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4418 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4419 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4420 4421 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface, 4422 sig_name); 4423 if (msg == NULL) 4424 return; 4425 4426 dbus_message_iter_init_append(msg, &iter); 4427 path = peer_obj_path; 4428 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 4429 &path) || 4430 (properties && !wpa_dbus_get_object_properties( 4431 iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER, 4432 &iter))) 4433 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 4434 else 4435 dbus_connection_send(iface->con, msg, NULL); 4436 4437 dbus_message_unref(msg); 4438 } 4439 4440 4441 /** 4442 * wpas_dbus_signal_peer_found - Send a peer found signal 4443 * @wpa_s: %wpa_supplicant network interface data 4444 * @dev_addr: Peer P2P Device Address 4445 * 4446 * Notify listeners about find a p2p peer device found 4447 */ 4448 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s, 4449 const u8 *dev_addr) 4450 { 4451 wpas_dbus_signal_peer(wpa_s, dev_addr, 4452 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4453 "DeviceFound", FALSE); 4454 4455 wpas_dbus_signal_peer(wpa_s, dev_addr, 4456 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4457 "DeviceFoundProperties", TRUE); 4458 } 4459 4460 /** 4461 * wpas_dbus_signal_peer_lost - Send a peer lost signal 4462 * @wpa_s: %wpa_supplicant network interface data 4463 * @dev_addr: Peer P2P Device Address 4464 * 4465 * Notify listeners about lost a p2p peer device 4466 */ 4467 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s, 4468 const u8 *dev_addr) 4469 { 4470 wpas_dbus_signal_peer(wpa_s, dev_addr, 4471 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4472 "DeviceLost", FALSE); 4473 } 4474 4475 /** 4476 * wpas_dbus_register_peer - Register a discovered peer object with dbus 4477 * @wpa_s: wpa_supplicant interface structure 4478 * @dev_addr: P2P Device Address of the peer 4479 * Returns: 0 on success, -1 on failure 4480 * 4481 * Registers network representing object with dbus 4482 */ 4483 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr) 4484 { 4485 struct wpas_dbus_priv *ctrl_iface; 4486 struct wpa_dbus_object_desc *obj_desc; 4487 struct peer_handler_args *arg; 4488 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4489 4490 /* Do nothing if the control interface is not turned on */ 4491 if (wpa_s == NULL || wpa_s->global == NULL) 4492 return 0; 4493 4494 ctrl_iface = wpa_s->global->dbus; 4495 if (ctrl_iface == NULL) 4496 return 0; 4497 4498 wpa_s = wpa_s->parent->parent; 4499 if (!wpa_s->dbus_new_path) 4500 return 0; 4501 4502 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4503 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4504 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4505 4506 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'", 4507 peer_obj_path); 4508 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 4509 if (!obj_desc) { 4510 wpa_printf(MSG_ERROR, 4511 "Not enough memory to create object description"); 4512 goto err; 4513 } 4514 4515 /* allocate memory for handlers arguments */ 4516 arg = os_zalloc(sizeof(struct peer_handler_args)); 4517 if (!arg) { 4518 wpa_printf(MSG_ERROR, 4519 "Not enough memory to create arguments for method"); 4520 goto err; 4521 } 4522 4523 arg->wpa_s = wpa_s; 4524 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN); 4525 4526 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, 4527 NULL, 4528 wpas_dbus_p2p_peer_properties, 4529 wpas_dbus_p2p_peer_signals); 4530 4531 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path, 4532 wpa_s->ifname, obj_desc)) 4533 goto err; 4534 4535 return 0; 4536 4537 err: 4538 free_dbus_object_desc(obj_desc); 4539 return -1; 4540 } 4541 4542 /** 4543 * wpas_dbus_unregister_peer - Unregister a peer object with dbus 4544 * @wpa_s: wpa_supplicant interface structure 4545 * @dev_addr: p2p device addr 4546 * Returns: 0 on success, -1 on failure 4547 * 4548 * Registers network representing object with dbus 4549 */ 4550 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s, 4551 const u8 *dev_addr) 4552 { 4553 struct wpas_dbus_priv *ctrl_iface; 4554 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4555 int ret; 4556 4557 /* Do nothing if the control interface is not turned on */ 4558 if (wpa_s == NULL || wpa_s->global == NULL) 4559 return 0; 4560 4561 wpa_s = wpa_s->parent->parent; 4562 if (!wpa_s->dbus_new_path) 4563 return 0; 4564 4565 ctrl_iface = wpa_s->global->dbus; 4566 if (ctrl_iface == NULL) 4567 return 0; 4568 4569 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4570 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4571 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4572 4573 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'", 4574 peer_obj_path); 4575 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path); 4576 4577 return ret; 4578 } 4579 4580 4581 /** 4582 * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal 4583 * @wpa_s: %wpa_supplicant network interface data 4584 * 4585 * Notify listeners about P2P Find stopped 4586 */ 4587 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s) 4588 { 4589 struct wpas_dbus_priv *iface; 4590 DBusMessage *msg; 4591 4592 iface = wpa_s->global->dbus; 4593 4594 /* Do nothing if the control interface is not turned on */ 4595 if (iface == NULL) 4596 return; 4597 4598 if (wpa_s->p2p_mgmt) 4599 wpa_s = wpa_s->parent; 4600 4601 if (!wpa_s->dbus_new_path) 4602 return; 4603 4604 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 4605 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4606 "FindStopped"); 4607 if (msg == NULL) 4608 return; 4609 4610 dbus_connection_send(iface->con, msg, NULL); 4611 4612 dbus_message_unref(msg); 4613 } 4614 4615 4616 /** 4617 * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal 4618 * @wpa_s: %wpa_supplicant network interface data 4619 * @dev_addr: P2P Device Address 4620 * 4621 * Notify listeners about peer Groups property changes. 4622 */ 4623 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s, 4624 const u8 *dev_addr) 4625 { 4626 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4627 4628 if (wpa_s->p2p_mgmt) 4629 wpa_s = wpa_s->parent; 4630 4631 if (!wpa_s->dbus_new_path) 4632 return; 4633 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4634 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4635 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4636 4637 wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path, 4638 WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups"); 4639 } 4640 4641 4642 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = { 4643 { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao", 4644 wpas_dbus_getter_p2p_group_members, 4645 NULL, 4646 NULL 4647 }, 4648 { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o", 4649 wpas_dbus_getter_p2p_group, 4650 NULL, 4651 NULL 4652 }, 4653 { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", 4654 wpas_dbus_getter_p2p_role, 4655 NULL, 4656 NULL 4657 }, 4658 { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 4659 wpas_dbus_getter_p2p_group_ssid, 4660 NULL, 4661 NULL 4662 }, 4663 { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 4664 wpas_dbus_getter_p2p_group_bssid, 4665 NULL, 4666 NULL 4667 }, 4668 { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q", 4669 wpas_dbus_getter_p2p_group_frequency, 4670 NULL, 4671 NULL 4672 }, 4673 { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", 4674 wpas_dbus_getter_p2p_group_passphrase, 4675 NULL, 4676 NULL 4677 }, 4678 { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 4679 wpas_dbus_getter_p2p_group_psk, 4680 NULL, 4681 NULL 4682 }, 4683 { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay", 4684 wpas_dbus_getter_p2p_group_vendor_ext, 4685 wpas_dbus_setter_p2p_group_vendor_ext, 4686 NULL 4687 }, 4688 { NULL, NULL, NULL, NULL, NULL, NULL } 4689 }; 4690 4691 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = { 4692 { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP, 4693 { 4694 { "peer", "o", ARG_OUT }, 4695 END_ARGS 4696 } 4697 }, 4698 { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP, 4699 { 4700 { "peer", "o", ARG_OUT }, 4701 END_ARGS 4702 } 4703 }, 4704 { NULL, NULL, { END_ARGS } } 4705 }; 4706 4707 /** 4708 * wpas_dbus_register_p2p_group - Register a p2p group object with dbus 4709 * @wpa_s: wpa_supplicant interface structure 4710 * @ssid: SSID struct 4711 * Returns: 0 on success, -1 on failure 4712 * 4713 * Registers p2p group representing object with dbus 4714 */ 4715 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s, 4716 struct wpa_ssid *ssid) 4717 { 4718 struct wpas_dbus_priv *ctrl_iface; 4719 struct wpa_dbus_object_desc *obj_desc; 4720 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4721 4722 /* Do nothing if the control interface is not turned on */ 4723 if (wpa_s == NULL || wpa_s->global == NULL) 4724 return; 4725 4726 ctrl_iface = wpa_s->global->dbus; 4727 if (ctrl_iface == NULL) 4728 return; 4729 4730 if (wpa_s->dbus_groupobj_path) { 4731 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists", 4732 __func__, wpa_s->dbus_groupobj_path); 4733 return; 4734 } 4735 4736 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0) 4737 return; 4738 4739 wpa_s->dbus_groupobj_path = os_strdup(group_obj_path); 4740 if (wpa_s->dbus_groupobj_path == NULL) 4741 return; 4742 4743 wpa_printf(MSG_INFO, "dbus: Register group object '%s'", 4744 group_obj_path); 4745 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 4746 if (!obj_desc) { 4747 wpa_printf(MSG_ERROR, 4748 "Not enough memory to create object description"); 4749 goto err; 4750 } 4751 4752 wpas_dbus_register(obj_desc, wpa_s, NULL, NULL, 4753 wpas_dbus_p2p_group_properties, 4754 wpas_dbus_p2p_group_signals); 4755 4756 if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path, 4757 wpa_s->ifname, obj_desc)) 4758 goto err; 4759 4760 return; 4761 4762 err: 4763 if (wpa_s->dbus_groupobj_path) { 4764 os_free(wpa_s->dbus_groupobj_path); 4765 wpa_s->dbus_groupobj_path = NULL; 4766 } 4767 4768 free_dbus_object_desc(obj_desc); 4769 } 4770 4771 /** 4772 * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus 4773 * @wpa_s: wpa_supplicant interface structure 4774 * @ssid: network name of the p2p group started 4775 */ 4776 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s, 4777 const struct wpa_ssid *ssid) 4778 { 4779 struct wpas_dbus_priv *ctrl_iface; 4780 4781 /* Do nothing if the control interface is not turned on */ 4782 if (wpa_s == NULL || wpa_s->global == NULL) 4783 return; 4784 4785 if (wpa_s->p2p_mgmt) 4786 wpa_s = wpa_s->parent; 4787 4788 ctrl_iface = wpa_s->global->dbus; 4789 if (ctrl_iface == NULL) 4790 return; 4791 4792 if (!wpa_s->dbus_groupobj_path) { 4793 wpa_printf(MSG_DEBUG, 4794 "%s: Group object '%s' already unregistered", 4795 __func__, wpa_s->dbus_groupobj_path); 4796 return; 4797 } 4798 4799 peer_groups_changed(wpa_s); 4800 4801 wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'", 4802 wpa_s->dbus_groupobj_path); 4803 4804 wpa_dbus_unregister_object_per_iface(ctrl_iface, 4805 wpa_s->dbus_groupobj_path); 4806 4807 os_free(wpa_s->dbus_groupobj_path); 4808 wpa_s->dbus_groupobj_path = NULL; 4809 } 4810 4811 static const struct wpa_dbus_property_desc 4812 wpas_dbus_persistent_group_properties[] = { 4813 { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}", 4814 wpas_dbus_getter_persistent_group_properties, 4815 wpas_dbus_setter_persistent_group_properties, 4816 NULL 4817 }, 4818 { NULL, NULL, NULL, NULL, NULL, NULL } 4819 }; 4820 4821 /* No signals intended for persistent group objects */ 4822 4823 /** 4824 * wpas_dbus_register_persistent_group - Register a configured(saved) 4825 * persistent group with dbus 4826 * @wpa_s: wpa_supplicant interface structure 4827 * @ssid: persistent group (still represented as a network within wpa) 4828 * configuration data 4829 * Returns: 0 on success, -1 on failure 4830 * 4831 * Registers a persistent group representing object with dbus. 4832 */ 4833 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s, 4834 struct wpa_ssid *ssid) 4835 { 4836 struct wpas_dbus_priv *ctrl_iface; 4837 struct wpa_dbus_object_desc *obj_desc; 4838 struct network_handler_args *arg; 4839 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4840 4841 /* Do nothing if the control interface is not turned on */ 4842 if (wpa_s == NULL || wpa_s->global == NULL) 4843 return 0; 4844 wpa_s = wpa_s->parent->parent; 4845 if (!wpa_s->dbus_new_path) 4846 return 0; 4847 4848 /* Make sure ssid is a persistent group */ 4849 if (ssid->disabled != 2 && !ssid->p2p_persistent_group) 4850 return -1; /* should we return w/o complaining? */ 4851 4852 if (wpa_s->p2p_mgmt) 4853 wpa_s = wpa_s->parent; 4854 4855 ctrl_iface = wpa_s->global->dbus; 4856 if (ctrl_iface == NULL) 4857 return 0; 4858 4859 /* 4860 * Intentionally not coming up with different numbering scheme 4861 * for persistent groups. 4862 */ 4863 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4864 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 4865 wpa_s->dbus_new_path, ssid->id); 4866 4867 wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'", 4868 pgrp_obj_path); 4869 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 4870 if (!obj_desc) { 4871 wpa_printf(MSG_ERROR, 4872 "dbus: Not enough memory to create object description"); 4873 goto err; 4874 } 4875 4876 /* 4877 * Reusing the same context structure as that for networks 4878 * since these are represented using same data structure. 4879 */ 4880 /* allocate memory for handlers arguments */ 4881 arg = os_zalloc(sizeof(struct network_handler_args)); 4882 if (!arg) { 4883 wpa_printf(MSG_ERROR, 4884 "dbus: Not enough memory to create arguments for method"); 4885 goto err; 4886 } 4887 4888 arg->wpa_s = wpa_s; 4889 arg->ssid = ssid; 4890 4891 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 4892 wpas_dbus_persistent_group_properties, 4893 NULL); 4894 4895 if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path, 4896 wpa_s->ifname, obj_desc)) 4897 goto err; 4898 4899 wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id); 4900 4901 return 0; 4902 4903 err: 4904 free_dbus_object_desc(obj_desc); 4905 return -1; 4906 } 4907 4908 4909 /** 4910 * wpas_dbus_unregister_persistent_group - Unregister a persistent_group 4911 * from dbus 4912 * @wpa_s: wpa_supplicant interface structure 4913 * @nid: network id 4914 * Returns: 0 on success, -1 on failure 4915 * 4916 * Unregisters persistent group representing object from dbus 4917 * 4918 * NOTE: There is a slight issue with the semantics here. While the 4919 * implementation simply means the persistent group is unloaded from memory, 4920 * it should not get interpreted as the group is actually being erased/removed 4921 * from persistent storage as well. 4922 */ 4923 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s, 4924 int nid) 4925 { 4926 struct wpas_dbus_priv *ctrl_iface; 4927 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4928 int ret; 4929 4930 /* Do nothing if the control interface is not turned on */ 4931 if (wpa_s == NULL || wpa_s->global == NULL) 4932 return 0; 4933 4934 wpa_s = wpa_s->parent->parent; 4935 4936 ctrl_iface = wpa_s->global->dbus; 4937 if (ctrl_iface == NULL || !wpa_s->dbus_new_path) 4938 return 0; 4939 4940 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4941 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 4942 wpa_s->dbus_new_path, nid); 4943 4944 wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'", 4945 pgrp_obj_path); 4946 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path); 4947 4948 if (!ret) 4949 wpas_dbus_signal_persistent_group_removed(wpa_s, nid); 4950 4951 return ret; 4952 } 4953 4954 #endif /* CONFIG_P2P */ 4955