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