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