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