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