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