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