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 1027 void wpas_dbus_signal_anqp_query_done(struct wpa_supplicant *wpa_s, 1028 const u8 *dst, const char *result) 1029 { 1030 struct wpas_dbus_priv *iface; 1031 DBusMessage *msg; 1032 DBusMessageIter iter; 1033 char addr[WPAS_DBUS_OBJECT_PATH_MAX], *bssid; 1034 1035 os_snprintf(addr, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(dst)); 1036 bssid = addr; 1037 1038 iface = wpa_s->global->dbus; 1039 1040 /* Do nothing if the control interface is not turned on */ 1041 if (!iface || !wpa_s->dbus_new_path) 1042 return; 1043 1044 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1045 WPAS_DBUS_NEW_IFACE_INTERFACE, 1046 "ANQPQueryDone"); 1047 if (!msg) 1048 return; 1049 1050 dbus_message_iter_init_append(msg, &iter); 1051 1052 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &bssid) || 1053 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &result)) 1054 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1055 else 1056 dbus_connection_send(iface->con, msg, NULL); 1057 dbus_message_unref(msg); 1058 } 1059 1060 #endif /* CONFIG_INTERWORKING */ 1061 1062 1063 void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s, 1064 int depth, const char *subject, 1065 const char *altsubject[], 1066 int num_altsubject, 1067 const char *cert_hash, 1068 const struct wpabuf *cert) 1069 { 1070 struct wpas_dbus_priv *iface; 1071 DBusMessage *msg; 1072 DBusMessageIter iter, dict_iter; 1073 1074 iface = wpa_s->global->dbus; 1075 1076 /* Do nothing if the control interface is not turned on */ 1077 if (iface == NULL || !wpa_s->dbus_new_path) 1078 return; 1079 1080 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1081 WPAS_DBUS_NEW_IFACE_INTERFACE, 1082 "Certification"); 1083 if (msg == NULL) 1084 return; 1085 1086 dbus_message_iter_init_append(msg, &iter); 1087 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1088 !wpa_dbus_dict_append_uint32(&dict_iter, "depth", depth) || 1089 !wpa_dbus_dict_append_string(&dict_iter, "subject", subject) || 1090 (altsubject && num_altsubject && 1091 !wpa_dbus_dict_append_string_array(&dict_iter, "altsubject", 1092 altsubject, num_altsubject)) || 1093 (cert_hash && 1094 !wpa_dbus_dict_append_string(&dict_iter, "cert_hash", 1095 cert_hash)) || 1096 (cert && 1097 !wpa_dbus_dict_append_byte_array(&dict_iter, "cert", 1098 wpabuf_head(cert), 1099 wpabuf_len(cert))) || 1100 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 1101 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1102 else 1103 dbus_connection_send(iface->con, msg, NULL); 1104 dbus_message_unref(msg); 1105 } 1106 1107 1108 void wpas_dbus_signal_eap_status(struct wpa_supplicant *wpa_s, 1109 const char *status, const char *parameter) 1110 { 1111 struct wpas_dbus_priv *iface; 1112 DBusMessage *msg; 1113 DBusMessageIter iter; 1114 1115 iface = wpa_s->global->dbus; 1116 1117 /* Do nothing if the control interface is not turned on */ 1118 if (iface == NULL || !wpa_s->dbus_new_path) 1119 return; 1120 1121 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1122 WPAS_DBUS_NEW_IFACE_INTERFACE, 1123 "EAP"); 1124 if (msg == NULL) 1125 return; 1126 1127 dbus_message_iter_init_append(msg, &iter); 1128 1129 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &status) || 1130 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, 1131 ¶meter)) 1132 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1133 else 1134 dbus_connection_send(iface->con, msg, NULL); 1135 dbus_message_unref(msg); 1136 } 1137 1138 1139 void wpas_dbus_signal_psk_mismatch(struct wpa_supplicant *wpa_s) 1140 { 1141 struct wpas_dbus_priv *iface; 1142 DBusMessage *msg; 1143 1144 iface = wpa_s->global->dbus; 1145 1146 /* Do nothing if the control interface is not turned on */ 1147 if (!iface || !wpa_s->dbus_new_path) 1148 return; 1149 1150 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1151 WPAS_DBUS_NEW_IFACE_INTERFACE, 1152 "PskMismatch"); 1153 if (!msg) 1154 return; 1155 1156 dbus_connection_send(iface->con, msg, NULL); 1157 1158 dbus_message_unref(msg); 1159 } 1160 1161 1162 /** 1163 * wpas_dbus_signal_sta - Send a station related event signal 1164 * @wpa_s: %wpa_supplicant network interface data 1165 * @sta: station mac address 1166 * @sig_name: signal name - StaAuthorized or StaDeauthorized 1167 * 1168 * Notify listeners about event related with station 1169 */ 1170 static void wpas_dbus_signal_sta(struct wpa_supplicant *wpa_s, 1171 const u8 *sta, const char *sig_name) 1172 { 1173 struct wpas_dbus_priv *iface; 1174 DBusMessage *msg; 1175 char sta_mac[WPAS_DBUS_OBJECT_PATH_MAX]; 1176 char *dev_mac; 1177 1178 os_snprintf(sta_mac, WPAS_DBUS_OBJECT_PATH_MAX, MACSTR, MAC2STR(sta)); 1179 dev_mac = sta_mac; 1180 1181 iface = wpa_s->global->dbus; 1182 1183 /* Do nothing if the control interface is not turned on */ 1184 if (iface == NULL || !wpa_s->dbus_new_path) 1185 return; 1186 1187 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1188 WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name); 1189 if (msg == NULL) 1190 return; 1191 1192 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &dev_mac, 1193 DBUS_TYPE_INVALID)) 1194 dbus_connection_send(iface->con, msg, NULL); 1195 else 1196 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1197 dbus_message_unref(msg); 1198 1199 wpa_printf(MSG_DEBUG, "dbus: Station MAC address '%s' '%s'", 1200 sta_mac, sig_name); 1201 } 1202 1203 1204 /** 1205 * wpas_dbus_signal_sta_authorized - Send a STA authorized signal 1206 * @wpa_s: %wpa_supplicant network interface data 1207 * @sta: station mac address 1208 * 1209 * Notify listeners a new station has been authorized 1210 */ 1211 void wpas_dbus_signal_sta_authorized(struct wpa_supplicant *wpa_s, 1212 const u8 *sta) 1213 { 1214 wpas_dbus_signal_sta(wpa_s, sta, "StaAuthorized"); 1215 } 1216 1217 1218 /** 1219 * wpas_dbus_signal_sta_deauthorized - Send a STA deauthorized signal 1220 * @wpa_s: %wpa_supplicant network interface data 1221 * @sta: station mac address 1222 * 1223 * Notify listeners a station has been deauthorized 1224 */ 1225 void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s, 1226 const u8 *sta) 1227 { 1228 wpas_dbus_signal_sta(wpa_s, sta, "StaDeauthorized"); 1229 } 1230 1231 1232 /** 1233 * wpas_dbus_signal_station - Send an event signal related to a station object 1234 * @wpa_s: %wpa_supplicant network interface data 1235 * @station_obj_path: Station object path 1236 * @sig_name: signal name - StationAdded or StationRemoved 1237 * @properties: Whether to add second argument with object properties 1238 * 1239 * Notify listeners about event related with station. 1240 */ 1241 static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s, 1242 const char *station_obj_path, 1243 const char *sig_name, 1244 dbus_bool_t properties) 1245 { 1246 struct wpas_dbus_priv *iface; 1247 DBusMessage *msg; 1248 DBusMessageIter iter; 1249 1250 iface = wpa_s->global->dbus; 1251 1252 /* Do nothing if the control interface is not turned on */ 1253 if (!iface || !wpa_s->dbus_new_path) 1254 return; 1255 1256 wpa_printf(MSG_DEBUG, "dbus: STA signal %s", sig_name); 1257 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1258 WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name); 1259 if (!msg) 1260 return; 1261 1262 dbus_message_iter_init_append(msg, &iter); 1263 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1264 &station_obj_path) || 1265 (properties && 1266 !wpa_dbus_get_object_properties(iface, station_obj_path, 1267 WPAS_DBUS_NEW_IFACE_STA, 1268 &iter))) 1269 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1270 else 1271 dbus_connection_send(iface->con, msg, NULL); 1272 dbus_message_unref(msg); 1273 } 1274 1275 1276 /** 1277 * wpas_dbus_signal_station_added - Send a Station added signal 1278 * @wpa_s: %wpa_supplicant network interface data 1279 * @station_obj_path: new Station object path 1280 * 1281 * Notify listeners about adding new Station 1282 */ 1283 static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s, 1284 const char *station_obj_path) 1285 { 1286 wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE); 1287 } 1288 1289 1290 /** 1291 * wpas_dbus_signal_station_removed - Send a Station removed signal 1292 * @wpa_s: %wpa_supplicant network interface data 1293 * @station_obj_path: Station object path 1294 * 1295 * Notify listeners about removing Station 1296 */ 1297 static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s, 1298 const char *station_obj_path) 1299 { 1300 wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved", 1301 FALSE); 1302 } 1303 1304 1305 #ifdef CONFIG_P2P 1306 1307 /** 1308 * wpas_dbus_signal_p2p_group_removed - Signals P2P group was removed 1309 * @wpa_s: %wpa_supplicant network interface data 1310 * @role: role of this device (client or GO) 1311 * Sends signal with i/f name and role as string arguments 1312 */ 1313 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s, 1314 const char *role) 1315 { 1316 DBusMessage *msg; 1317 DBusMessageIter iter, dict_iter; 1318 struct wpas_dbus_priv *iface = wpa_s->global->dbus; 1319 struct wpa_supplicant *parent; 1320 1321 /* Do nothing if the control interface is not turned on */ 1322 if (iface == NULL) 1323 return; 1324 1325 parent = wpa_s->parent; 1326 if (parent->p2p_mgmt) 1327 parent = parent->parent; 1328 1329 if (!wpa_s->dbus_groupobj_path || !wpa_s->dbus_new_path || 1330 !parent->dbus_new_path) 1331 return; 1332 1333 msg = dbus_message_new_signal(parent->dbus_new_path, 1334 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1335 "GroupFinished"); 1336 if (msg == NULL) 1337 return; 1338 1339 dbus_message_iter_init_append(msg, &iter); 1340 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1341 !wpa_dbus_dict_append_object_path(&dict_iter, 1342 "interface_object", 1343 wpa_s->dbus_new_path) || 1344 !wpa_dbus_dict_append_string(&dict_iter, "role", role) || 1345 !wpa_dbus_dict_append_object_path(&dict_iter, "group_object", 1346 wpa_s->dbus_groupobj_path) || 1347 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 1348 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1349 else 1350 dbus_connection_send(iface->con, msg, NULL); 1351 dbus_message_unref(msg); 1352 } 1353 1354 1355 /** 1356 * wpas_dbus_signal_p2p_provision_discovery - Signals various PD events 1357 * 1358 * @dev_addr - who sent the request or responded to our request. 1359 * @request - Will be 1 if request, 0 for response. 1360 * @status - valid only in case of response 1361 * @config_methods - wps config methods 1362 * @generated_pin - pin to be displayed in case of WPS_CONFIG_DISPLAY method 1363 * 1364 * Sends following provision discovery related events: 1365 * ProvisionDiscoveryRequestDisplayPin 1366 * ProvisionDiscoveryResponseDisplayPin 1367 * ProvisionDiscoveryRequestEnterPin 1368 * ProvisionDiscoveryResponseEnterPin 1369 * ProvisionDiscoveryPBCRequest 1370 * ProvisionDiscoveryPBCResponse 1371 * 1372 * TODO:: 1373 * ProvisionDiscoveryFailure (timeout case) 1374 */ 1375 void wpas_dbus_signal_p2p_provision_discovery(struct wpa_supplicant *wpa_s, 1376 const u8 *dev_addr, int request, 1377 enum p2p_prov_disc_status status, 1378 u16 config_methods, 1379 unsigned int generated_pin) 1380 { 1381 DBusMessage *msg; 1382 DBusMessageIter iter; 1383 struct wpas_dbus_priv *iface; 1384 char *_signal; 1385 int add_pin = 0; 1386 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1387 int error_ret = 1; 1388 char pin[9], *p_pin = NULL; 1389 1390 iface = wpa_s->global->dbus; 1391 1392 /* Do nothing if the control interface is not turned on */ 1393 if (iface == NULL) 1394 return; 1395 1396 if (wpa_s->p2p_mgmt) 1397 wpa_s = wpa_s->parent; 1398 if (!wpa_s->dbus_new_path) 1399 return; 1400 1401 if (request || !status) { 1402 if (config_methods & WPS_CONFIG_DISPLAY) 1403 _signal = request ? 1404 "ProvisionDiscoveryRequestDisplayPin" : 1405 "ProvisionDiscoveryResponseEnterPin"; 1406 else if (config_methods & WPS_CONFIG_KEYPAD) 1407 _signal = request ? 1408 "ProvisionDiscoveryRequestEnterPin" : 1409 "ProvisionDiscoveryResponseDisplayPin"; 1410 else if (config_methods & WPS_CONFIG_PUSHBUTTON) 1411 _signal = request ? "ProvisionDiscoveryPBCRequest" : 1412 "ProvisionDiscoveryPBCResponse"; 1413 else 1414 return; /* Unknown or un-supported method */ 1415 } else { 1416 /* Explicit check for failure response */ 1417 _signal = "ProvisionDiscoveryFailure"; 1418 } 1419 1420 add_pin = ((request && (config_methods & WPS_CONFIG_DISPLAY)) || 1421 (!request && !status && 1422 (config_methods & WPS_CONFIG_KEYPAD))); 1423 1424 if (add_pin) { 1425 os_snprintf(pin, sizeof(pin), "%08d", generated_pin); 1426 p_pin = pin; 1427 } 1428 1429 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1430 WPAS_DBUS_NEW_IFACE_P2PDEVICE, _signal); 1431 if (msg == NULL) 1432 return; 1433 1434 /* Check if this is a known peer */ 1435 if (!p2p_peer_known(wpa_s->global->p2p, dev_addr)) 1436 goto error; 1437 1438 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1439 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1440 COMPACT_MACSTR, 1441 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 1442 1443 path = peer_obj_path; 1444 1445 dbus_message_iter_init_append(msg, &iter); 1446 1447 if (!dbus_message_iter_append_basic(&iter, 1448 DBUS_TYPE_OBJECT_PATH, 1449 &path)) 1450 goto error; 1451 1452 if (!request && status) 1453 /* Attach status to ProvisionDiscoveryFailure */ 1454 error_ret = !dbus_message_iter_append_basic(&iter, 1455 DBUS_TYPE_INT32, 1456 &status); 1457 else 1458 error_ret = (add_pin && 1459 !dbus_message_iter_append_basic(&iter, 1460 DBUS_TYPE_STRING, 1461 &p_pin)); 1462 1463 error: 1464 if (!error_ret) 1465 dbus_connection_send(iface->con, msg, NULL); 1466 else 1467 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1468 1469 dbus_message_unref(msg); 1470 } 1471 1472 1473 /** 1474 * wpas_dbus_signal_p2p_go_neg_req - Signal P2P GO Negotiation Request RX 1475 * @wpa_s: %wpa_supplicant network interface data 1476 * @src: Source address of the message triggering this notification 1477 * @dev_passwd_id: WPS Device Password Id 1478 * @go_intent: Peer's GO Intent value 1479 * 1480 * Sends signal to notify that a peer P2P Device is requesting group owner 1481 * negotiation with us. 1482 */ 1483 void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s, 1484 const u8 *src, u16 dev_passwd_id, 1485 u8 go_intent) 1486 { 1487 DBusMessage *msg; 1488 DBusMessageIter iter; 1489 struct wpas_dbus_priv *iface; 1490 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1491 1492 iface = wpa_s->global->dbus; 1493 1494 /* Do nothing if the control interface is not turned on */ 1495 if (iface == NULL) 1496 return; 1497 1498 if (wpa_s->p2p_mgmt) 1499 wpa_s = wpa_s->parent; 1500 if (!wpa_s->dbus_new_path) 1501 return; 1502 1503 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1504 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 1505 wpa_s->dbus_new_path, MAC2STR(src)); 1506 path = peer_obj_path; 1507 1508 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1509 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1510 "GONegotiationRequest"); 1511 if (msg == NULL) 1512 return; 1513 1514 dbus_message_iter_init_append(msg, &iter); 1515 1516 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1517 &path) || 1518 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT16, 1519 &dev_passwd_id) || 1520 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE, 1521 &go_intent)) 1522 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1523 else 1524 dbus_connection_send(iface->con, msg, NULL); 1525 1526 dbus_message_unref(msg); 1527 } 1528 1529 1530 static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s, 1531 const struct wpa_ssid *ssid, 1532 char *group_obj_path) 1533 { 1534 char group_name[3]; 1535 1536 if (!wpa_s->dbus_new_path || 1537 os_memcmp(ssid->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN)) 1538 return -1; 1539 1540 os_memcpy(group_name, ssid->ssid + P2P_WILDCARD_SSID_LEN, 2); 1541 group_name[2] = '\0'; 1542 1543 os_snprintf(group_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1544 "%s/" WPAS_DBUS_NEW_P2P_GROUPS_PART "/%s", 1545 wpa_s->dbus_new_path, group_name); 1546 1547 return 0; 1548 } 1549 1550 1551 struct group_changed_data { 1552 struct wpa_supplicant *wpa_s; 1553 struct p2p_peer_info *info; 1554 }; 1555 1556 1557 static int match_group_where_peer_is_client(struct p2p_group *group, 1558 void *user_data) 1559 { 1560 struct group_changed_data *data = user_data; 1561 const struct p2p_group_config *cfg; 1562 struct wpa_supplicant *wpa_s_go; 1563 1564 if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr)) 1565 return 1; 1566 1567 cfg = p2p_group_get_config(group); 1568 1569 wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid, 1570 cfg->ssid_len); 1571 if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) { 1572 wpas_dbus_signal_peer_groups_changed( 1573 data->wpa_s->p2pdev, data->info->p2p_device_addr); 1574 return 0; 1575 } 1576 1577 return 1; 1578 } 1579 1580 1581 static void signal_peer_groups_changed(struct p2p_peer_info *info, 1582 void *user_data) 1583 { 1584 struct group_changed_data *data = user_data; 1585 struct wpa_supplicant *wpa_s_go; 1586 1587 wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s, 1588 info->p2p_device_addr); 1589 if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) { 1590 wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev, 1591 info->p2p_device_addr); 1592 return; 1593 } 1594 1595 data->info = info; 1596 p2p_loop_on_all_groups(data->wpa_s->global->p2p, 1597 match_group_where_peer_is_client, data); 1598 data->info = NULL; 1599 } 1600 1601 1602 static void peer_groups_changed(struct wpa_supplicant *wpa_s) 1603 { 1604 struct group_changed_data data; 1605 1606 os_memset(&data, 0, sizeof(data)); 1607 data.wpa_s = wpa_s; 1608 1609 p2p_loop_on_known_peers(wpa_s->global->p2p, 1610 signal_peer_groups_changed, &data); 1611 } 1612 1613 1614 /** 1615 * wpas_dbus_signal_p2p_group_started - Signals P2P group has 1616 * started. Emitted when a group is successfully started 1617 * irrespective of the role (client/GO) of the current device 1618 * 1619 * @wpa_s: %wpa_supplicant network interface data 1620 * @client: this device is P2P client 1621 * @persistent: 0 - non persistent group, 1 - persistent group 1622 * @ip: When group role is client, it contains local IP address, netmask, and 1623 * GO's IP address, if assigned; otherwise, NULL 1624 */ 1625 void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s, 1626 int client, int persistent, 1627 const u8 *ip) 1628 { 1629 DBusMessage *msg; 1630 DBusMessageIter iter, dict_iter; 1631 struct wpas_dbus_priv *iface; 1632 struct wpa_supplicant *parent; 1633 1634 parent = wpa_s->parent; 1635 if (parent->p2p_mgmt) 1636 parent = parent->parent; 1637 1638 iface = parent->global->dbus; 1639 1640 /* Do nothing if the control interface is not turned on */ 1641 if (iface == NULL || !parent->dbus_new_path || !wpa_s->dbus_new_path) 1642 return; 1643 1644 if (wpa_s->dbus_groupobj_path == NULL) 1645 return; 1646 1647 /* New interface has been created for this group */ 1648 msg = dbus_message_new_signal(parent->dbus_new_path, 1649 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1650 "GroupStarted"); 1651 if (msg == NULL) 1652 return; 1653 1654 dbus_message_iter_init_append(msg, &iter); 1655 /* 1656 * In case the device supports creating a separate interface the 1657 * DBus client will need to know the object path for the interface 1658 * object this group was created on, so include it here. 1659 */ 1660 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1661 !wpa_dbus_dict_append_object_path(&dict_iter, 1662 "interface_object", 1663 wpa_s->dbus_new_path) || 1664 !wpa_dbus_dict_append_string(&dict_iter, "role", 1665 client ? "client" : "GO") || 1666 !wpa_dbus_dict_append_bool(&dict_iter, "persistent", 1667 !!persistent) || 1668 !wpa_dbus_dict_append_object_path(&dict_iter, "group_object", 1669 wpa_s->dbus_groupobj_path) || 1670 (ip && 1671 (!wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddr", 1672 (char *) ip, 4) || 1673 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrMask", 1674 (char *) ip + 4, 4) || 1675 !wpa_dbus_dict_append_byte_array(&dict_iter, "IpAddrGo", 1676 (char *) ip + 8, 4))) || 1677 !wpa_dbus_dict_close_write(&iter, &dict_iter)) { 1678 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1679 } else { 1680 dbus_connection_send(iface->con, msg, NULL); 1681 if (client) 1682 peer_groups_changed(wpa_s); 1683 } 1684 dbus_message_unref(msg); 1685 } 1686 1687 1688 /** 1689 * wpas_dbus_signal_p2p_go_neg_resp - Emit GONegotiation Success/Failure signal 1690 * @wpa_s: %wpa_supplicant network interface data 1691 * @res: Result of the GO Neg Request 1692 */ 1693 void wpas_dbus_signal_p2p_go_neg_resp(struct wpa_supplicant *wpa_s, 1694 struct p2p_go_neg_results *res) 1695 { 1696 DBusMessage *msg; 1697 DBusMessageIter iter, dict_iter; 1698 DBusMessageIter iter_dict_entry, iter_dict_val, iter_dict_array; 1699 struct wpas_dbus_priv *iface; 1700 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1701 dbus_int32_t freqs[P2P_MAX_CHANNELS]; 1702 dbus_int32_t *f_array = freqs; 1703 1704 1705 iface = wpa_s->global->dbus; 1706 1707 if (wpa_s->p2p_mgmt) 1708 wpa_s = wpa_s->parent; 1709 1710 os_memset(freqs, 0, sizeof(freqs)); 1711 /* Do nothing if the control interface is not turned on */ 1712 if (iface == NULL || !wpa_s->dbus_new_path) 1713 return; 1714 1715 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1716 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 1717 wpa_s->dbus_new_path, MAC2STR(res->peer_device_addr)); 1718 path = peer_obj_path; 1719 1720 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1721 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1722 res->status ? "GONegotiationFailure" : 1723 "GONegotiationSuccess"); 1724 if (msg == NULL) 1725 return; 1726 1727 dbus_message_iter_init_append(msg, &iter); 1728 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1729 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object", 1730 path) || 1731 !wpa_dbus_dict_append_int32(&dict_iter, "status", res->status)) 1732 goto err; 1733 1734 if (!res->status) { 1735 int i = 0; 1736 int freq_list_num = 0; 1737 1738 if ((res->role_go && 1739 !wpa_dbus_dict_append_string(&dict_iter, "passphrase", 1740 res->passphrase)) || 1741 !wpa_dbus_dict_append_string(&dict_iter, "role_go", 1742 res->role_go ? "GO" : 1743 "client") || 1744 !wpa_dbus_dict_append_int32(&dict_iter, "frequency", 1745 res->freq) || 1746 !wpa_dbus_dict_append_byte_array(&dict_iter, "ssid", 1747 (const char *) res->ssid, 1748 res->ssid_len) || 1749 !wpa_dbus_dict_append_byte_array(&dict_iter, 1750 "peer_device_addr", 1751 (const char *) 1752 res->peer_device_addr, 1753 ETH_ALEN) || 1754 !wpa_dbus_dict_append_byte_array(&dict_iter, 1755 "peer_interface_addr", 1756 (const char *) 1757 res->peer_interface_addr, 1758 ETH_ALEN) || 1759 !wpa_dbus_dict_append_string(&dict_iter, "wps_method", 1760 p2p_wps_method_text( 1761 res->wps_method))) 1762 goto err; 1763 1764 for (i = 0; i < P2P_MAX_CHANNELS; i++) { 1765 if (res->freq_list[i]) { 1766 freqs[i] = res->freq_list[i]; 1767 freq_list_num++; 1768 } 1769 } 1770 1771 if (!wpa_dbus_dict_begin_array(&dict_iter, 1772 "frequency_list", 1773 DBUS_TYPE_INT32_AS_STRING, 1774 &iter_dict_entry, 1775 &iter_dict_val, 1776 &iter_dict_array) || 1777 !dbus_message_iter_append_fixed_array(&iter_dict_array, 1778 DBUS_TYPE_INT32, 1779 &f_array, 1780 freq_list_num) || 1781 !wpa_dbus_dict_end_array(&dict_iter, 1782 &iter_dict_entry, 1783 &iter_dict_val, 1784 &iter_dict_array) || 1785 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_group", 1786 res->persistent_group) || 1787 !wpa_dbus_dict_append_uint32(&dict_iter, 1788 "peer_config_timeout", 1789 res->peer_config_timeout)) 1790 goto err; 1791 } 1792 1793 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) 1794 goto err; 1795 1796 dbus_connection_send(iface->con, msg, NULL); 1797 err: 1798 dbus_message_unref(msg); 1799 } 1800 1801 1802 /** 1803 * wpas_dbus_signal_p2p_invitation_result - Emit InvitationResult signal 1804 * @wpa_s: %wpa_supplicant network interface data 1805 * @status: Status of invitation process 1806 * @bssid: Basic Service Set Identifier 1807 */ 1808 void wpas_dbus_signal_p2p_invitation_result(struct wpa_supplicant *wpa_s, 1809 int status, const u8 *bssid) 1810 { 1811 DBusMessage *msg; 1812 DBusMessageIter iter, dict_iter; 1813 struct wpas_dbus_priv *iface; 1814 1815 wpa_printf(MSG_DEBUG, "%s", __func__); 1816 1817 iface = wpa_s->global->dbus; 1818 /* Do nothing if the control interface is not turned on */ 1819 if (iface == NULL) 1820 return; 1821 1822 if (wpa_s->p2p_mgmt) 1823 wpa_s = wpa_s->parent; 1824 if (!wpa_s->dbus_new_path) 1825 return; 1826 1827 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 1828 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 1829 "InvitationResult"); 1830 1831 if (msg == NULL) 1832 return; 1833 1834 dbus_message_iter_init_append(msg, &iter); 1835 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 1836 !wpa_dbus_dict_append_int32(&dict_iter, "status", status) || 1837 (bssid && 1838 !wpa_dbus_dict_append_byte_array(&dict_iter, "BSSID", 1839 (const char *) bssid, 1840 ETH_ALEN)) || 1841 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 1842 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 1843 else 1844 dbus_connection_send(iface->con, msg, NULL); 1845 dbus_message_unref(msg); 1846 } 1847 1848 1849 /** 1850 * 1851 * Method to emit a signal for a peer joining the group. 1852 * The signal will carry path to the group member object 1853 * constructed using p2p i/f addr used for connecting. 1854 * 1855 * @wpa_s: %wpa_supplicant network interface data 1856 * @peer_addr: P2P Device Address of the peer joining the group 1857 */ 1858 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s, 1859 const u8 *peer_addr) 1860 { 1861 struct wpas_dbus_priv *iface; 1862 DBusMessage *msg; 1863 DBusMessageIter iter; 1864 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1865 struct wpa_supplicant *parent; 1866 1867 iface = wpa_s->global->dbus; 1868 1869 /* Do nothing if the control interface is not turned on */ 1870 if (iface == NULL) 1871 return; 1872 1873 if (!wpa_s->dbus_groupobj_path) 1874 return; 1875 1876 parent = wpa_s->parent; 1877 if (parent->p2p_mgmt) 1878 parent = parent->parent; 1879 if (!parent->dbus_new_path) 1880 return; 1881 1882 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1883 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1884 COMPACT_MACSTR, 1885 parent->dbus_new_path, MAC2STR(peer_addr)); 1886 1887 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path, 1888 WPAS_DBUS_NEW_IFACE_P2P_GROUP, 1889 "PeerJoined"); 1890 if (msg == NULL) 1891 return; 1892 1893 dbus_message_iter_init_append(msg, &iter); 1894 path = peer_obj_path; 1895 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1896 &path)) { 1897 wpa_printf(MSG_ERROR, "dbus: Failed to construct 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 peer disconnecting the group. 1909 * The signal will carry path to the group member object 1910 * constructed using the P2P Device Address of the peer. 1911 * 1912 * @wpa_s: %wpa_supplicant network interface data 1913 * @peer_addr: P2P Device Address of the peer joining the group 1914 */ 1915 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s, 1916 const u8 *peer_addr) 1917 { 1918 struct wpas_dbus_priv *iface; 1919 DBusMessage *msg; 1920 DBusMessageIter iter; 1921 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1922 struct wpa_supplicant *parent; 1923 1924 iface = wpa_s->global->dbus; 1925 1926 /* Do nothing if the control interface is not turned on */ 1927 if (iface == NULL) 1928 return; 1929 1930 if (!wpa_s->dbus_groupobj_path) 1931 return; 1932 1933 parent = wpa_s->parent; 1934 if (parent->p2p_mgmt) 1935 parent = parent->parent; 1936 if (!parent->dbus_new_path) 1937 return; 1938 1939 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1940 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 1941 COMPACT_MACSTR, 1942 parent->dbus_new_path, MAC2STR(peer_addr)); 1943 1944 msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path, 1945 WPAS_DBUS_NEW_IFACE_P2P_GROUP, 1946 "PeerDisconnected"); 1947 if (msg == NULL) 1948 return; 1949 1950 dbus_message_iter_init_append(msg, &iter); 1951 path = peer_obj_path; 1952 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 1953 &path)) { 1954 wpa_printf(MSG_ERROR, 1955 "dbus: Failed to construct PeerDisconnected signal"); 1956 } else { 1957 dbus_connection_send(iface->con, msg, NULL); 1958 wpas_dbus_signal_peer_groups_changed(parent, peer_addr); 1959 } 1960 dbus_message_unref(msg); 1961 } 1962 1963 1964 /** 1965 * 1966 * Method to emit a signal for a service discovery request. 1967 * The signal will carry station address, frequency, dialog token, 1968 * update indicator and it tlvs 1969 * 1970 * @wpa_s: %wpa_supplicant network interface data 1971 * @sa: station addr (p2p i/f) of the peer 1972 * @dialog_token: service discovery request dialog token 1973 * @update_indic: service discovery request update indicator 1974 * @tlvs: service discovery request generated byte array of tlvs 1975 * @tlvs_len: service discovery request tlvs length 1976 */ 1977 void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, 1978 int freq, const u8 *sa, u8 dialog_token, 1979 u16 update_indic, const u8 *tlvs, 1980 size_t tlvs_len) 1981 { 1982 DBusMessage *msg; 1983 DBusMessageIter iter, dict_iter; 1984 struct wpas_dbus_priv *iface; 1985 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 1986 1987 iface = wpa_s->global->dbus; 1988 1989 /* Do nothing if the control interface is not turned on */ 1990 if (iface == NULL) 1991 return; 1992 1993 if (wpa_s->p2p_mgmt) 1994 wpa_s = wpa_s->parent; 1995 if (!wpa_s->dbus_new_path) 1996 return; 1997 1998 /* Check if this is a known peer */ 1999 if (!p2p_peer_known(wpa_s->global->p2p, sa)) 2000 return; 2001 2002 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2003 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2004 "ServiceDiscoveryRequest"); 2005 if (msg == NULL) 2006 return; 2007 2008 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2009 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 2010 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa)); 2011 2012 path = peer_obj_path; 2013 2014 dbus_message_iter_init_append(msg, &iter); 2015 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 2016 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object", 2017 path) || 2018 !wpa_dbus_dict_append_int32(&dict_iter, "frequency", freq) || 2019 !wpa_dbus_dict_append_int32(&dict_iter, "dialog_token", 2020 dialog_token) || 2021 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator", 2022 update_indic) || 2023 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs", 2024 (const char *) tlvs, 2025 tlvs_len) || 2026 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 2027 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 2028 else 2029 dbus_connection_send(iface->con, msg, NULL); 2030 dbus_message_unref(msg); 2031 } 2032 2033 2034 /** 2035 * 2036 * Method to emit a signal for a service discovery response. 2037 * The signal will carry station address, update indicator and it 2038 * tlvs 2039 * 2040 * @wpa_s: %wpa_supplicant network interface data 2041 * @sa: station addr (p2p i/f) of the peer 2042 * @update_indic: service discovery request update indicator 2043 * @tlvs: service discovery request generated byte array of tlvs 2044 * @tlvs_len: service discovery request tlvs length 2045 */ 2046 void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s, 2047 const u8 *sa, u16 update_indic, 2048 const u8 *tlvs, size_t tlvs_len) 2049 { 2050 DBusMessage *msg; 2051 DBusMessageIter iter, dict_iter; 2052 struct wpas_dbus_priv *iface; 2053 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 2054 2055 iface = wpa_s->global->dbus; 2056 2057 /* Do nothing if the control interface is not turned on */ 2058 if (iface == NULL) 2059 return; 2060 2061 if (wpa_s->p2p_mgmt) 2062 wpa_s = wpa_s->parent; 2063 if (!wpa_s->dbus_new_path) 2064 return; 2065 2066 /* Check if this is a known peer */ 2067 if (!p2p_peer_known(wpa_s->global->p2p, sa)) 2068 return; 2069 2070 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2071 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2072 "ServiceDiscoveryResponse"); 2073 if (msg == NULL) 2074 return; 2075 2076 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2077 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" 2078 COMPACT_MACSTR, wpa_s->dbus_new_path, MAC2STR(sa)); 2079 2080 path = peer_obj_path; 2081 2082 dbus_message_iter_init_append(msg, &iter); 2083 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 2084 !wpa_dbus_dict_append_object_path(&dict_iter, "peer_object", 2085 path) || 2086 !wpa_dbus_dict_append_uint16(&dict_iter, "update_indicator", 2087 update_indic) || 2088 !wpa_dbus_dict_append_byte_array(&dict_iter, "tlvs", 2089 (const char *) tlvs, 2090 tlvs_len) || 2091 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 2092 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 2093 else 2094 dbus_connection_send(iface->con, msg, NULL); 2095 dbus_message_unref(msg); 2096 } 2097 2098 2099 /** 2100 * wpas_dbus_signal_persistent_group - Send a persistent group related 2101 * event signal 2102 * @wpa_s: %wpa_supplicant network interface data 2103 * @id: new persistent group id 2104 * @sig_name: signal name - PersistentGroupAdded, PersistentGroupRemoved 2105 * @properties: determines if add second argument with object properties 2106 * 2107 * Notify listeners about an event related to persistent groups. 2108 */ 2109 static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s, 2110 int id, const char *sig_name, 2111 dbus_bool_t properties) 2112 { 2113 struct wpas_dbus_priv *iface; 2114 DBusMessage *msg; 2115 DBusMessageIter iter; 2116 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 2117 2118 iface = wpa_s->global->dbus; 2119 2120 /* Do nothing if the control interface is not turned on */ 2121 if (iface == NULL) 2122 return; 2123 2124 if (wpa_s->p2p_mgmt) 2125 wpa_s = wpa_s->parent; 2126 if (!wpa_s->dbus_new_path) 2127 return; 2128 2129 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2130 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 2131 wpa_s->dbus_new_path, id); 2132 2133 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2134 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2135 sig_name); 2136 if (msg == NULL) 2137 return; 2138 2139 dbus_message_iter_init_append(msg, &iter); 2140 path = pgrp_obj_path; 2141 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 2142 &path) || 2143 (properties && 2144 !wpa_dbus_get_object_properties( 2145 iface, pgrp_obj_path, 2146 WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, &iter))) 2147 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 2148 else 2149 dbus_connection_send(iface->con, msg, NULL); 2150 2151 dbus_message_unref(msg); 2152 } 2153 2154 2155 /** 2156 * wpas_dbus_signal_persistent_group_added - Send a persistent_group 2157 * added signal 2158 * @wpa_s: %wpa_supplicant network interface data 2159 * @id: new persistent group id 2160 * 2161 * Notify listeners about addition of a new persistent group. 2162 */ 2163 static void wpas_dbus_signal_persistent_group_added( 2164 struct wpa_supplicant *wpa_s, int id) 2165 { 2166 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupAdded", 2167 TRUE); 2168 } 2169 2170 2171 /** 2172 * wpas_dbus_signal_persistent_group_removed - Send a persistent_group 2173 * removed signal 2174 * @wpa_s: %wpa_supplicant network interface data 2175 * @id: persistent group id 2176 * 2177 * Notify listeners about removal of a persistent group. 2178 */ 2179 static void wpas_dbus_signal_persistent_group_removed( 2180 struct wpa_supplicant *wpa_s, int id) 2181 { 2182 wpas_dbus_signal_persistent_group(wpa_s, id, "PersistentGroupRemoved", 2183 FALSE); 2184 } 2185 2186 2187 /** 2188 * wpas_dbus_signal_p2p_wps_failed - Signals WpsFailed event 2189 * @wpa_s: %wpa_supplicant network interface data 2190 * @fail: WPS failure information 2191 * 2192 * Sends Event dbus signal with name "fail" and dictionary containing 2193 * "msg" field with fail message number (int32) as arguments 2194 */ 2195 void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s, 2196 struct wps_event_fail *fail) 2197 { 2198 2199 DBusMessage *msg; 2200 DBusMessageIter iter, dict_iter; 2201 struct wpas_dbus_priv *iface; 2202 char *key = "fail"; 2203 2204 iface = wpa_s->global->dbus; 2205 2206 /* Do nothing if the control interface is not turned on */ 2207 if (iface == NULL) 2208 return; 2209 2210 if (wpa_s->p2p_mgmt) 2211 wpa_s = wpa_s->parent; 2212 2213 if (!wpa_s->dbus_new_path) 2214 return; 2215 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2216 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2217 "WpsFailed"); 2218 if (msg == NULL) 2219 return; 2220 2221 dbus_message_iter_init_append(msg, &iter); 2222 2223 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 2224 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 2225 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) || 2226 !wpa_dbus_dict_append_int16(&dict_iter, "config_error", 2227 fail->config_error) || 2228 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 2229 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 2230 else 2231 dbus_connection_send(iface->con, msg, NULL); 2232 2233 dbus_message_unref(msg); 2234 } 2235 2236 2237 /** 2238 * wpas_dbus_signal_p2p_group_formation_failure - Signals GroupFormationFailure event 2239 * @wpa_s: %wpa_supplicant network interface data 2240 * @reason: indicates the reason code for group formation failure 2241 * 2242 * Sends Event dbus signal and string reason code when available. 2243 */ 2244 void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s, 2245 const char *reason) 2246 { 2247 DBusMessage *msg; 2248 struct wpas_dbus_priv *iface; 2249 2250 iface = wpa_s->global->dbus; 2251 2252 /* Do nothing if the control interface is not turned on */ 2253 if (iface == NULL) 2254 return; 2255 2256 if (wpa_s->p2p_mgmt) 2257 wpa_s = wpa_s->parent; 2258 2259 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2260 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2261 "GroupFormationFailure"); 2262 if (msg == NULL) 2263 return; 2264 2265 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason, 2266 DBUS_TYPE_INVALID)) 2267 dbus_connection_send(iface->con, msg, NULL); 2268 else 2269 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 2270 2271 dbus_message_unref(msg); 2272 } 2273 2274 2275 /** 2276 * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal 2277 * @wpa_s: %wpa_supplicant network interface data 2278 * @sa: Source address of the Invitation Request 2279 * @dev_add: GO Device Address 2280 * @bssid: P2P Group BSSID or %NULL if not received 2281 * @id: Persistent group id or %0 if not persistent group 2282 * @op_freq: Operating frequency for the group 2283 */ 2284 2285 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s, 2286 const u8 *sa, const u8 *dev_addr, 2287 const u8 *bssid, int id, 2288 int op_freq) 2289 { 2290 DBusMessage *msg; 2291 DBusMessageIter iter, dict_iter; 2292 struct wpas_dbus_priv *iface; 2293 2294 iface = wpa_s->global->dbus; 2295 2296 /* Do nothing if the control interface is not turned on */ 2297 if (iface == NULL) 2298 return; 2299 2300 if (wpa_s->p2p_mgmt) 2301 wpa_s = wpa_s->parent; 2302 2303 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2304 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2305 "InvitationReceived"); 2306 if (msg == NULL) 2307 return; 2308 2309 dbus_message_iter_init_append(msg, &iter); 2310 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 2311 (sa && 2312 !wpa_dbus_dict_append_byte_array(&dict_iter, "sa", 2313 (const char *) sa, ETH_ALEN)) || 2314 (dev_addr && 2315 !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr", 2316 (const char *) dev_addr, 2317 ETH_ALEN)) || 2318 (bssid && 2319 !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid", 2320 (const char *) bssid, 2321 ETH_ALEN)) || 2322 (id && 2323 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) || 2324 !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) || 2325 !wpa_dbus_dict_close_write(&iter, &dict_iter)) { 2326 dbus_message_unref(msg); 2327 return; 2328 } 2329 2330 dbus_connection_send(iface->con, msg, NULL); 2331 dbus_message_unref(msg); 2332 } 2333 2334 2335 #endif /* CONFIG_P2P */ 2336 2337 2338 /** 2339 * wpas_dbus_signal_prop_changed - Signals change of property 2340 * @wpa_s: %wpa_supplicant network interface data 2341 * @property: indicates which property has changed 2342 * 2343 * Sends PropertyChanged signals with path, interface and arguments 2344 * depending on which property has changed. 2345 */ 2346 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, 2347 enum wpas_dbus_prop property) 2348 { 2349 char *prop; 2350 dbus_bool_t flush; 2351 2352 if (wpa_s->dbus_new_path == NULL) 2353 return; /* Skip signal since D-Bus setup is not yet ready */ 2354 2355 flush = FALSE; 2356 switch (property) { 2357 case WPAS_DBUS_PROP_AP_SCAN: 2358 prop = "ApScan"; 2359 break; 2360 case WPAS_DBUS_PROP_SCANNING: 2361 prop = "Scanning"; 2362 break; 2363 case WPAS_DBUS_PROP_STATE: 2364 prop = "State"; 2365 break; 2366 case WPAS_DBUS_PROP_CURRENT_BSS: 2367 prop = "CurrentBSS"; 2368 break; 2369 case WPAS_DBUS_PROP_CURRENT_NETWORK: 2370 prop = "CurrentNetwork"; 2371 break; 2372 case WPAS_DBUS_PROP_BSSS: 2373 prop = "BSSs"; 2374 break; 2375 case WPAS_DBUS_PROP_STATIONS: 2376 prop = "Stations"; 2377 break; 2378 case WPAS_DBUS_PROP_CURRENT_AUTH_MODE: 2379 prop = "CurrentAuthMode"; 2380 break; 2381 case WPAS_DBUS_PROP_DISCONNECT_REASON: 2382 prop = "DisconnectReason"; 2383 flush = TRUE; 2384 break; 2385 case WPAS_DBUS_PROP_AUTH_STATUS_CODE: 2386 prop = "AuthStatusCode"; 2387 flush = TRUE; 2388 break; 2389 case WPAS_DBUS_PROP_ASSOC_STATUS_CODE: 2390 prop = "AssocStatusCode"; 2391 flush = TRUE; 2392 break; 2393 case WPAS_DBUS_PROP_ROAM_TIME: 2394 prop = "RoamTime"; 2395 break; 2396 case WPAS_DBUS_PROP_ROAM_COMPLETE: 2397 prop = "RoamComplete"; 2398 break; 2399 case WPAS_DBUS_PROP_SESSION_LENGTH: 2400 prop = "SessionLength"; 2401 break; 2402 case WPAS_DBUS_PROP_BSS_TM_STATUS: 2403 prop = "BSSTMStatus"; 2404 break; 2405 case WPAS_DBUS_PROP_MAC_ADDRESS: 2406 prop = "MACAddress"; 2407 break; 2408 case WPAS_DBUS_PROP_SIGNAL_CHANGE: 2409 prop = "SignalChange"; 2410 break; 2411 default: 2412 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 2413 __func__, property); 2414 return; 2415 } 2416 2417 wpa_dbus_mark_property_changed(wpa_s->global->dbus, 2418 wpa_s->dbus_new_path, 2419 WPAS_DBUS_NEW_IFACE_INTERFACE, prop); 2420 if (flush) { 2421 wpa_dbus_flush_object_changed_properties( 2422 wpa_s->global->dbus->con, wpa_s->dbus_new_path); 2423 } 2424 } 2425 2426 2427 /** 2428 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property 2429 * @wpa_s: %wpa_supplicant network interface data 2430 * @property: indicates which property has changed 2431 * @id: unique BSS identifier 2432 * 2433 * Sends PropertyChanged signals with path, interface, and arguments depending 2434 * on which property has changed. 2435 */ 2436 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s, 2437 enum wpas_dbus_bss_prop property, 2438 unsigned int id) 2439 { 2440 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 2441 char *prop; 2442 2443 if (!wpa_s->dbus_new_path) 2444 return; 2445 2446 switch (property) { 2447 case WPAS_DBUS_BSS_PROP_SIGNAL: 2448 prop = "Signal"; 2449 break; 2450 case WPAS_DBUS_BSS_PROP_FREQ: 2451 prop = "Frequency"; 2452 break; 2453 case WPAS_DBUS_BSS_PROP_MODE: 2454 prop = "Mode"; 2455 break; 2456 case WPAS_DBUS_BSS_PROP_PRIVACY: 2457 prop = "Privacy"; 2458 break; 2459 case WPAS_DBUS_BSS_PROP_RATES: 2460 prop = "Rates"; 2461 break; 2462 case WPAS_DBUS_BSS_PROP_WPA: 2463 prop = "WPA"; 2464 break; 2465 case WPAS_DBUS_BSS_PROP_RSN: 2466 prop = "RSN"; 2467 break; 2468 case WPAS_DBUS_BSS_PROP_WPS: 2469 prop = "WPS"; 2470 break; 2471 case WPAS_DBUS_BSS_PROP_IES: 2472 prop = "IEs"; 2473 break; 2474 case WPAS_DBUS_BSS_PROP_AGE: 2475 prop = "Age"; 2476 break; 2477 case WPAS_DBUS_BSS_PROP_ANQP: 2478 prop = "ANQP"; 2479 break; 2480 default: 2481 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 2482 __func__, property); 2483 return; 2484 } 2485 2486 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 2487 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2488 wpa_s->dbus_new_path, id); 2489 2490 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 2491 WPAS_DBUS_NEW_IFACE_BSS, prop); 2492 } 2493 2494 2495 /** 2496 * wpas_dbus_sta_signal_prop_changed - Signals change of STA property 2497 * @wpa_s: %wpa_supplicant network interface data 2498 * @property: indicates which property has changed 2499 * @address: unique BSS identifier 2500 * 2501 * Sends PropertyChanged signals with path, interface, and arguments depending 2502 * on which property has changed. 2503 */ 2504 void wpas_dbus_sta_signal_prop_changed(struct wpa_supplicant *wpa_s, 2505 enum wpas_dbus_bss_prop property, 2506 u8 address[ETH_ALEN]) 2507 { 2508 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 2509 char *prop; 2510 2511 switch (property) { 2512 case WPAS_DBUS_STA_PROP_ADDRESS: 2513 prop = "Address"; 2514 break; 2515 default: 2516 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 2517 __func__, property); 2518 return; 2519 } 2520 2521 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 2522 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, 2523 wpa_s->dbus_new_path, MAC2STR(address)); 2524 2525 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 2526 WPAS_DBUS_NEW_IFACE_STA, prop); 2527 } 2528 2529 2530 /** 2531 * wpas_dbus_signal_debug_level_changed - Signals change of debug param 2532 * @global: wpa_global structure 2533 * 2534 * Sends PropertyChanged signals informing that debug level has changed. 2535 */ 2536 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global) 2537 { 2538 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2539 WPAS_DBUS_NEW_INTERFACE, 2540 "DebugLevel"); 2541 } 2542 2543 2544 /** 2545 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param 2546 * @global: wpa_global structure 2547 * 2548 * Sends PropertyChanged signals informing that debug timestamp has changed. 2549 */ 2550 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global) 2551 { 2552 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2553 WPAS_DBUS_NEW_INTERFACE, 2554 "DebugTimestamp"); 2555 } 2556 2557 2558 /** 2559 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param 2560 * @global: wpa_global structure 2561 * 2562 * Sends PropertyChanged signals informing that debug show_keys has changed. 2563 */ 2564 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global) 2565 { 2566 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2567 WPAS_DBUS_NEW_INTERFACE, 2568 "DebugShowKeys"); 2569 } 2570 2571 2572 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc, 2573 void *priv, 2574 WPADBusArgumentFreeFunction priv_free, 2575 const struct wpa_dbus_method_desc *methods, 2576 const struct wpa_dbus_property_desc *properties, 2577 const struct wpa_dbus_signal_desc *signals) 2578 { 2579 int n; 2580 2581 obj_desc->user_data = priv; 2582 obj_desc->user_data_free_func = priv_free; 2583 obj_desc->methods = methods; 2584 obj_desc->properties = properties; 2585 obj_desc->signals = signals; 2586 2587 for (n = 0; properties && properties->dbus_property; properties++) 2588 n++; 2589 2590 obj_desc->prop_changed_flags = os_zalloc(n); 2591 if (!obj_desc->prop_changed_flags) 2592 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers", 2593 __func__); 2594 } 2595 2596 2597 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = { 2598 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE, 2599 (WPADBusMethodHandler) wpas_dbus_handler_create_interface, 2600 { 2601 { "args", "a{sv}", ARG_IN }, 2602 { "path", "o", ARG_OUT }, 2603 END_ARGS 2604 } 2605 }, 2606 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE, 2607 (WPADBusMethodHandler) wpas_dbus_handler_remove_interface, 2608 { 2609 { "path", "o", ARG_IN }, 2610 END_ARGS 2611 } 2612 }, 2613 { "GetInterface", WPAS_DBUS_NEW_INTERFACE, 2614 (WPADBusMethodHandler) wpas_dbus_handler_get_interface, 2615 { 2616 { "ifname", "s", ARG_IN }, 2617 { "path", "o", ARG_OUT }, 2618 END_ARGS 2619 } 2620 }, 2621 { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE, 2622 (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect, 2623 { 2624 END_ARGS 2625 } 2626 }, 2627 { NULL, NULL, NULL, { END_ARGS } } 2628 }; 2629 2630 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = { 2631 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s", 2632 wpas_dbus_getter_debug_level, 2633 wpas_dbus_setter_debug_level, 2634 NULL 2635 }, 2636 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b", 2637 wpas_dbus_getter_debug_timestamp, 2638 wpas_dbus_setter_debug_timestamp, 2639 NULL 2640 }, 2641 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b", 2642 wpas_dbus_getter_debug_show_keys, 2643 wpas_dbus_setter_debug_show_keys, 2644 NULL 2645 }, 2646 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao", 2647 wpas_dbus_getter_interfaces, 2648 NULL, 2649 NULL 2650 }, 2651 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as", 2652 wpas_dbus_getter_eap_methods, 2653 NULL, 2654 NULL 2655 }, 2656 { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as", 2657 wpas_dbus_getter_global_capabilities, 2658 NULL, 2659 NULL 2660 }, 2661 #ifdef CONFIG_WIFI_DISPLAY 2662 { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay", 2663 wpas_dbus_getter_global_wfd_ies, 2664 wpas_dbus_setter_global_wfd_ies, 2665 NULL 2666 }, 2667 #endif /* CONFIG_WIFI_DISPLAY */ 2668 { NULL, NULL, NULL, NULL, NULL, NULL } 2669 }; 2670 2671 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = { 2672 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE, 2673 { 2674 { "path", "o", ARG_OUT }, 2675 { "properties", "a{sv}", ARG_OUT }, 2676 END_ARGS 2677 } 2678 }, 2679 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE, 2680 { 2681 { "path", "o", ARG_OUT }, 2682 END_ARGS 2683 } 2684 }, 2685 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2686 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE, 2687 { 2688 { "properties", "a{sv}", ARG_OUT }, 2689 END_ARGS 2690 } 2691 }, 2692 { NULL, NULL, { END_ARGS } } 2693 }; 2694 2695 2696 static char * uscore_to_dbus(const char *uscore) 2697 { 2698 const char *p = uscore; 2699 char *str, *s; 2700 dbus_bool_t last_was_uscore = TRUE; 2701 2702 s = str = os_zalloc(os_strlen(uscore) + 1); 2703 if (!str) 2704 return NULL; 2705 while (p && *p) { 2706 if (*p == '_') { 2707 last_was_uscore = TRUE; 2708 } else { 2709 *s++ = last_was_uscore ? toupper(*p) : *p; 2710 last_was_uscore = FALSE; 2711 } 2712 p++; 2713 } 2714 2715 return str; 2716 } 2717 2718 2719 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv); 2720 2721 2722 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv) 2723 { 2724 int idx = priv->globals_start; 2725 2726 /* Free all allocated property values */ 2727 while (priv->all_interface_properties[idx].dbus_property) 2728 os_free((char *) 2729 priv->all_interface_properties[idx++].dbus_property); 2730 os_free((char *) priv->all_interface_properties); 2731 } 2732 2733 2734 /** 2735 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface 2736 * @global: Pointer to global data from wpa_supplicant_init() 2737 * Returns: 0 on success or -1 on failure 2738 * 2739 * Initialize the dbus control interface for wpa_supplicant and start 2740 * receiving commands from external programs over the bus. 2741 */ 2742 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv) 2743 { 2744 struct wpa_dbus_object_desc *obj_desc; 2745 int ret; 2746 2747 ret = wpa_dbus_ctrl_iface_props_init(priv); 2748 if (ret < 0) { 2749 wpa_printf(MSG_ERROR, 2750 "dbus: Not enough memory to init interface properties"); 2751 return -1; 2752 } 2753 2754 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2755 if (!obj_desc) { 2756 wpa_printf(MSG_ERROR, 2757 "Not enough memory to create object description"); 2758 goto error; 2759 } 2760 2761 wpas_dbus_register(obj_desc, priv->global, NULL, 2762 wpas_dbus_global_methods, 2763 wpas_dbus_global_properties, 2764 wpas_dbus_global_signals); 2765 2766 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'", 2767 WPAS_DBUS_NEW_PATH); 2768 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH, 2769 WPAS_DBUS_NEW_SERVICE, 2770 obj_desc); 2771 if (ret < 0) { 2772 free_dbus_object_desc(obj_desc); 2773 goto error; 2774 } 2775 2776 priv->dbus_new_initialized = 1; 2777 return 0; 2778 2779 error: 2780 wpa_dbus_ctrl_iface_props_deinit(priv); 2781 return -1; 2782 } 2783 2784 2785 /** 2786 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for 2787 * wpa_supplicant 2788 * @priv: Pointer to dbus private data from wpas_dbus_init() 2789 * 2790 * Deinitialize the dbus control interface that was initialized with 2791 * wpas_dbus_ctrl_iface_init(). 2792 */ 2793 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv) 2794 { 2795 if (!priv->dbus_new_initialized) 2796 return; 2797 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'", 2798 WPAS_DBUS_NEW_PATH); 2799 dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH); 2800 wpa_dbus_ctrl_iface_props_deinit(priv); 2801 } 2802 2803 2804 static void wpa_dbus_free(void *ptr) 2805 { 2806 os_free(ptr); 2807 } 2808 2809 2810 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = { 2811 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}", 2812 wpas_dbus_getter_network_properties, 2813 wpas_dbus_setter_network_properties, 2814 NULL 2815 }, 2816 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b", 2817 wpas_dbus_getter_enabled, 2818 wpas_dbus_setter_enabled, 2819 NULL 2820 }, 2821 { NULL, NULL, NULL, NULL, NULL, NULL } 2822 }; 2823 2824 2825 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = { 2826 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2827 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK, 2828 { 2829 { "properties", "a{sv}", ARG_OUT }, 2830 END_ARGS 2831 } 2832 }, 2833 { NULL, NULL, { END_ARGS } } 2834 }; 2835 2836 2837 /** 2838 * wpas_dbus_register_network - Register a configured network with dbus 2839 * @wpa_s: wpa_supplicant interface structure 2840 * @ssid: network configuration data 2841 * Returns: 0 on success, -1 on failure 2842 * 2843 * Registers network representing object with dbus 2844 */ 2845 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s, 2846 struct wpa_ssid *ssid) 2847 { 2848 struct wpas_dbus_priv *ctrl_iface; 2849 struct wpa_dbus_object_desc *obj_desc; 2850 struct network_handler_args *arg; 2851 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2852 2853 #ifdef CONFIG_P2P 2854 /* 2855 * If it is a persistent group register it as such. 2856 * This is to handle cases where an interface is being initialized 2857 * with a list of networks read from config. 2858 */ 2859 if (network_is_persistent_group(ssid)) 2860 return wpas_dbus_register_persistent_group(wpa_s, ssid); 2861 #endif /* CONFIG_P2P */ 2862 2863 /* Do nothing if the control interface is not turned on */ 2864 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 2865 return 0; 2866 ctrl_iface = wpa_s->global->dbus; 2867 if (ctrl_iface == NULL) 2868 return 0; 2869 2870 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2871 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2872 wpa_s->dbus_new_path, ssid->id); 2873 2874 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'", 2875 net_obj_path); 2876 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2877 if (!obj_desc) { 2878 wpa_printf(MSG_ERROR, 2879 "Not enough memory to create object description"); 2880 goto err; 2881 } 2882 2883 /* allocate memory for handlers arguments */ 2884 arg = os_zalloc(sizeof(struct network_handler_args)); 2885 if (!arg) { 2886 wpa_printf(MSG_ERROR, 2887 "Not enough memory to create arguments for method"); 2888 goto err; 2889 } 2890 2891 arg->wpa_s = wpa_s; 2892 arg->ssid = ssid; 2893 2894 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2895 wpas_dbus_network_properties, 2896 wpas_dbus_network_signals); 2897 2898 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path, 2899 wpa_s->ifname, obj_desc)) 2900 goto err; 2901 2902 wpas_dbus_signal_network_added(wpa_s, ssid->id); 2903 2904 return 0; 2905 2906 err: 2907 free_dbus_object_desc(obj_desc); 2908 return -1; 2909 } 2910 2911 2912 /** 2913 * wpas_dbus_unregister_network - Unregister a configured network from dbus 2914 * @wpa_s: wpa_supplicant interface structure 2915 * @nid: network id 2916 * Returns: 0 on success, -1 on failure 2917 * 2918 * Unregisters network representing object from dbus 2919 */ 2920 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid) 2921 { 2922 struct wpas_dbus_priv *ctrl_iface; 2923 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2924 int ret; 2925 #ifdef CONFIG_P2P 2926 struct wpa_ssid *ssid; 2927 2928 ssid = wpa_config_get_network(wpa_s->conf, nid); 2929 2930 /* If it is a persistent group unregister it as such */ 2931 if (ssid && network_is_persistent_group(ssid)) 2932 return wpas_dbus_unregister_persistent_group(wpa_s, nid); 2933 #endif /* CONFIG_P2P */ 2934 2935 /* Do nothing if the control interface is not turned on */ 2936 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL) 2937 return 0; 2938 ctrl_iface = wpa_s->global->dbus; 2939 if (ctrl_iface == NULL) 2940 return 0; 2941 2942 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2943 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2944 wpa_s->dbus_new_path, nid); 2945 2946 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'", 2947 net_obj_path); 2948 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path); 2949 2950 if (!ret) 2951 wpas_dbus_signal_network_removed(wpa_s, nid); 2952 2953 return ret; 2954 } 2955 2956 2957 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = { 2958 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2959 wpas_dbus_getter_bss_ssid, 2960 NULL, 2961 NULL 2962 }, 2963 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2964 wpas_dbus_getter_bss_bssid, 2965 NULL, 2966 NULL 2967 }, 2968 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b", 2969 wpas_dbus_getter_bss_privacy, 2970 NULL, 2971 NULL 2972 }, 2973 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s", 2974 wpas_dbus_getter_bss_mode, 2975 NULL, 2976 NULL 2977 }, 2978 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n", 2979 wpas_dbus_getter_bss_signal, 2980 NULL, 2981 NULL 2982 }, 2983 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q", 2984 wpas_dbus_getter_bss_frequency, 2985 NULL, 2986 NULL 2987 }, 2988 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au", 2989 wpas_dbus_getter_bss_rates, 2990 NULL, 2991 NULL 2992 }, 2993 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2994 wpas_dbus_getter_bss_wpa, 2995 NULL, 2996 NULL 2997 }, 2998 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2999 wpas_dbus_getter_bss_rsn, 3000 NULL, 3001 NULL 3002 }, 3003 { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 3004 wpas_dbus_getter_bss_wps, 3005 NULL, 3006 NULL 3007 }, 3008 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay", 3009 wpas_dbus_getter_bss_ies, 3010 NULL, 3011 NULL 3012 }, 3013 { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u", 3014 wpas_dbus_getter_bss_age, 3015 NULL, 3016 NULL 3017 }, 3018 {"ANQP", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 3019 wpas_dbus_getter_bss_anqp, 3020 NULL, 3021 NULL, 3022 }, 3023 { NULL, NULL, NULL, NULL, NULL, NULL } 3024 }; 3025 3026 3027 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = { 3028 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3029 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS, 3030 { 3031 { "properties", "a{sv}", ARG_OUT }, 3032 END_ARGS 3033 } 3034 }, 3035 { NULL, NULL, { END_ARGS } } 3036 }; 3037 3038 3039 /** 3040 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus 3041 * @wpa_s: wpa_supplicant interface structure 3042 * @bssid: scanned network bssid 3043 * @id: unique BSS identifier 3044 * Returns: 0 on success, -1 on failure 3045 * 3046 * Unregisters BSS representing object from dbus 3047 */ 3048 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s, 3049 u8 bssid[ETH_ALEN], unsigned int id) 3050 { 3051 struct wpas_dbus_priv *ctrl_iface; 3052 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3053 3054 /* Do nothing if the control interface is not turned on */ 3055 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 3056 return 0; 3057 ctrl_iface = wpa_s->global->dbus; 3058 if (ctrl_iface == NULL) 3059 return 0; 3060 3061 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3062 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 3063 wpa_s->dbus_new_path, id); 3064 3065 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'", 3066 bss_obj_path); 3067 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) { 3068 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s", 3069 bss_obj_path); 3070 return -1; 3071 } 3072 3073 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path); 3074 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 3075 3076 return 0; 3077 } 3078 3079 3080 /** 3081 * wpas_dbus_register_bss - Register a scanned BSS with dbus 3082 * @wpa_s: wpa_supplicant interface structure 3083 * @bssid: scanned network bssid 3084 * @id: unique BSS identifier 3085 * Returns: 0 on success, -1 on failure 3086 * 3087 * Registers BSS representing object with dbus 3088 */ 3089 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, 3090 u8 bssid[ETH_ALEN], unsigned int id) 3091 { 3092 struct wpas_dbus_priv *ctrl_iface; 3093 struct wpa_dbus_object_desc *obj_desc; 3094 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3095 struct bss_handler_args *arg; 3096 3097 /* Do nothing if the control interface is not turned on */ 3098 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 3099 return 0; 3100 ctrl_iface = wpa_s->global->dbus; 3101 if (ctrl_iface == NULL) 3102 return 0; 3103 3104 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3105 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 3106 wpa_s->dbus_new_path, id); 3107 3108 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3109 if (!obj_desc) { 3110 wpa_printf(MSG_ERROR, 3111 "Not enough memory to create object description"); 3112 goto err; 3113 } 3114 3115 arg = os_zalloc(sizeof(struct bss_handler_args)); 3116 if (!arg) { 3117 wpa_printf(MSG_ERROR, 3118 "Not enough memory to create arguments for handler"); 3119 goto err; 3120 } 3121 arg->wpa_s = wpa_s; 3122 arg->id = id; 3123 3124 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 3125 wpas_dbus_bss_properties, 3126 wpas_dbus_bss_signals); 3127 3128 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'", 3129 bss_obj_path); 3130 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path, 3131 wpa_s->ifname, obj_desc)) { 3132 wpa_printf(MSG_ERROR, 3133 "Cannot register BSSID dbus object %s.", 3134 bss_obj_path); 3135 goto err; 3136 } 3137 3138 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path); 3139 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 3140 3141 return 0; 3142 3143 err: 3144 free_dbus_object_desc(obj_desc); 3145 return -1; 3146 } 3147 3148 3149 static const struct wpa_dbus_property_desc wpas_dbus_sta_properties[] = { 3150 { "Address", WPAS_DBUS_NEW_IFACE_STA, "ay", 3151 wpas_dbus_getter_sta_address, 3152 NULL, NULL 3153 }, 3154 { "AID", WPAS_DBUS_NEW_IFACE_STA, "q", 3155 wpas_dbus_getter_sta_aid, 3156 NULL, NULL 3157 }, 3158 { "Capabilities", WPAS_DBUS_NEW_IFACE_STA, "q", 3159 wpas_dbus_getter_sta_caps, 3160 NULL, NULL 3161 }, 3162 { "RxPackets", WPAS_DBUS_NEW_IFACE_STA, "t", 3163 wpas_dbus_getter_sta_rx_packets, 3164 NULL, NULL 3165 }, 3166 { "TxPackets", WPAS_DBUS_NEW_IFACE_STA, "t", 3167 wpas_dbus_getter_sta_tx_packets, 3168 NULL, NULL 3169 }, 3170 { "RxBytes", WPAS_DBUS_NEW_IFACE_STA, "t", 3171 wpas_dbus_getter_sta_rx_bytes, 3172 NULL, NULL 3173 }, 3174 { "TxBytes", WPAS_DBUS_NEW_IFACE_STA, "t", 3175 wpas_dbus_getter_sta_tx_bytes, 3176 NULL, NULL 3177 }, 3178 { NULL, NULL, NULL, NULL, NULL, NULL } 3179 }; 3180 3181 3182 static const struct wpa_dbus_signal_desc wpas_dbus_sta_signals[] = { 3183 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3184 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_STA, 3185 { 3186 { "properties", "a{sv}", ARG_OUT }, 3187 END_ARGS 3188 } 3189 }, 3190 { NULL, NULL, { END_ARGS } } 3191 }; 3192 3193 3194 /** 3195 * wpas_dbus_unregister_sta - Unregister a connected station from dbus 3196 * @wpa_s: wpa_supplicant interface structure 3197 * @sta: station MAC address 3198 * Returns: 0 on success, -1 on failure 3199 * 3200 * Unregisters STA representing object from dbus. 3201 */ 3202 int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta) 3203 { 3204 struct wpas_dbus_priv *ctrl_iface; 3205 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3206 3207 /* Do nothing if the control interface is not turned on */ 3208 if (!wpa_s || !wpa_s->global) 3209 return 0; 3210 ctrl_iface = wpa_s->global->dbus; 3211 if (!ctrl_iface) 3212 return 0; 3213 3214 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3215 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, 3216 wpa_s->dbus_new_path, MAC2STR(sta)); 3217 3218 wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'", 3219 station_obj_path); 3220 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, 3221 station_obj_path)) { 3222 wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s", 3223 station_obj_path); 3224 return -1; 3225 } 3226 3227 wpas_dbus_signal_station_removed(wpa_s, station_obj_path); 3228 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS); 3229 3230 return 0; 3231 } 3232 3233 3234 /** 3235 * wpas_dbus_register_sta - Register a connected station with dbus 3236 * @wpa_s: wpa_supplicant interface structure 3237 * @sta: station MAC address 3238 * Returns: 0 on success, -1 on failure 3239 * 3240 * Registers STA representing object with dbus. 3241 */ 3242 int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta) 3243 { 3244 struct wpas_dbus_priv *ctrl_iface; 3245 struct wpa_dbus_object_desc *obj_desc; 3246 char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 3247 struct sta_handler_args *arg; 3248 3249 /* Do nothing if the control interface is not turned on */ 3250 if (!wpa_s || !wpa_s->global) 3251 return 0; 3252 ctrl_iface = wpa_s->global->dbus; 3253 if (!ctrl_iface) 3254 return 0; 3255 3256 os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3257 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, 3258 wpa_s->dbus_new_path, MAC2STR(sta)); 3259 3260 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3261 if (!obj_desc) { 3262 wpa_printf(MSG_ERROR, 3263 "Not enough memory to create object description"); 3264 goto err; 3265 } 3266 3267 arg = os_zalloc(sizeof(struct sta_handler_args)); 3268 if (!arg) { 3269 wpa_printf(MSG_ERROR, 3270 "Not enough memory to create arguments for handler"); 3271 goto err; 3272 } 3273 arg->wpa_s = wpa_s; 3274 arg->sta = sta; 3275 3276 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 3277 wpas_dbus_sta_properties, wpas_dbus_sta_signals); 3278 3279 wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'", 3280 station_obj_path); 3281 if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path, 3282 wpa_s->ifname, obj_desc)) { 3283 wpa_printf(MSG_ERROR, 3284 "Cannot register STA dbus object %s", 3285 station_obj_path); 3286 goto err; 3287 } 3288 3289 wpas_dbus_signal_station_added(wpa_s, station_obj_path); 3290 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS); 3291 3292 return 0; 3293 3294 err: 3295 free_dbus_object_desc(obj_desc); 3296 return -1; 3297 } 3298 3299 3300 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { 3301 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE, 3302 (WPADBusMethodHandler) wpas_dbus_handler_scan, 3303 { 3304 { "args", "a{sv}", ARG_IN }, 3305 END_ARGS 3306 } 3307 }, 3308 { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE, 3309 (WPADBusMethodHandler) wpas_dbus_handler_signal_poll, 3310 { 3311 { "args", "a{sv}", ARG_OUT }, 3312 END_ARGS 3313 } 3314 }, 3315 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 3316 (WPADBusMethodHandler) wpas_dbus_handler_disconnect, 3317 { 3318 END_ARGS 3319 } 3320 }, 3321 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 3322 (WPADBusMethodHandler) wpas_dbus_handler_add_network, 3323 { 3324 { "args", "a{sv}", ARG_IN }, 3325 { "path", "o", ARG_OUT }, 3326 END_ARGS 3327 } 3328 }, 3329 { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE, 3330 (WPADBusMethodHandler) wpas_dbus_handler_reassociate, 3331 { 3332 END_ARGS 3333 } 3334 }, 3335 { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE, 3336 (WPADBusMethodHandler) wpas_dbus_handler_reattach, 3337 { 3338 END_ARGS 3339 } 3340 }, 3341 { "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 3342 (WPADBusMethodHandler) wpas_dbus_handler_reconnect, 3343 { 3344 END_ARGS 3345 } 3346 }, 3347 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 3348 (WPADBusMethodHandler) wpas_dbus_handler_remove_network, 3349 { 3350 { "path", "o", ARG_IN }, 3351 END_ARGS 3352 } 3353 }, 3354 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE, 3355 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks, 3356 { 3357 END_ARGS 3358 } 3359 }, 3360 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 3361 (WPADBusMethodHandler) wpas_dbus_handler_select_network, 3362 { 3363 { "path", "o", ARG_IN }, 3364 END_ARGS 3365 } 3366 }, 3367 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE, 3368 (WPADBusMethodHandler) wpas_dbus_handler_network_reply, 3369 { 3370 { "path", "o", ARG_IN }, 3371 { "field", "s", ARG_IN }, 3372 { "value", "s", ARG_IN }, 3373 END_ARGS 3374 } 3375 }, 3376 { "Roam", WPAS_DBUS_NEW_IFACE_INTERFACE, 3377 (WPADBusMethodHandler) wpas_dbus_handler_roam, 3378 { 3379 { "addr", "s", ARG_IN }, 3380 END_ARGS 3381 } 3382 }, 3383 3384 #ifndef CONFIG_NO_CONFIG_BLOBS 3385 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 3386 (WPADBusMethodHandler) wpas_dbus_handler_add_blob, 3387 { 3388 { "name", "s", ARG_IN }, 3389 { "data", "ay", ARG_IN }, 3390 END_ARGS 3391 } 3392 }, 3393 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 3394 (WPADBusMethodHandler) wpas_dbus_handler_get_blob, 3395 { 3396 { "name", "s", ARG_IN }, 3397 { "data", "ay", ARG_OUT }, 3398 END_ARGS 3399 } 3400 }, 3401 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 3402 (WPADBusMethodHandler) wpas_dbus_handler_remove_blob, 3403 { 3404 { "name", "s", ARG_IN }, 3405 END_ARGS 3406 } 3407 }, 3408 #endif /* CONFIG_NO_CONFIG_BLOBS */ 3409 { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, 3410 (WPADBusMethodHandler) 3411 wpas_dbus_handler_set_pkcs11_engine_and_module_path, 3412 { 3413 { "pkcs11_engine_path", "s", ARG_IN }, 3414 { "pkcs11_module_path", "s", ARG_IN }, 3415 END_ARGS 3416 } 3417 }, 3418 #ifdef CONFIG_WPS 3419 { "Start", WPAS_DBUS_NEW_IFACE_WPS, 3420 (WPADBusMethodHandler) wpas_dbus_handler_wps_start, 3421 { 3422 { "args", "a{sv}", ARG_IN }, 3423 { "output", "a{sv}", ARG_OUT }, 3424 END_ARGS 3425 } 3426 }, 3427 { "Cancel", WPAS_DBUS_NEW_IFACE_WPS, 3428 (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel, 3429 { 3430 END_ARGS 3431 } 3432 }, 3433 #endif /* CONFIG_WPS */ 3434 #ifdef CONFIG_P2P 3435 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3436 (WPADBusMethodHandler) wpas_dbus_handler_p2p_find, 3437 { 3438 { "args", "a{sv}", ARG_IN }, 3439 END_ARGS 3440 } 3441 }, 3442 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3443 (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find, 3444 { 3445 END_ARGS 3446 } 3447 }, 3448 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3449 (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen, 3450 { 3451 { "timeout", "i", ARG_IN }, 3452 END_ARGS 3453 } 3454 }, 3455 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3456 (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten, 3457 { 3458 { "args", "a{sv}", ARG_IN }, 3459 END_ARGS 3460 } 3461 }, 3462 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3463 (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request, 3464 { 3465 { "args", "a{sv}", ARG_IN }, 3466 END_ARGS 3467 } 3468 }, 3469 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3470 (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req, 3471 { 3472 { "peer", "o", ARG_IN }, 3473 { "config_method", "s", ARG_IN }, 3474 END_ARGS 3475 } 3476 }, 3477 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3478 (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect, 3479 { 3480 { "args", "a{sv}", ARG_IN }, 3481 { "generated_pin", "s", ARG_OUT }, 3482 END_ARGS 3483 } 3484 }, 3485 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3486 (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add, 3487 { 3488 { "args", "a{sv}", ARG_IN }, 3489 END_ARGS 3490 } 3491 }, 3492 { "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3493 (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel, 3494 { 3495 END_ARGS 3496 } 3497 }, 3498 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3499 (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite, 3500 { 3501 { "args", "a{sv}", ARG_IN }, 3502 END_ARGS 3503 } 3504 }, 3505 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3506 (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect, 3507 { 3508 END_ARGS 3509 } 3510 }, 3511 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3512 (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer, 3513 { 3514 { "peer", "o", ARG_IN }, 3515 END_ARGS 3516 } 3517 }, 3518 { "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3519 (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client, 3520 { 3521 { "args", "a{sv}", ARG_IN }, 3522 END_ARGS 3523 } 3524 }, 3525 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3526 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush, 3527 { 3528 END_ARGS 3529 } 3530 }, 3531 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3532 (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service, 3533 { 3534 { "args", "a{sv}", ARG_IN }, 3535 END_ARGS 3536 } 3537 }, 3538 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3539 (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service, 3540 { 3541 { "args", "a{sv}", ARG_IN }, 3542 END_ARGS 3543 } 3544 }, 3545 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3546 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service, 3547 { 3548 END_ARGS 3549 } 3550 }, 3551 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3552 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req, 3553 { 3554 { "args", "a{sv}", ARG_IN }, 3555 { "ref", "t", ARG_OUT }, 3556 END_ARGS 3557 } 3558 }, 3559 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3560 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res, 3561 { 3562 { "args", "a{sv}", ARG_IN }, 3563 END_ARGS 3564 } 3565 }, 3566 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3567 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req, 3568 { 3569 { "args", "t", ARG_IN }, 3570 END_ARGS 3571 } 3572 }, 3573 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3574 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update, 3575 { 3576 END_ARGS 3577 } 3578 }, 3579 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3580 (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external, 3581 { 3582 { "arg", "i", ARG_IN }, 3583 END_ARGS 3584 } 3585 }, 3586 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3587 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group, 3588 { 3589 { "args", "a{sv}", ARG_IN }, 3590 { "path", "o", ARG_OUT }, 3591 END_ARGS 3592 } 3593 }, 3594 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3595 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group, 3596 { 3597 { "path", "o", ARG_IN }, 3598 END_ARGS 3599 } 3600 }, 3601 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3602 (WPADBusMethodHandler) 3603 wpas_dbus_handler_remove_all_persistent_groups, 3604 { 3605 END_ARGS 3606 } 3607 }, 3608 #endif /* CONFIG_P2P */ 3609 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, 3610 (WPADBusMethodHandler) wpas_dbus_handler_flush_bss, 3611 { 3612 { "age", "u", ARG_IN }, 3613 END_ARGS 3614 } 3615 }, 3616 #ifdef CONFIG_AP 3617 { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 3618 (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq, 3619 { 3620 END_ARGS 3621 } 3622 }, 3623 { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 3624 (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq, 3625 { 3626 END_ARGS 3627 } 3628 }, 3629 #endif /* CONFIG_AP */ 3630 { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE, 3631 (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff, 3632 { 3633 END_ARGS 3634 } 3635 }, 3636 { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE, 3637 (WPADBusMethodHandler) wpas_dbus_handler_eap_logon, 3638 { 3639 END_ARGS 3640 } 3641 }, 3642 #ifdef CONFIG_AUTOSCAN 3643 { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE, 3644 (WPADBusMethodHandler) wpas_dbus_handler_autoscan, 3645 { 3646 { "arg", "s", ARG_IN }, 3647 END_ARGS 3648 } 3649 }, 3650 #endif /* CONFIG_AUTOSCAN */ 3651 #ifdef CONFIG_TDLS 3652 { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE, 3653 (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover, 3654 { 3655 { "peer_address", "s", ARG_IN }, 3656 END_ARGS 3657 } 3658 }, 3659 { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE, 3660 (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup, 3661 { 3662 { "peer_address", "s", ARG_IN }, 3663 END_ARGS 3664 } 3665 }, 3666 { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, 3667 (WPADBusMethodHandler) wpas_dbus_handler_tdls_status, 3668 { 3669 { "peer_address", "s", ARG_IN }, 3670 { "status", "s", ARG_OUT }, 3671 END_ARGS 3672 } 3673 }, 3674 { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE, 3675 (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown, 3676 { 3677 { "peer_address", "s", ARG_IN }, 3678 END_ARGS 3679 } 3680 }, 3681 { "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE, 3682 (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch, 3683 { 3684 { "args", "a{sv}", ARG_IN }, 3685 END_ARGS 3686 } 3687 }, 3688 { "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE, 3689 (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch, 3690 { 3691 { "peer_address", "s", ARG_IN }, 3692 END_ARGS 3693 } 3694 }, 3695 #endif /* CONFIG_TDLS */ 3696 { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE, 3697 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add, 3698 { 3699 { "frame_id", "i", ARG_IN }, 3700 { "ielems", "ay", ARG_IN }, 3701 END_ARGS 3702 } 3703 }, 3704 { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE, 3705 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get, 3706 { 3707 { "frame_id", "i", ARG_IN }, 3708 { "ielems", "ay", ARG_OUT }, 3709 END_ARGS 3710 } 3711 }, 3712 { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE, 3713 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove, 3714 { 3715 { "frame_id", "i", ARG_IN }, 3716 { "ielems", "ay", ARG_IN }, 3717 END_ARGS 3718 } 3719 }, 3720 #ifndef CONFIG_NO_CONFIG_WRITE 3721 { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE, 3722 (WPADBusMethodHandler) wpas_dbus_handler_save_config, 3723 { 3724 END_ARGS 3725 } 3726 }, 3727 #endif /* CONFIG_NO_CONFIG_WRITE */ 3728 { "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE, 3729 (WPADBusMethodHandler) wpas_dbus_handler_abort_scan, 3730 { 3731 END_ARGS 3732 } 3733 }, 3734 #ifdef CONFIG_INTERWORKING 3735 { "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE, 3736 (WPADBusMethodHandler) wpas_dbus_handler_add_cred, 3737 { 3738 { "args", "a{sv}", ARG_IN }, 3739 { "path", "o", ARG_OUT }, 3740 END_ARGS 3741 } 3742 }, 3743 { "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE, 3744 (WPADBusMethodHandler) wpas_dbus_handler_remove_cred, 3745 { 3746 { "path", "o", ARG_IN }, 3747 END_ARGS 3748 } 3749 }, 3750 { "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE, 3751 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds, 3752 { 3753 END_ARGS 3754 } 3755 }, 3756 { "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE, 3757 (WPADBusMethodHandler) wpas_dbus_handler_interworking_select, 3758 { 3759 END_ARGS 3760 } 3761 }, 3762 {"ANQPGet", WPAS_DBUS_NEW_IFACE_INTERFACE, 3763 (WPADBusMethodHandler) wpas_dbus_handler_anqp_get, 3764 { 3765 { "args", "a{sv}", ARG_IN }, 3766 END_ARGS 3767 }, 3768 }, 3769 #endif /* CONFIG_INTERWORKING */ 3770 { NULL, NULL, NULL, { END_ARGS } } 3771 }; 3772 3773 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { 3774 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}", 3775 wpas_dbus_getter_capabilities, 3776 NULL, 3777 NULL 3778 }, 3779 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3780 wpas_dbus_getter_state, 3781 NULL, 3782 NULL 3783 }, 3784 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 3785 wpas_dbus_getter_scanning, 3786 NULL, 3787 NULL 3788 }, 3789 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3790 wpas_dbus_getter_ap_scan, 3791 wpas_dbus_setter_ap_scan, 3792 NULL 3793 }, 3794 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3795 wpas_dbus_getter_bss_expire_age, 3796 wpas_dbus_setter_bss_expire_age, 3797 NULL 3798 }, 3799 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3800 wpas_dbus_getter_bss_expire_count, 3801 wpas_dbus_setter_bss_expire_count, 3802 NULL 3803 }, 3804 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3805 wpas_dbus_getter_country, 3806 wpas_dbus_setter_country, 3807 NULL 3808 }, 3809 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3810 wpas_dbus_getter_ifname, 3811 NULL, 3812 NULL 3813 }, 3814 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3815 wpas_dbus_getter_driver, 3816 NULL, 3817 NULL 3818 }, 3819 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3820 wpas_dbus_getter_bridge_ifname, 3821 wpas_dbus_setter_bridge_ifname, 3822 NULL 3823 }, 3824 { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3825 wpas_dbus_getter_config_file, 3826 NULL, 3827 NULL 3828 }, 3829 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 3830 wpas_dbus_getter_current_bss, 3831 NULL, 3832 NULL 3833 }, 3834 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 3835 wpas_dbus_getter_current_network, 3836 NULL, 3837 NULL 3838 }, 3839 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3840 wpas_dbus_getter_current_auth_mode, 3841 NULL, 3842 NULL 3843 }, 3844 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}", 3845 wpas_dbus_getter_blobs, 3846 NULL, 3847 NULL 3848 }, 3849 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 3850 wpas_dbus_getter_bsss, 3851 NULL, 3852 NULL 3853 }, 3854 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 3855 wpas_dbus_getter_networks, 3856 NULL, 3857 NULL 3858 }, 3859 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 3860 wpas_dbus_getter_fast_reauth, 3861 wpas_dbus_setter_fast_reauth, 3862 NULL 3863 }, 3864 { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3865 wpas_dbus_getter_scan_interval, 3866 wpas_dbus_setter_scan_interval, 3867 NULL 3868 }, 3869 { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3870 wpas_dbus_getter_pkcs11_engine_path, 3871 NULL, 3872 NULL 3873 }, 3874 { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3875 wpas_dbus_getter_pkcs11_module_path, 3876 NULL, 3877 NULL 3878 }, 3879 #ifdef CONFIG_WPS 3880 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b", 3881 wpas_dbus_getter_process_credentials, 3882 wpas_dbus_setter_process_credentials, 3883 NULL 3884 }, 3885 { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s", 3886 wpas_dbus_getter_config_methods, 3887 wpas_dbus_setter_config_methods, 3888 NULL 3889 }, 3890 { 3891 "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s", 3892 wpas_dbus_getter_wps_device_name, 3893 wpas_dbus_setter_wps_device_name, 3894 NULL 3895 }, 3896 { 3897 "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s", 3898 wpas_dbus_getter_wps_manufacturer, 3899 wpas_dbus_setter_wps_manufacturer, 3900 NULL 3901 }, 3902 { 3903 "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s", 3904 wpas_dbus_getter_wps_device_model_name, 3905 wpas_dbus_setter_wps_device_model_name, 3906 NULL 3907 }, 3908 { 3909 "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s", 3910 wpas_dbus_getter_wps_device_model_number, 3911 wpas_dbus_setter_wps_device_model_number, 3912 NULL 3913 }, 3914 { 3915 "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s", 3916 wpas_dbus_getter_wps_device_serial_number, 3917 wpas_dbus_setter_wps_device_serial_number, 3918 NULL 3919 }, 3920 { 3921 "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay", 3922 wpas_dbus_getter_wps_device_device_type, 3923 wpas_dbus_setter_wps_device_device_type, 3924 NULL 3925 }, 3926 #endif /* CONFIG_WPS */ 3927 #ifdef CONFIG_P2P 3928 { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}", 3929 wpas_dbus_getter_p2p_device_config, 3930 wpas_dbus_setter_p2p_device_config, 3931 NULL 3932 }, 3933 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 3934 wpas_dbus_getter_p2p_peers, 3935 NULL, 3936 NULL 3937 }, 3938 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s", 3939 wpas_dbus_getter_p2p_role, 3940 NULL, 3941 NULL 3942 }, 3943 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 3944 wpas_dbus_getter_p2p_group, 3945 NULL, 3946 NULL 3947 }, 3948 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 3949 wpas_dbus_getter_p2p_peergo, 3950 NULL, 3951 NULL 3952 }, 3953 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 3954 wpas_dbus_getter_persistent_groups, 3955 NULL, 3956 NULL 3957 }, 3958 #endif /* CONFIG_P2P */ 3959 { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3960 wpas_dbus_getter_disconnect_reason, 3961 NULL, 3962 NULL 3963 }, 3964 { "AuthStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3965 wpas_dbus_getter_auth_status_code, 3966 NULL, 3967 NULL 3968 }, 3969 { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3970 wpas_dbus_getter_assoc_status_code, 3971 NULL, 3972 NULL 3973 }, 3974 { 3975 "RoamTime", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3976 wpas_dbus_getter_roam_time, 3977 NULL, 3978 NULL 3979 }, 3980 { 3981 "RoamComplete", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 3982 wpas_dbus_getter_roam_complete, 3983 NULL, 3984 NULL 3985 }, 3986 { 3987 "SessionLength", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3988 wpas_dbus_getter_session_length, 3989 NULL, 3990 NULL 3991 }, 3992 { 3993 "BSSTMStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3994 wpas_dbus_getter_bss_tm_status, 3995 NULL, 3996 NULL 3997 }, 3998 #ifdef CONFIG_MESH 3999 { "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay", 4000 wpas_dbus_getter_mesh_peers, 4001 NULL, 4002 NULL 4003 }, 4004 { "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay", 4005 wpas_dbus_getter_mesh_group, 4006 NULL, 4007 NULL 4008 }, 4009 #endif /* CONFIG_MESH */ 4010 { "Stations", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 4011 wpas_dbus_getter_stas, 4012 NULL, 4013 NULL 4014 }, 4015 { "MACAddressRandomizationMask", WPAS_DBUS_NEW_IFACE_INTERFACE, 4016 "a{say}", 4017 wpas_dbus_getter_mac_address_randomization_mask, 4018 wpas_dbus_setter_mac_address_randomization_mask, 4019 NULL 4020 }, 4021 { "MACAddress", WPAS_DBUS_NEW_IFACE_INTERFACE, "ay", 4022 wpas_dbus_getter_mac_address, 4023 NULL, 4024 NULL, 4025 }, 4026 { "SignalChange", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}", 4027 wpas_dbus_getter_signal_change, 4028 NULL, 4029 NULL 4030 }, 4031 { NULL, NULL, NULL, NULL, NULL, NULL } 4032 }; 4033 4034 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { 4035 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE, 4036 { 4037 { "success", "b", ARG_OUT }, 4038 END_ARGS 4039 } 4040 }, 4041 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 4042 { 4043 { "path", "o", ARG_OUT }, 4044 { "properties", "a{sv}", ARG_OUT }, 4045 END_ARGS 4046 } 4047 }, 4048 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 4049 { 4050 { "path", "o", ARG_OUT }, 4051 END_ARGS 4052 } 4053 }, 4054 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 4055 { 4056 { "name", "s", ARG_OUT }, 4057 END_ARGS 4058 } 4059 }, 4060 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 4061 { 4062 { "name", "s", ARG_OUT }, 4063 END_ARGS 4064 } 4065 }, 4066 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 4067 { 4068 { "path", "o", ARG_OUT }, 4069 { "properties", "a{sv}", ARG_OUT }, 4070 END_ARGS 4071 } 4072 }, 4073 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 4074 { 4075 { "path", "o", ARG_OUT }, 4076 END_ARGS 4077 } 4078 }, 4079 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE, 4080 { 4081 { "path", "o", ARG_OUT }, 4082 END_ARGS 4083 } 4084 }, 4085 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 4086 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE, 4087 { 4088 { "properties", "a{sv}", ARG_OUT }, 4089 END_ARGS 4090 } 4091 }, 4092 #ifdef CONFIG_WPS 4093 { "Event", WPAS_DBUS_NEW_IFACE_WPS, 4094 { 4095 { "name", "s", ARG_OUT }, 4096 { "args", "a{sv}", ARG_OUT }, 4097 END_ARGS 4098 } 4099 }, 4100 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS, 4101 { 4102 { "credentials", "a{sv}", ARG_OUT }, 4103 END_ARGS 4104 } 4105 }, 4106 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 4107 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS, 4108 { 4109 { "properties", "a{sv}", ARG_OUT }, 4110 END_ARGS 4111 } 4112 }, 4113 #endif /* CONFIG_WPS */ 4114 #ifdef CONFIG_P2P 4115 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4116 { 4117 { "path", "o", ARG_OUT }, 4118 END_ARGS 4119 } 4120 }, 4121 { "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4122 { 4123 { "path", "o", ARG_OUT }, 4124 { "properties", "a{sv}", ARG_OUT }, 4125 END_ARGS 4126 } 4127 }, 4128 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4129 { 4130 { "path", "o", ARG_OUT }, 4131 END_ARGS 4132 } 4133 }, 4134 { "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4135 { 4136 END_ARGS 4137 } 4138 }, 4139 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4140 { 4141 { "peer_object", "o", ARG_OUT }, 4142 { "pin", "s", ARG_OUT }, 4143 END_ARGS 4144 } 4145 }, 4146 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4147 { 4148 { "peer_object", "o", ARG_OUT }, 4149 { "pin", "s", ARG_OUT }, 4150 END_ARGS 4151 } 4152 }, 4153 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4154 { 4155 { "peer_object", "o", ARG_OUT }, 4156 END_ARGS 4157 } 4158 }, 4159 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4160 { 4161 { "peer_object", "o", ARG_OUT }, 4162 END_ARGS 4163 } 4164 }, 4165 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4166 { 4167 { "peer_object", "o", ARG_OUT }, 4168 END_ARGS 4169 } 4170 }, 4171 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4172 { 4173 { "peer_object", "o", ARG_OUT }, 4174 END_ARGS 4175 } 4176 }, 4177 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4178 { 4179 { "peer_object", "o", ARG_OUT }, 4180 { "status", "i", ARG_OUT }, 4181 END_ARGS 4182 } 4183 }, 4184 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4185 { 4186 { "properties", "a{sv}", ARG_OUT }, 4187 END_ARGS 4188 } 4189 }, 4190 { "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4191 { 4192 { "reason", "s", ARG_OUT }, 4193 END_ARGS 4194 } 4195 }, 4196 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4197 { 4198 { "properties", "a{sv}", ARG_OUT }, 4199 END_ARGS 4200 } 4201 }, 4202 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4203 { 4204 { "properties", "a{sv}", ARG_OUT }, 4205 END_ARGS 4206 } 4207 }, 4208 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4209 { 4210 { "path", "o", ARG_OUT }, 4211 { "dev_passwd_id", "q", ARG_OUT }, 4212 { "device_go_intent", "y", ARG_OUT }, 4213 END_ARGS 4214 } 4215 }, 4216 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4217 { 4218 { "invite_result", "a{sv}", ARG_OUT }, 4219 END_ARGS 4220 } 4221 }, 4222 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4223 { 4224 { "properties", "a{sv}", ARG_OUT }, 4225 END_ARGS 4226 } 4227 }, 4228 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4229 { 4230 { "sd_request", "a{sv}", ARG_OUT }, 4231 END_ARGS 4232 } 4233 }, 4234 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4235 { 4236 { "sd_response", "a{sv}", ARG_OUT }, 4237 END_ARGS 4238 } 4239 }, 4240 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4241 { 4242 { "path", "o", ARG_OUT }, 4243 { "properties", "a{sv}", ARG_OUT }, 4244 END_ARGS 4245 } 4246 }, 4247 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4248 { 4249 { "path", "o", ARG_OUT }, 4250 END_ARGS 4251 } 4252 }, 4253 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4254 { 4255 { "name", "s", ARG_OUT }, 4256 { "args", "a{sv}", ARG_OUT }, 4257 END_ARGS 4258 } 4259 }, 4260 { "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4261 { 4262 { "properties", "a{sv}", ARG_OUT }, 4263 END_ARGS 4264 } 4265 }, 4266 #endif /* CONFIG_P2P */ 4267 #ifdef CONFIG_AP 4268 { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 4269 { 4270 { "args", "a{sv}", ARG_OUT }, 4271 END_ARGS 4272 } 4273 }, 4274 #endif /* CONFIG_AP */ 4275 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE, 4276 { 4277 { "certification", "a{sv}", ARG_OUT }, 4278 END_ARGS 4279 } 4280 }, 4281 { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE, 4282 { 4283 { "status", "s", ARG_OUT }, 4284 { "parameter", "s", ARG_OUT }, 4285 END_ARGS 4286 } 4287 }, 4288 { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE, 4289 { 4290 { "name", "s", ARG_OUT }, 4291 END_ARGS 4292 } 4293 }, 4294 { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE, 4295 { 4296 { "name", "s", ARG_OUT }, 4297 END_ARGS 4298 } 4299 }, 4300 { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 4301 { 4302 { "path", "o", ARG_OUT }, 4303 { "properties", "a{sv}", ARG_OUT }, 4304 END_ARGS 4305 } 4306 }, 4307 { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 4308 { 4309 { "path", "o", ARG_OUT }, 4310 END_ARGS 4311 } 4312 }, 4313 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 4314 { 4315 { "path", "o", ARG_OUT }, 4316 { "field", "s", ARG_OUT }, 4317 { "text", "s", ARG_OUT }, 4318 END_ARGS 4319 } 4320 }, 4321 #ifdef CONFIG_MESH 4322 { "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH, 4323 { 4324 { "args", "a{sv}", ARG_OUT }, 4325 END_ARGS 4326 } 4327 }, 4328 { "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH, 4329 { 4330 { "args", "a{sv}", ARG_OUT }, 4331 END_ARGS 4332 } 4333 }, 4334 { "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH, 4335 { 4336 { "args", "a{sv}", ARG_OUT }, 4337 END_ARGS 4338 } 4339 }, 4340 { "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH, 4341 { 4342 { "args", "a{sv}", ARG_OUT }, 4343 END_ARGS 4344 } 4345 }, 4346 #endif /* CONFIG_MESH */ 4347 #ifdef CONFIG_INTERWORKING 4348 { "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 4349 { 4350 { "bss", "o", ARG_OUT }, 4351 { "cred", "o", ARG_OUT }, 4352 { "properties", "a{sv}", ARG_OUT }, 4353 END_ARGS 4354 } 4355 }, 4356 { "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE, 4357 { 4358 END_ARGS 4359 } 4360 }, 4361 {"ANQPQueryDone", WPAS_DBUS_NEW_IFACE_INTERFACE, 4362 { 4363 { "addr", "s", ARG_OUT }, 4364 { "result", "s", ARG_OUT }, 4365 END_ARGS 4366 } 4367 }, 4368 #endif /* CONFIG_INTERWORKING */ 4369 #ifdef CONFIG_HS20 4370 { "HS20TermsAndConditions", WPAS_DBUS_NEW_IFACE_INTERFACE, 4371 { 4372 { "url", "s", ARG_OUT }, 4373 END_ARGS 4374 } 4375 }, 4376 #endif /* CONFIG_HS20 */ 4377 { NULL, NULL, { END_ARGS } } 4378 }; 4379 4380 4381 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv) 4382 { 4383 size_t all_size; 4384 unsigned int i, j, count, num_const, num_globals; 4385 const char *global_name; 4386 static const char * const ignored_globals[] = { 4387 "bss_expiration_age", "bss_expiration_scan_count", 4388 "ap_scan", "country", "fast_reauth", 4389 "pkcs11_engine_path", "pkcs11_module_path" 4390 }; 4391 4392 /* wpas_dbus_interface_properties terminates with a NULL element */ 4393 num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1; 4394 4395 num_globals = wpa_config_get_num_global_field_names(); 4396 priv->globals_start = num_const; 4397 4398 /* allocate enough for all properties + terminating NULL element */ 4399 all_size = (num_globals + num_const + 1) * 4400 sizeof(wpas_dbus_interface_properties[0]); 4401 priv->all_interface_properties = os_zalloc(all_size); 4402 if (!priv->all_interface_properties) { 4403 wpa_printf(MSG_ERROR, 4404 "dbus: Not enough memory for interface properties"); 4405 return -1; 4406 } 4407 4408 /* Copy constant interface properties to the start of the array */ 4409 os_memcpy(priv->all_interface_properties, 4410 wpas_dbus_interface_properties, 4411 sizeof(wpas_dbus_interface_properties)); 4412 4413 /* Dynamically construct interface global properties */ 4414 for (i = 0, count = num_const; i < num_globals; i++) { 4415 struct wpa_dbus_property_desc *desc; 4416 int no_var = 0; 4417 4418 /* ignore globals that are actually just methods */ 4419 global_name = wpa_config_get_global_field_name(i, &no_var); 4420 if (no_var) 4421 continue; 4422 /* Ignore fields already explicitly exposed */ 4423 for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) { 4424 if (os_strcmp(global_name, ignored_globals[j]) == 0) 4425 break; 4426 } 4427 if (j < ARRAY_SIZE(ignored_globals)) 4428 continue; 4429 4430 desc = &priv->all_interface_properties[count++]; 4431 desc->dbus_property = uscore_to_dbus(global_name); 4432 if (!desc->dbus_property) { 4433 wpa_printf(MSG_ERROR, 4434 "dbus: Not enough memory for D-Bus property name"); 4435 goto error; 4436 } 4437 desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE; 4438 desc->type = "s"; 4439 desc->getter = wpas_dbus_getter_iface_global; 4440 desc->setter = wpas_dbus_setter_iface_global; 4441 desc->data = global_name; 4442 } 4443 4444 return 0; 4445 4446 error: 4447 wpa_dbus_ctrl_iface_props_deinit(priv); 4448 return -1; 4449 } 4450 4451 4452 /** 4453 * wpas_dbus_register_interface - Register an interface with D-Bus 4454 * @wpa_s: wpa_supplicant interface structure 4455 * Returns: 0 on success, -1 on failure 4456 */ 4457 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s) 4458 { 4459 struct wpa_dbus_object_desc *obj_desc = NULL; 4460 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus; 4461 int next; 4462 4463 /* Do nothing if the control interface is not turned on */ 4464 if (ctrl_iface == NULL) 4465 return 0; 4466 4467 /* Create and set the interface's object path */ 4468 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 4469 if (wpa_s->dbus_new_path == NULL) 4470 return -1; 4471 next = ctrl_iface->next_objid++; 4472 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX, 4473 WPAS_DBUS_NEW_PATH_INTERFACES "/%u", 4474 next); 4475 4476 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 4477 if (!obj_desc) { 4478 wpa_printf(MSG_ERROR, 4479 "Not enough memory to create object description"); 4480 goto err; 4481 } 4482 4483 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods, 4484 ctrl_iface->all_interface_properties, 4485 wpas_dbus_interface_signals); 4486 4487 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", 4488 wpa_s->dbus_new_path); 4489 if (wpa_dbus_register_object_per_iface(ctrl_iface, 4490 wpa_s->dbus_new_path, 4491 wpa_s->ifname, obj_desc)) 4492 goto err; 4493 4494 wpas_dbus_signal_interface_added(wpa_s); 4495 4496 return 0; 4497 4498 err: 4499 os_free(wpa_s->dbus_new_path); 4500 wpa_s->dbus_new_path = NULL; 4501 free_dbus_object_desc(obj_desc); 4502 return -1; 4503 } 4504 4505 4506 /** 4507 * wpas_dbus_unregister_interface - Unregister the interface from D-Bus 4508 * @wpa_s: wpa_supplicant interface structure 4509 * Returns: 0 on success, -1 on failure 4510 */ 4511 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s) 4512 { 4513 struct wpas_dbus_priv *ctrl_iface; 4514 4515 /* Do nothing if the control interface is not turned on */ 4516 if (wpa_s == NULL || wpa_s->global == NULL) 4517 return 0; 4518 ctrl_iface = wpa_s->global->dbus; 4519 if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL) 4520 return 0; 4521 4522 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'", 4523 wpa_s->dbus_new_path); 4524 4525 #ifdef CONFIG_AP 4526 if (wpa_s->preq_notify_peer) { 4527 wpas_dbus_unsubscribe_noc(ctrl_iface); 4528 os_free(wpa_s->preq_notify_peer); 4529 wpa_s->preq_notify_peer = NULL; 4530 } 4531 #endif /* CONFIG_AP */ 4532 4533 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, 4534 wpa_s->dbus_new_path)) 4535 return -1; 4536 4537 wpas_dbus_signal_interface_removed(wpa_s); 4538 4539 os_free(wpa_s->dbus_new_path); 4540 wpa_s->dbus_new_path = NULL; 4541 4542 return 0; 4543 } 4544 4545 #ifdef CONFIG_P2P 4546 4547 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = { 4548 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4549 wpas_dbus_getter_p2p_peer_device_name, 4550 NULL, 4551 NULL 4552 }, 4553 { "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4554 wpas_dbus_getter_p2p_peer_manufacturer, 4555 NULL, 4556 NULL 4557 }, 4558 { "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4559 wpas_dbus_getter_p2p_peer_modelname, 4560 NULL, 4561 NULL 4562 }, 4563 { "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4564 wpas_dbus_getter_p2p_peer_modelnumber, 4565 NULL, 4566 NULL 4567 }, 4568 { "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 4569 wpas_dbus_getter_p2p_peer_serialnumber, 4570 NULL, 4571 NULL 4572 }, 4573 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4574 wpas_dbus_getter_p2p_peer_primary_device_type, 4575 NULL, 4576 NULL 4577 }, 4578 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q", 4579 wpas_dbus_getter_p2p_peer_config_method, 4580 NULL, 4581 NULL 4582 }, 4583 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i", 4584 wpas_dbus_getter_p2p_peer_level, 4585 NULL, 4586 NULL 4587 }, 4588 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 4589 wpas_dbus_getter_p2p_peer_device_capability, 4590 NULL, 4591 NULL 4592 }, 4593 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 4594 wpas_dbus_getter_p2p_peer_group_capability, 4595 NULL, 4596 NULL 4597 }, 4598 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 4599 wpas_dbus_getter_p2p_peer_secondary_device_types, 4600 NULL, 4601 NULL 4602 }, 4603 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 4604 wpas_dbus_getter_p2p_peer_vendor_extension, 4605 NULL, 4606 NULL 4607 }, 4608 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4609 wpas_dbus_getter_p2p_peer_ies, 4610 NULL, 4611 NULL 4612 }, 4613 { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4614 wpas_dbus_getter_p2p_peer_device_address, 4615 NULL, 4616 NULL 4617 }, 4618 { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao", 4619 wpas_dbus_getter_p2p_peer_groups, 4620 NULL, 4621 NULL 4622 }, 4623 { "VSIE", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4624 wpas_dbus_getter_p2p_peer_vsie, 4625 NULL, 4626 NULL 4627 }, 4628 { NULL, NULL, NULL, NULL, NULL, NULL } 4629 }; 4630 4631 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = { 4632 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 4633 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER, 4634 { 4635 { "properties", "a{sv}", ARG_OUT }, 4636 END_ARGS 4637 } 4638 }, 4639 { NULL, NULL, { END_ARGS } } 4640 }; 4641 4642 /** 4643 * wpas_dbus_signal_peer - Send a peer related event signal 4644 * @wpa_s: %wpa_supplicant network interface data 4645 * @dev: peer device object 4646 * @interface: name of the interface emitting this signal. 4647 * In case of peer objects, it would be emitted by either 4648 * the "interface object" or by "peer objects" 4649 * @sig_name: signal name - DeviceFound 4650 * @properties: Whether to add a second argument with object properties 4651 * 4652 * Notify listeners about event related with p2p peer device 4653 */ 4654 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s, 4655 const u8 *dev_addr, const char *interface, 4656 const char *sig_name, dbus_bool_t properties) 4657 { 4658 struct wpas_dbus_priv *iface; 4659 DBusMessage *msg; 4660 DBusMessageIter iter; 4661 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 4662 4663 if (wpa_s->p2p_mgmt) 4664 wpa_s = wpa_s->parent; 4665 4666 iface = wpa_s->global->dbus; 4667 4668 /* Do nothing if the control interface is not turned on */ 4669 if (iface == NULL || !wpa_s->dbus_new_path) 4670 return; 4671 4672 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4673 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4674 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4675 4676 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface, 4677 sig_name); 4678 if (msg == NULL) 4679 return; 4680 4681 dbus_message_iter_init_append(msg, &iter); 4682 path = peer_obj_path; 4683 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 4684 &path) || 4685 (properties && !wpa_dbus_get_object_properties( 4686 iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER, 4687 &iter))) 4688 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 4689 else 4690 dbus_connection_send(iface->con, msg, NULL); 4691 4692 dbus_message_unref(msg); 4693 } 4694 4695 4696 /** 4697 * wpas_dbus_signal_peer_found - Send a peer found signal 4698 * @wpa_s: %wpa_supplicant network interface data 4699 * @dev_addr: Peer P2P Device Address 4700 * 4701 * Notify listeners about find a p2p peer device found 4702 */ 4703 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s, 4704 const u8 *dev_addr) 4705 { 4706 wpas_dbus_signal_peer(wpa_s, dev_addr, 4707 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4708 "DeviceFound", FALSE); 4709 4710 wpas_dbus_signal_peer(wpa_s, dev_addr, 4711 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4712 "DeviceFoundProperties", TRUE); 4713 } 4714 4715 /** 4716 * wpas_dbus_signal_peer_lost - Send a peer lost signal 4717 * @wpa_s: %wpa_supplicant network interface data 4718 * @dev_addr: Peer P2P Device Address 4719 * 4720 * Notify listeners about lost a p2p peer device 4721 */ 4722 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s, 4723 const u8 *dev_addr) 4724 { 4725 wpas_dbus_signal_peer(wpa_s, dev_addr, 4726 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4727 "DeviceLost", FALSE); 4728 } 4729 4730 /** 4731 * wpas_dbus_register_peer - Register a discovered peer object with dbus 4732 * @wpa_s: wpa_supplicant interface structure 4733 * @dev_addr: P2P Device Address of the peer 4734 * Returns: 0 on success, -1 on failure 4735 * 4736 * Registers network representing object with dbus 4737 */ 4738 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr) 4739 { 4740 struct wpas_dbus_priv *ctrl_iface; 4741 struct wpa_dbus_object_desc *obj_desc; 4742 struct peer_handler_args *arg; 4743 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4744 4745 /* Do nothing if the control interface is not turned on */ 4746 if (wpa_s == NULL || wpa_s->global == NULL) 4747 return 0; 4748 4749 ctrl_iface = wpa_s->global->dbus; 4750 if (ctrl_iface == NULL) 4751 return 0; 4752 4753 wpa_s = wpa_s->parent->parent; 4754 if (!wpa_s->dbus_new_path) 4755 return 0; 4756 4757 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4758 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4759 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4760 4761 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'", 4762 peer_obj_path); 4763 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 4764 if (!obj_desc) { 4765 wpa_printf(MSG_ERROR, 4766 "Not enough memory to create object description"); 4767 goto err; 4768 } 4769 4770 /* allocate memory for handlers arguments */ 4771 arg = os_zalloc(sizeof(struct peer_handler_args)); 4772 if (!arg) { 4773 wpa_printf(MSG_ERROR, 4774 "Not enough memory to create arguments for method"); 4775 goto err; 4776 } 4777 4778 arg->wpa_s = wpa_s; 4779 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN); 4780 4781 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, 4782 NULL, 4783 wpas_dbus_p2p_peer_properties, 4784 wpas_dbus_p2p_peer_signals); 4785 4786 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path, 4787 wpa_s->ifname, obj_desc)) 4788 goto err; 4789 4790 return 0; 4791 4792 err: 4793 free_dbus_object_desc(obj_desc); 4794 return -1; 4795 } 4796 4797 /** 4798 * wpas_dbus_unregister_peer - Unregister a peer object with dbus 4799 * @wpa_s: wpa_supplicant interface structure 4800 * @dev_addr: p2p device addr 4801 * Returns: 0 on success, -1 on failure 4802 * 4803 * Registers network representing object with dbus 4804 */ 4805 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s, 4806 const u8 *dev_addr) 4807 { 4808 struct wpas_dbus_priv *ctrl_iface; 4809 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4810 int ret; 4811 4812 /* Do nothing if the control interface is not turned on */ 4813 if (wpa_s == NULL || wpa_s->global == NULL) 4814 return 0; 4815 4816 wpa_s = wpa_s->parent->parent; 4817 if (!wpa_s->dbus_new_path) 4818 return 0; 4819 4820 ctrl_iface = wpa_s->global->dbus; 4821 if (ctrl_iface == NULL) 4822 return 0; 4823 4824 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4825 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4826 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4827 4828 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'", 4829 peer_obj_path); 4830 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path); 4831 4832 return ret; 4833 } 4834 4835 4836 /** 4837 * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal 4838 * @wpa_s: %wpa_supplicant network interface data 4839 * 4840 * Notify listeners about P2P Find stopped 4841 */ 4842 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s) 4843 { 4844 struct wpas_dbus_priv *iface; 4845 DBusMessage *msg; 4846 4847 iface = wpa_s->global->dbus; 4848 4849 /* Do nothing if the control interface is not turned on */ 4850 if (iface == NULL) 4851 return; 4852 4853 if (wpa_s->p2p_mgmt) 4854 wpa_s = wpa_s->parent; 4855 4856 if (!wpa_s->dbus_new_path) 4857 return; 4858 4859 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 4860 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4861 "FindStopped"); 4862 if (msg == NULL) 4863 return; 4864 4865 dbus_connection_send(iface->con, msg, NULL); 4866 4867 dbus_message_unref(msg); 4868 } 4869 4870 4871 /** 4872 * wpas_dbus_signal_peer_groups_changed - Send peer group change property signal 4873 * @wpa_s: %wpa_supplicant network interface data 4874 * @dev_addr: P2P Device Address 4875 * 4876 * Notify listeners about peer Groups property changes. 4877 */ 4878 void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s, 4879 const u8 *dev_addr) 4880 { 4881 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4882 4883 if (wpa_s->p2p_mgmt) 4884 wpa_s = wpa_s->parent; 4885 4886 if (!wpa_s->dbus_new_path) 4887 return; 4888 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4889 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4890 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4891 4892 wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path, 4893 WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups"); 4894 } 4895 4896 4897 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = { 4898 { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao", 4899 wpas_dbus_getter_p2p_group_members, 4900 NULL, 4901 NULL 4902 }, 4903 { "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o", 4904 wpas_dbus_getter_p2p_group, 4905 NULL, 4906 NULL 4907 }, 4908 { "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", 4909 wpas_dbus_getter_p2p_role, 4910 NULL, 4911 NULL 4912 }, 4913 { "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 4914 wpas_dbus_getter_p2p_group_ssid, 4915 NULL, 4916 NULL 4917 }, 4918 { "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 4919 wpas_dbus_getter_p2p_group_bssid, 4920 NULL, 4921 NULL 4922 }, 4923 { "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q", 4924 wpas_dbus_getter_p2p_group_frequency, 4925 NULL, 4926 NULL 4927 }, 4928 { "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s", 4929 wpas_dbus_getter_p2p_group_passphrase, 4930 NULL, 4931 NULL 4932 }, 4933 { "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay", 4934 wpas_dbus_getter_p2p_group_psk, 4935 NULL, 4936 NULL 4937 }, 4938 { "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay", 4939 wpas_dbus_getter_p2p_group_vendor_ext, 4940 wpas_dbus_setter_p2p_group_vendor_ext, 4941 NULL 4942 }, 4943 { NULL, NULL, NULL, NULL, NULL, NULL } 4944 }; 4945 4946 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = { 4947 { "PeerJoined", WPAS_DBUS_NEW_IFACE_P2P_GROUP, 4948 { 4949 { "peer", "o", ARG_OUT }, 4950 END_ARGS 4951 } 4952 }, 4953 { "PeerDisconnected", WPAS_DBUS_NEW_IFACE_P2P_GROUP, 4954 { 4955 { "peer", "o", ARG_OUT }, 4956 END_ARGS 4957 } 4958 }, 4959 { NULL, NULL, { END_ARGS } } 4960 }; 4961 4962 /** 4963 * wpas_dbus_register_p2p_group - Register a p2p group object with dbus 4964 * @wpa_s: wpa_supplicant interface structure 4965 * @ssid: SSID struct 4966 * Returns: 0 on success, -1 on failure 4967 * 4968 * Registers p2p group representing object with dbus 4969 */ 4970 void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s, 4971 struct wpa_ssid *ssid) 4972 { 4973 struct wpas_dbus_priv *ctrl_iface; 4974 struct wpa_dbus_object_desc *obj_desc; 4975 char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4976 4977 /* Do nothing if the control interface is not turned on */ 4978 if (wpa_s == NULL || wpa_s->global == NULL) 4979 return; 4980 4981 ctrl_iface = wpa_s->global->dbus; 4982 if (ctrl_iface == NULL) 4983 return; 4984 4985 if (wpa_s->dbus_groupobj_path) { 4986 wpa_printf(MSG_INFO, "%s: Group object '%s' already exists", 4987 __func__, wpa_s->dbus_groupobj_path); 4988 return; 4989 } 4990 4991 if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0) 4992 return; 4993 4994 wpa_s->dbus_groupobj_path = os_strdup(group_obj_path); 4995 if (wpa_s->dbus_groupobj_path == NULL) 4996 return; 4997 4998 wpa_printf(MSG_INFO, "dbus: Register group object '%s'", 4999 group_obj_path); 5000 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 5001 if (!obj_desc) { 5002 wpa_printf(MSG_ERROR, 5003 "Not enough memory to create object description"); 5004 goto err; 5005 } 5006 5007 wpas_dbus_register(obj_desc, wpa_s, NULL, NULL, 5008 wpas_dbus_p2p_group_properties, 5009 wpas_dbus_p2p_group_signals); 5010 5011 if (wpa_dbus_register_object_per_iface(ctrl_iface, group_obj_path, 5012 wpa_s->ifname, obj_desc)) 5013 goto err; 5014 5015 return; 5016 5017 err: 5018 if (wpa_s->dbus_groupobj_path) { 5019 os_free(wpa_s->dbus_groupobj_path); 5020 wpa_s->dbus_groupobj_path = NULL; 5021 } 5022 5023 free_dbus_object_desc(obj_desc); 5024 } 5025 5026 /** 5027 * wpas_dbus_unregister_p2p_group - Unregister a p2p group object from dbus 5028 * @wpa_s: wpa_supplicant interface structure 5029 * @ssid: network name of the p2p group started 5030 */ 5031 void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s, 5032 const struct wpa_ssid *ssid) 5033 { 5034 struct wpas_dbus_priv *ctrl_iface; 5035 5036 /* Do nothing if the control interface is not turned on */ 5037 if (wpa_s == NULL || wpa_s->global == NULL) 5038 return; 5039 5040 if (wpa_s->p2p_mgmt) 5041 wpa_s = wpa_s->parent; 5042 5043 ctrl_iface = wpa_s->global->dbus; 5044 if (ctrl_iface == NULL) 5045 return; 5046 5047 if (!wpa_s->dbus_groupobj_path) { 5048 wpa_printf(MSG_DEBUG, 5049 "%s: Group object has already unregistered", 5050 __func__); 5051 return; 5052 } 5053 5054 peer_groups_changed(wpa_s); 5055 5056 wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'", 5057 wpa_s->dbus_groupobj_path); 5058 5059 wpa_dbus_unregister_object_per_iface(ctrl_iface, 5060 wpa_s->dbus_groupobj_path); 5061 5062 os_free(wpa_s->dbus_groupobj_path); 5063 wpa_s->dbus_groupobj_path = NULL; 5064 } 5065 5066 static const struct wpa_dbus_property_desc 5067 wpas_dbus_persistent_group_properties[] = { 5068 { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}", 5069 wpas_dbus_getter_persistent_group_properties, 5070 wpas_dbus_setter_persistent_group_properties, 5071 NULL 5072 }, 5073 { NULL, NULL, NULL, NULL, NULL, NULL } 5074 }; 5075 5076 /* No signals intended for persistent group objects */ 5077 5078 /** 5079 * wpas_dbus_register_persistent_group - Register a configured(saved) 5080 * persistent group with dbus 5081 * @wpa_s: wpa_supplicant interface structure 5082 * @ssid: persistent group (still represented as a network within wpa) 5083 * configuration data 5084 * Returns: 0 on success, -1 on failure 5085 * 5086 * Registers a persistent group representing object with dbus. 5087 */ 5088 int wpas_dbus_register_persistent_group(struct wpa_supplicant *wpa_s, 5089 struct wpa_ssid *ssid) 5090 { 5091 struct wpas_dbus_priv *ctrl_iface; 5092 struct wpa_dbus_object_desc *obj_desc; 5093 struct network_handler_args *arg; 5094 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 5095 5096 /* Do nothing if the control interface is not turned on */ 5097 if (wpa_s == NULL || wpa_s->global == NULL) 5098 return 0; 5099 wpa_s = wpa_s->parent->parent; 5100 if (!wpa_s->dbus_new_path) 5101 return 0; 5102 5103 /* Make sure ssid is a persistent group */ 5104 if (ssid->disabled != 2 && !ssid->p2p_persistent_group) 5105 return -1; /* should we return w/o complaining? */ 5106 5107 if (wpa_s->p2p_mgmt) 5108 wpa_s = wpa_s->parent; 5109 5110 ctrl_iface = wpa_s->global->dbus; 5111 if (ctrl_iface == NULL) 5112 return 0; 5113 5114 /* 5115 * Intentionally not coming up with different numbering scheme 5116 * for persistent groups. 5117 */ 5118 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 5119 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 5120 wpa_s->dbus_new_path, ssid->id); 5121 5122 wpa_printf(MSG_DEBUG, "dbus: Register persistent group object '%s'", 5123 pgrp_obj_path); 5124 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 5125 if (!obj_desc) { 5126 wpa_printf(MSG_ERROR, 5127 "dbus: Not enough memory to create object description"); 5128 goto err; 5129 } 5130 5131 /* 5132 * Reusing the same context structure as that for networks 5133 * since these are represented using same data structure. 5134 */ 5135 /* allocate memory for handlers arguments */ 5136 arg = os_zalloc(sizeof(struct network_handler_args)); 5137 if (!arg) { 5138 wpa_printf(MSG_ERROR, 5139 "dbus: Not enough memory to create arguments for method"); 5140 goto err; 5141 } 5142 5143 arg->wpa_s = wpa_s; 5144 arg->ssid = ssid; 5145 5146 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 5147 wpas_dbus_persistent_group_properties, 5148 NULL); 5149 5150 if (wpa_dbus_register_object_per_iface(ctrl_iface, pgrp_obj_path, 5151 wpa_s->ifname, obj_desc)) 5152 goto err; 5153 5154 wpas_dbus_signal_persistent_group_added(wpa_s, ssid->id); 5155 5156 return 0; 5157 5158 err: 5159 free_dbus_object_desc(obj_desc); 5160 return -1; 5161 } 5162 5163 5164 /** 5165 * wpas_dbus_unregister_persistent_group - Unregister a persistent_group 5166 * from dbus 5167 * @wpa_s: wpa_supplicant interface structure 5168 * @nid: network id 5169 * Returns: 0 on success, -1 on failure 5170 * 5171 * Unregisters persistent group representing object from dbus 5172 * 5173 * NOTE: There is a slight issue with the semantics here. While the 5174 * implementation simply means the persistent group is unloaded from memory, 5175 * it should not get interpreted as the group is actually being erased/removed 5176 * from persistent storage as well. 5177 */ 5178 int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s, 5179 int nid) 5180 { 5181 struct wpas_dbus_priv *ctrl_iface; 5182 char pgrp_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 5183 int ret; 5184 5185 /* Do nothing if the control interface is not turned on */ 5186 if (wpa_s == NULL || wpa_s->global == NULL) 5187 return 0; 5188 5189 wpa_s = wpa_s->parent->parent; 5190 5191 ctrl_iface = wpa_s->global->dbus; 5192 if (ctrl_iface == NULL || !wpa_s->dbus_new_path) 5193 return 0; 5194 5195 os_snprintf(pgrp_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 5196 "%s/" WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/%u", 5197 wpa_s->dbus_new_path, nid); 5198 5199 wpa_printf(MSG_DEBUG, "dbus: Unregister persistent group object '%s'", 5200 pgrp_obj_path); 5201 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, pgrp_obj_path); 5202 5203 if (!ret) 5204 wpas_dbus_signal_persistent_group_removed(wpa_s, nid); 5205 5206 return ret; 5207 } 5208 5209 #endif /* CONFIG_P2P */ 5210 5211 5212 #ifdef CONFIG_HS20 5213 /** 5214 * wpas_dbus_signal_hs20_t_c_acceptance - Signals a terms and conditions was 5215 * received. 5216 * 5217 * @wpa_s: %wpa_supplicant network interface data 5218 * @url: URL of the terms and conditions acceptance page. 5219 */ 5220 void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s, 5221 const char *url) 5222 { 5223 struct wpas_dbus_priv *iface; 5224 DBusMessage *msg; 5225 5226 iface = wpa_s->global->dbus; 5227 5228 /* Do nothing if the control interface is not turned on */ 5229 if (!iface || !wpa_s->dbus_new_path) 5230 return; 5231 5232 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 5233 WPAS_DBUS_NEW_IFACE_INTERFACE, 5234 "HS20TermsAndConditions"); 5235 if (!msg) 5236 return; 5237 5238 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &url, 5239 DBUS_TYPE_INVALID)) 5240 dbus_connection_send(iface->con, msg, NULL); 5241 else 5242 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 5243 dbus_message_unref(msg); 5244 } 5245 #endif /* CONFIG_HS20 */ 5246