1 /* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc. 4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa (at) gmail.com> 5 * Copyright (c) 2009, Jouni Malinen <j (at) 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 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2031 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2032 "GroupFormationFailure"); 2033 if (msg == NULL) 2034 return; 2035 2036 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &reason, 2037 DBUS_TYPE_INVALID)) 2038 dbus_connection_send(iface->con, msg, NULL); 2039 else 2040 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 2041 2042 dbus_message_unref(msg); 2043 } 2044 2045 2046 /** 2047 * wpas_dbus_signal_p2p_invitation_received - Emit InvitationReceived signal 2048 * @wpa_s: %wpa_supplicant network interface data 2049 * @sa: Source address of the Invitation Request 2050 * @dev_add: GO Device Address 2051 * @bssid: P2P Group BSSID or %NULL if not received 2052 * @id: Persistent group id or %0 if not persistent group 2053 * @op_freq: Operating frequency for the group 2054 */ 2055 2056 void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s, 2057 const u8 *sa, const u8 *dev_addr, 2058 const u8 *bssid, int id, 2059 int op_freq) 2060 { 2061 DBusMessage *msg; 2062 DBusMessageIter iter, dict_iter; 2063 struct wpas_dbus_priv *iface; 2064 2065 iface = wpa_s->global->dbus; 2066 2067 /* Do nothing if the control interface is not turned on */ 2068 if (iface == NULL) 2069 return; 2070 2071 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 2072 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2073 "InvitationReceived"); 2074 if (msg == NULL) 2075 return; 2076 2077 dbus_message_iter_init_append(msg, &iter); 2078 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 2079 (sa && 2080 !wpa_dbus_dict_append_byte_array(&dict_iter, "sa", 2081 (const char *) sa, ETH_ALEN)) || 2082 (dev_addr && 2083 !wpa_dbus_dict_append_byte_array(&dict_iter, "go_dev_addr", 2084 (const char *) dev_addr, 2085 ETH_ALEN)) || 2086 (bssid && 2087 !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid", 2088 (const char *) bssid, 2089 ETH_ALEN)) || 2090 (id && 2091 !wpa_dbus_dict_append_int32(&dict_iter, "persistent_id", id)) || 2092 !wpa_dbus_dict_append_int32(&dict_iter, "op_freq", op_freq) || 2093 !wpa_dbus_dict_close_write(&iter, &dict_iter)) { 2094 dbus_message_unref(msg); 2095 return; 2096 } 2097 2098 dbus_connection_send(iface->con, msg, NULL); 2099 dbus_message_unref(msg); 2100 } 2101 2102 2103 #endif /* CONFIG_P2P */ 2104 2105 2106 /** 2107 * wpas_dbus_signal_prop_changed - Signals change of property 2108 * @wpa_s: %wpa_supplicant network interface data 2109 * @property: indicates which property has changed 2110 * 2111 * Sends PropertyChanged signals with path, interface and arguments 2112 * depending on which property has changed. 2113 */ 2114 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, 2115 enum wpas_dbus_prop property) 2116 { 2117 char *prop; 2118 dbus_bool_t flush; 2119 2120 if (wpa_s->dbus_new_path == NULL) 2121 return; /* Skip signal since D-Bus setup is not yet ready */ 2122 2123 flush = FALSE; 2124 switch (property) { 2125 case WPAS_DBUS_PROP_AP_SCAN: 2126 prop = "ApScan"; 2127 break; 2128 #ifdef CONFIG_IEEE80211W 2129 case WPAS_DBUS_PROP_PMF: 2130 prop = "Pmf"; 2131 break; 2132 #endif /* CONFIG_IEEE80211W */ 2133 case WPAS_DBUS_PROP_SCANNING: 2134 prop = "Scanning"; 2135 break; 2136 case WPAS_DBUS_PROP_STATE: 2137 prop = "State"; 2138 break; 2139 case WPAS_DBUS_PROP_CURRENT_BSS: 2140 prop = "CurrentBSS"; 2141 break; 2142 case WPAS_DBUS_PROP_CURRENT_NETWORK: 2143 prop = "CurrentNetwork"; 2144 break; 2145 case WPAS_DBUS_PROP_BSSS: 2146 prop = "BSSs"; 2147 break; 2148 case WPAS_DBUS_PROP_CURRENT_AUTH_MODE: 2149 prop = "CurrentAuthMode"; 2150 break; 2151 case WPAS_DBUS_PROP_DISCONNECT_REASON: 2152 prop = "DisconnectReason"; 2153 flush = TRUE; 2154 break; 2155 case WPAS_DBUS_PROP_ASSOC_STATUS_CODE: 2156 prop = "AssocStatusCode"; 2157 flush = TRUE; 2158 break; 2159 default: 2160 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 2161 __func__, property); 2162 return; 2163 } 2164 2165 wpa_dbus_mark_property_changed(wpa_s->global->dbus, 2166 wpa_s->dbus_new_path, 2167 WPAS_DBUS_NEW_IFACE_INTERFACE, prop); 2168 if (flush) { 2169 wpa_dbus_flush_object_changed_properties( 2170 wpa_s->global->dbus->con, wpa_s->dbus_new_path); 2171 } 2172 } 2173 2174 2175 /** 2176 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property 2177 * @wpa_s: %wpa_supplicant network interface data 2178 * @property: indicates which property has changed 2179 * @id: unique BSS identifier 2180 * 2181 * Sends PropertyChanged signals with path, interface, and arguments depending 2182 * on which property has changed. 2183 */ 2184 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s, 2185 enum wpas_dbus_bss_prop property, 2186 unsigned int id) 2187 { 2188 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 2189 char *prop; 2190 2191 if (!wpa_s->dbus_new_path) 2192 return; 2193 2194 switch (property) { 2195 case WPAS_DBUS_BSS_PROP_SIGNAL: 2196 prop = "Signal"; 2197 break; 2198 case WPAS_DBUS_BSS_PROP_FREQ: 2199 prop = "Frequency"; 2200 break; 2201 case WPAS_DBUS_BSS_PROP_MODE: 2202 prop = "Mode"; 2203 break; 2204 case WPAS_DBUS_BSS_PROP_PRIVACY: 2205 prop = "Privacy"; 2206 break; 2207 case WPAS_DBUS_BSS_PROP_RATES: 2208 prop = "Rates"; 2209 break; 2210 case WPAS_DBUS_BSS_PROP_WPA: 2211 prop = "WPA"; 2212 break; 2213 case WPAS_DBUS_BSS_PROP_RSN: 2214 prop = "RSN"; 2215 break; 2216 case WPAS_DBUS_BSS_PROP_WPS: 2217 prop = "WPS"; 2218 break; 2219 case WPAS_DBUS_BSS_PROP_IES: 2220 prop = "IEs"; 2221 break; 2222 case WPAS_DBUS_BSS_PROP_AGE: 2223 prop = "Age"; 2224 break; 2225 default: 2226 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 2227 __func__, property); 2228 return; 2229 } 2230 2231 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 2232 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2233 wpa_s->dbus_new_path, id); 2234 2235 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 2236 WPAS_DBUS_NEW_IFACE_BSS, prop); 2237 } 2238 2239 2240 /** 2241 * wpas_dbus_signal_debug_level_changed - Signals change of debug param 2242 * @global: wpa_global structure 2243 * 2244 * Sends PropertyChanged signals informing that debug level has changed. 2245 */ 2246 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global) 2247 { 2248 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2249 WPAS_DBUS_NEW_INTERFACE, 2250 "DebugLevel"); 2251 } 2252 2253 2254 /** 2255 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param 2256 * @global: wpa_global structure 2257 * 2258 * Sends PropertyChanged signals informing that debug timestamp has changed. 2259 */ 2260 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global) 2261 { 2262 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2263 WPAS_DBUS_NEW_INTERFACE, 2264 "DebugTimestamp"); 2265 } 2266 2267 2268 /** 2269 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param 2270 * @global: wpa_global structure 2271 * 2272 * Sends PropertyChanged signals informing that debug show_keys has changed. 2273 */ 2274 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global) 2275 { 2276 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 2277 WPAS_DBUS_NEW_INTERFACE, 2278 "DebugShowKeys"); 2279 } 2280 2281 2282 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc, 2283 void *priv, 2284 WPADBusArgumentFreeFunction priv_free, 2285 const struct wpa_dbus_method_desc *methods, 2286 const struct wpa_dbus_property_desc *properties, 2287 const struct wpa_dbus_signal_desc *signals) 2288 { 2289 int n; 2290 2291 obj_desc->user_data = priv; 2292 obj_desc->user_data_free_func = priv_free; 2293 obj_desc->methods = methods; 2294 obj_desc->properties = properties; 2295 obj_desc->signals = signals; 2296 2297 for (n = 0; properties && properties->dbus_property; properties++) 2298 n++; 2299 2300 obj_desc->prop_changed_flags = os_zalloc(n); 2301 if (!obj_desc->prop_changed_flags) 2302 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers", 2303 __func__); 2304 } 2305 2306 2307 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = { 2308 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE, 2309 (WPADBusMethodHandler) wpas_dbus_handler_create_interface, 2310 { 2311 { "args", "a{sv}", ARG_IN }, 2312 { "path", "o", ARG_OUT }, 2313 END_ARGS 2314 } 2315 }, 2316 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE, 2317 (WPADBusMethodHandler) wpas_dbus_handler_remove_interface, 2318 { 2319 { "path", "o", ARG_IN }, 2320 END_ARGS 2321 } 2322 }, 2323 { "GetInterface", WPAS_DBUS_NEW_INTERFACE, 2324 (WPADBusMethodHandler) wpas_dbus_handler_get_interface, 2325 { 2326 { "ifname", "s", ARG_IN }, 2327 { "path", "o", ARG_OUT }, 2328 END_ARGS 2329 } 2330 }, 2331 { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE, 2332 (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect, 2333 { 2334 END_ARGS 2335 } 2336 }, 2337 { NULL, NULL, NULL, { END_ARGS } } 2338 }; 2339 2340 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = { 2341 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s", 2342 wpas_dbus_getter_debug_level, 2343 wpas_dbus_setter_debug_level, 2344 NULL 2345 }, 2346 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b", 2347 wpas_dbus_getter_debug_timestamp, 2348 wpas_dbus_setter_debug_timestamp, 2349 NULL 2350 }, 2351 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b", 2352 wpas_dbus_getter_debug_show_keys, 2353 wpas_dbus_setter_debug_show_keys, 2354 NULL 2355 }, 2356 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao", 2357 wpas_dbus_getter_interfaces, 2358 NULL, 2359 NULL 2360 }, 2361 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as", 2362 wpas_dbus_getter_eap_methods, 2363 NULL, 2364 NULL 2365 }, 2366 { "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as", 2367 wpas_dbus_getter_global_capabilities, 2368 NULL, 2369 NULL 2370 }, 2371 #ifdef CONFIG_WIFI_DISPLAY 2372 { "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay", 2373 wpas_dbus_getter_global_wfd_ies, 2374 wpas_dbus_setter_global_wfd_ies, 2375 NULL 2376 }, 2377 #endif /* CONFIG_WIFI_DISPLAY */ 2378 { NULL, NULL, NULL, NULL, NULL, NULL } 2379 }; 2380 2381 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = { 2382 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE, 2383 { 2384 { "path", "o", ARG_OUT }, 2385 { "properties", "a{sv}", ARG_OUT }, 2386 END_ARGS 2387 } 2388 }, 2389 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE, 2390 { 2391 { "path", "o", ARG_OUT }, 2392 END_ARGS 2393 } 2394 }, 2395 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2396 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE, 2397 { 2398 { "properties", "a{sv}", ARG_OUT }, 2399 END_ARGS 2400 } 2401 }, 2402 { NULL, NULL, { END_ARGS } } 2403 }; 2404 2405 2406 static char * uscore_to_dbus(const char *uscore) 2407 { 2408 const char *p = uscore; 2409 char *str, *s; 2410 dbus_bool_t last_was_uscore = TRUE; 2411 2412 s = str = os_zalloc(os_strlen(uscore) + 1); 2413 if (!str) 2414 return NULL; 2415 while (p && *p) { 2416 if (*p == '_') { 2417 last_was_uscore = TRUE; 2418 } else { 2419 *s++ = last_was_uscore ? toupper(*p) : *p; 2420 last_was_uscore = FALSE; 2421 } 2422 p++; 2423 } 2424 2425 return str; 2426 } 2427 2428 2429 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv); 2430 2431 2432 static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv) 2433 { 2434 int idx = priv->globals_start; 2435 2436 /* Free all allocated property values */ 2437 while (priv->all_interface_properties[idx].dbus_property) 2438 os_free((char *) 2439 priv->all_interface_properties[idx++].dbus_property); 2440 os_free((char *) priv->all_interface_properties); 2441 } 2442 2443 2444 /** 2445 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface 2446 * @global: Pointer to global data from wpa_supplicant_init() 2447 * Returns: 0 on success or -1 on failure 2448 * 2449 * Initialize the dbus control interface for wpa_supplicant and start 2450 * receiving commands from external programs over the bus. 2451 */ 2452 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv) 2453 { 2454 struct wpa_dbus_object_desc *obj_desc; 2455 int ret; 2456 2457 ret = wpa_dbus_ctrl_iface_props_init(priv); 2458 if (ret < 0) { 2459 wpa_printf(MSG_ERROR, 2460 "dbus: Not enough memory to init interface properties"); 2461 return -1; 2462 } 2463 2464 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2465 if (!obj_desc) { 2466 wpa_printf(MSG_ERROR, 2467 "Not enough memory to create object description"); 2468 goto error; 2469 } 2470 2471 wpas_dbus_register(obj_desc, priv->global, NULL, 2472 wpas_dbus_global_methods, 2473 wpas_dbus_global_properties, 2474 wpas_dbus_global_signals); 2475 2476 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'", 2477 WPAS_DBUS_NEW_PATH); 2478 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH, 2479 WPAS_DBUS_NEW_SERVICE, 2480 obj_desc); 2481 if (ret < 0) { 2482 free_dbus_object_desc(obj_desc); 2483 goto error; 2484 } 2485 2486 priv->dbus_new_initialized = 1; 2487 return 0; 2488 2489 error: 2490 wpa_dbus_ctrl_iface_props_deinit(priv); 2491 return -1; 2492 } 2493 2494 2495 /** 2496 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for 2497 * wpa_supplicant 2498 * @priv: Pointer to dbus private data from wpas_dbus_init() 2499 * 2500 * Deinitialize the dbus control interface that was initialized with 2501 * wpas_dbus_ctrl_iface_init(). 2502 */ 2503 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv) 2504 { 2505 if (!priv->dbus_new_initialized) 2506 return; 2507 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'", 2508 WPAS_DBUS_NEW_PATH); 2509 dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH); 2510 wpa_dbus_ctrl_iface_props_deinit(priv); 2511 } 2512 2513 2514 static void wpa_dbus_free(void *ptr) 2515 { 2516 os_free(ptr); 2517 } 2518 2519 2520 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = { 2521 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}", 2522 wpas_dbus_getter_network_properties, 2523 wpas_dbus_setter_network_properties, 2524 NULL 2525 }, 2526 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b", 2527 wpas_dbus_getter_enabled, 2528 wpas_dbus_setter_enabled, 2529 NULL 2530 }, 2531 { NULL, NULL, NULL, NULL, NULL, NULL } 2532 }; 2533 2534 2535 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = { 2536 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2537 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK, 2538 { 2539 { "properties", "a{sv}", ARG_OUT }, 2540 END_ARGS 2541 } 2542 }, 2543 { NULL, NULL, { END_ARGS } } 2544 }; 2545 2546 2547 /** 2548 * wpas_dbus_register_network - Register a configured network with dbus 2549 * @wpa_s: wpa_supplicant interface structure 2550 * @ssid: network configuration data 2551 * Returns: 0 on success, -1 on failure 2552 * 2553 * Registers network representing object with dbus 2554 */ 2555 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s, 2556 struct wpa_ssid *ssid) 2557 { 2558 struct wpas_dbus_priv *ctrl_iface; 2559 struct wpa_dbus_object_desc *obj_desc; 2560 struct network_handler_args *arg; 2561 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2562 2563 #ifdef CONFIG_P2P 2564 /* 2565 * If it is a persistent group register it as such. 2566 * This is to handle cases where an interface is being initialized 2567 * with a list of networks read from config. 2568 */ 2569 if (network_is_persistent_group(ssid)) 2570 return wpas_dbus_register_persistent_group(wpa_s, ssid); 2571 #endif /* CONFIG_P2P */ 2572 2573 /* Do nothing if the control interface is not turned on */ 2574 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 2575 return 0; 2576 ctrl_iface = wpa_s->global->dbus; 2577 if (ctrl_iface == NULL) 2578 return 0; 2579 2580 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2581 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2582 wpa_s->dbus_new_path, ssid->id); 2583 2584 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'", 2585 net_obj_path); 2586 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2587 if (!obj_desc) { 2588 wpa_printf(MSG_ERROR, 2589 "Not enough memory to create object description"); 2590 goto err; 2591 } 2592 2593 /* allocate memory for handlers arguments */ 2594 arg = os_zalloc(sizeof(struct network_handler_args)); 2595 if (!arg) { 2596 wpa_printf(MSG_ERROR, 2597 "Not enough memory to create arguments for method"); 2598 goto err; 2599 } 2600 2601 arg->wpa_s = wpa_s; 2602 arg->ssid = ssid; 2603 2604 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2605 wpas_dbus_network_properties, 2606 wpas_dbus_network_signals); 2607 2608 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path, 2609 wpa_s->ifname, obj_desc)) 2610 goto err; 2611 2612 wpas_dbus_signal_network_added(wpa_s, ssid->id); 2613 2614 return 0; 2615 2616 err: 2617 free_dbus_object_desc(obj_desc); 2618 return -1; 2619 } 2620 2621 2622 /** 2623 * wpas_dbus_unregister_network - Unregister a configured network from dbus 2624 * @wpa_s: wpa_supplicant interface structure 2625 * @nid: network id 2626 * Returns: 0 on success, -1 on failure 2627 * 2628 * Unregisters network representing object from dbus 2629 */ 2630 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid) 2631 { 2632 struct wpas_dbus_priv *ctrl_iface; 2633 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2634 int ret; 2635 #ifdef CONFIG_P2P 2636 struct wpa_ssid *ssid; 2637 2638 ssid = wpa_config_get_network(wpa_s->conf, nid); 2639 2640 /* If it is a persistent group unregister it as such */ 2641 if (ssid && network_is_persistent_group(ssid)) 2642 return wpas_dbus_unregister_persistent_group(wpa_s, nid); 2643 #endif /* CONFIG_P2P */ 2644 2645 /* Do nothing if the control interface is not turned on */ 2646 if (wpa_s->global == NULL || wpa_s->dbus_new_path == NULL) 2647 return 0; 2648 ctrl_iface = wpa_s->global->dbus; 2649 if (ctrl_iface == NULL) 2650 return 0; 2651 2652 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2653 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2654 wpa_s->dbus_new_path, nid); 2655 2656 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'", 2657 net_obj_path); 2658 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path); 2659 2660 if (!ret) 2661 wpas_dbus_signal_network_removed(wpa_s, nid); 2662 2663 return ret; 2664 } 2665 2666 2667 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = { 2668 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2669 wpas_dbus_getter_bss_ssid, 2670 NULL, 2671 NULL 2672 }, 2673 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2674 wpas_dbus_getter_bss_bssid, 2675 NULL, 2676 NULL 2677 }, 2678 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b", 2679 wpas_dbus_getter_bss_privacy, 2680 NULL, 2681 NULL 2682 }, 2683 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s", 2684 wpas_dbus_getter_bss_mode, 2685 NULL, 2686 NULL 2687 }, 2688 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n", 2689 wpas_dbus_getter_bss_signal, 2690 NULL, 2691 NULL 2692 }, 2693 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q", 2694 wpas_dbus_getter_bss_frequency, 2695 NULL, 2696 NULL 2697 }, 2698 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au", 2699 wpas_dbus_getter_bss_rates, 2700 NULL, 2701 NULL 2702 }, 2703 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2704 wpas_dbus_getter_bss_wpa, 2705 NULL, 2706 NULL 2707 }, 2708 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2709 wpas_dbus_getter_bss_rsn, 2710 NULL, 2711 NULL 2712 }, 2713 { "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 2714 wpas_dbus_getter_bss_wps, 2715 NULL, 2716 NULL 2717 }, 2718 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay", 2719 wpas_dbus_getter_bss_ies, 2720 NULL, 2721 NULL 2722 }, 2723 { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u", 2724 wpas_dbus_getter_bss_age, 2725 NULL, 2726 NULL 2727 }, 2728 { NULL, NULL, NULL, NULL, NULL, NULL } 2729 }; 2730 2731 2732 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = { 2733 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 2734 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS, 2735 { 2736 { "properties", "a{sv}", ARG_OUT }, 2737 END_ARGS 2738 } 2739 }, 2740 { NULL, NULL, { END_ARGS } } 2741 }; 2742 2743 2744 /** 2745 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus 2746 * @wpa_s: wpa_supplicant interface structure 2747 * @bssid: scanned network bssid 2748 * @id: unique BSS identifier 2749 * Returns: 0 on success, -1 on failure 2750 * 2751 * Unregisters BSS representing object from dbus 2752 */ 2753 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s, 2754 u8 bssid[ETH_ALEN], unsigned int id) 2755 { 2756 struct wpas_dbus_priv *ctrl_iface; 2757 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2758 2759 /* Do nothing if the control interface is not turned on */ 2760 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 2761 return 0; 2762 ctrl_iface = wpa_s->global->dbus; 2763 if (ctrl_iface == NULL) 2764 return 0; 2765 2766 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2767 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2768 wpa_s->dbus_new_path, id); 2769 2770 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'", 2771 bss_obj_path); 2772 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) { 2773 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s", 2774 bss_obj_path); 2775 return -1; 2776 } 2777 2778 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path); 2779 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 2780 2781 return 0; 2782 } 2783 2784 2785 /** 2786 * wpas_dbus_register_bss - Register a scanned BSS with dbus 2787 * @wpa_s: wpa_supplicant interface structure 2788 * @bssid: scanned network bssid 2789 * @id: unique BSS identifier 2790 * Returns: 0 on success, -1 on failure 2791 * 2792 * Registers BSS representing object with dbus 2793 */ 2794 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, 2795 u8 bssid[ETH_ALEN], unsigned int id) 2796 { 2797 struct wpas_dbus_priv *ctrl_iface; 2798 struct wpa_dbus_object_desc *obj_desc; 2799 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 2800 struct bss_handler_args *arg; 2801 2802 /* Do nothing if the control interface is not turned on */ 2803 if (wpa_s == NULL || wpa_s->global == NULL || !wpa_s->dbus_new_path) 2804 return 0; 2805 ctrl_iface = wpa_s->global->dbus; 2806 if (ctrl_iface == NULL) 2807 return 0; 2808 2809 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2810 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2811 wpa_s->dbus_new_path, id); 2812 2813 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 2814 if (!obj_desc) { 2815 wpa_printf(MSG_ERROR, 2816 "Not enough memory to create object description"); 2817 goto err; 2818 } 2819 2820 arg = os_zalloc(sizeof(struct bss_handler_args)); 2821 if (!arg) { 2822 wpa_printf(MSG_ERROR, 2823 "Not enough memory to create arguments for handler"); 2824 goto err; 2825 } 2826 arg->wpa_s = wpa_s; 2827 arg->id = id; 2828 2829 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 2830 wpas_dbus_bss_properties, 2831 wpas_dbus_bss_signals); 2832 2833 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'", 2834 bss_obj_path); 2835 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path, 2836 wpa_s->ifname, obj_desc)) { 2837 wpa_printf(MSG_ERROR, 2838 "Cannot register BSSID dbus object %s.", 2839 bss_obj_path); 2840 goto err; 2841 } 2842 2843 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path); 2844 wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS); 2845 2846 return 0; 2847 2848 err: 2849 free_dbus_object_desc(obj_desc); 2850 return -1; 2851 } 2852 2853 2854 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { 2855 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE, 2856 (WPADBusMethodHandler) wpas_dbus_handler_scan, 2857 { 2858 { "args", "a{sv}", ARG_IN }, 2859 END_ARGS 2860 } 2861 }, 2862 { "SignalPoll", WPAS_DBUS_NEW_IFACE_INTERFACE, 2863 (WPADBusMethodHandler) wpas_dbus_handler_signal_poll, 2864 { 2865 { "args", "a{sv}", ARG_OUT }, 2866 END_ARGS 2867 } 2868 }, 2869 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 2870 (WPADBusMethodHandler) wpas_dbus_handler_disconnect, 2871 { 2872 END_ARGS 2873 } 2874 }, 2875 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2876 (WPADBusMethodHandler) wpas_dbus_handler_add_network, 2877 { 2878 { "args", "a{sv}", ARG_IN }, 2879 { "path", "o", ARG_OUT }, 2880 END_ARGS 2881 } 2882 }, 2883 { "Reassociate", WPAS_DBUS_NEW_IFACE_INTERFACE, 2884 (WPADBusMethodHandler) wpas_dbus_handler_reassociate, 2885 { 2886 END_ARGS 2887 } 2888 }, 2889 { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE, 2890 (WPADBusMethodHandler) wpas_dbus_handler_reattach, 2891 { 2892 END_ARGS 2893 } 2894 }, 2895 { "Reconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 2896 (WPADBusMethodHandler) wpas_dbus_handler_reconnect, 2897 { 2898 END_ARGS 2899 } 2900 }, 2901 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2902 (WPADBusMethodHandler) wpas_dbus_handler_remove_network, 2903 { 2904 { "path", "o", ARG_IN }, 2905 END_ARGS 2906 } 2907 }, 2908 { "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE, 2909 (WPADBusMethodHandler) wpas_dbus_handler_remove_all_networks, 2910 { 2911 END_ARGS 2912 } 2913 }, 2914 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 2915 (WPADBusMethodHandler) wpas_dbus_handler_select_network, 2916 { 2917 { "path", "o", ARG_IN }, 2918 END_ARGS 2919 } 2920 }, 2921 { "NetworkReply", WPAS_DBUS_NEW_IFACE_INTERFACE, 2922 (WPADBusMethodHandler) wpas_dbus_handler_network_reply, 2923 { 2924 { "path", "o", ARG_IN }, 2925 { "field", "s", ARG_IN }, 2926 { "value", "s", ARG_IN }, 2927 END_ARGS 2928 } 2929 }, 2930 #ifndef CONFIG_NO_CONFIG_BLOBS 2931 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2932 (WPADBusMethodHandler) wpas_dbus_handler_add_blob, 2933 { 2934 { "name", "s", ARG_IN }, 2935 { "data", "ay", ARG_IN }, 2936 END_ARGS 2937 } 2938 }, 2939 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2940 (WPADBusMethodHandler) wpas_dbus_handler_get_blob, 2941 { 2942 { "name", "s", ARG_IN }, 2943 { "data", "ay", ARG_OUT }, 2944 END_ARGS 2945 } 2946 }, 2947 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 2948 (WPADBusMethodHandler) wpas_dbus_handler_remove_blob, 2949 { 2950 { "name", "s", ARG_IN }, 2951 END_ARGS 2952 } 2953 }, 2954 #endif /* CONFIG_NO_CONFIG_BLOBS */ 2955 { "SetPKCS11EngineAndModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, 2956 (WPADBusMethodHandler) 2957 wpas_dbus_handler_set_pkcs11_engine_and_module_path, 2958 { 2959 { "pkcs11_engine_path", "s", ARG_IN }, 2960 { "pkcs11_module_path", "s", ARG_IN }, 2961 END_ARGS 2962 } 2963 }, 2964 #ifdef CONFIG_WPS 2965 { "Start", WPAS_DBUS_NEW_IFACE_WPS, 2966 (WPADBusMethodHandler) wpas_dbus_handler_wps_start, 2967 { 2968 { "args", "a{sv}", ARG_IN }, 2969 { "output", "a{sv}", ARG_OUT }, 2970 END_ARGS 2971 } 2972 }, 2973 { "Cancel", WPAS_DBUS_NEW_IFACE_WPS, 2974 (WPADBusMethodHandler) wpas_dbus_handler_wps_cancel, 2975 { 2976 END_ARGS 2977 } 2978 }, 2979 #endif /* CONFIG_WPS */ 2980 #ifdef CONFIG_P2P 2981 { "Find", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2982 (WPADBusMethodHandler) wpas_dbus_handler_p2p_find, 2983 { 2984 { "args", "a{sv}", ARG_IN }, 2985 END_ARGS 2986 } 2987 }, 2988 { "StopFind", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2989 (WPADBusMethodHandler) wpas_dbus_handler_p2p_stop_find, 2990 { 2991 END_ARGS 2992 } 2993 }, 2994 { "Listen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 2995 (WPADBusMethodHandler) wpas_dbus_handler_p2p_listen, 2996 { 2997 { "timeout", "i", ARG_IN }, 2998 END_ARGS 2999 } 3000 }, 3001 { "ExtendedListen", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3002 (WPADBusMethodHandler) wpas_dbus_handler_p2p_extendedlisten, 3003 { 3004 { "args", "a{sv}", ARG_IN }, 3005 END_ARGS 3006 } 3007 }, 3008 { "PresenceRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3009 (WPADBusMethodHandler) wpas_dbus_handler_p2p_presence_request, 3010 { 3011 { "args", "a{sv}", ARG_IN }, 3012 END_ARGS 3013 } 3014 }, 3015 { "ProvisionDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3016 (WPADBusMethodHandler) wpas_dbus_handler_p2p_prov_disc_req, 3017 { 3018 { "peer", "o", ARG_IN }, 3019 { "config_method", "s", ARG_IN }, 3020 END_ARGS 3021 } 3022 }, 3023 { "Connect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3024 (WPADBusMethodHandler) wpas_dbus_handler_p2p_connect, 3025 { 3026 { "args", "a{sv}", ARG_IN }, 3027 { "generated_pin", "s", ARG_OUT }, 3028 END_ARGS 3029 } 3030 }, 3031 { "GroupAdd", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3032 (WPADBusMethodHandler) wpas_dbus_handler_p2p_group_add, 3033 { 3034 { "args", "a{sv}", ARG_IN }, 3035 END_ARGS 3036 } 3037 }, 3038 { "Cancel", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3039 (WPADBusMethodHandler) wpas_dbus_handler_p2p_cancel, 3040 { 3041 END_ARGS 3042 } 3043 }, 3044 { "Invite", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3045 (WPADBusMethodHandler) wpas_dbus_handler_p2p_invite, 3046 { 3047 { "args", "a{sv}", ARG_IN }, 3048 END_ARGS 3049 } 3050 }, 3051 { "Disconnect", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3052 (WPADBusMethodHandler) wpas_dbus_handler_p2p_disconnect, 3053 { 3054 END_ARGS 3055 } 3056 }, 3057 { "RejectPeer", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3058 (WPADBusMethodHandler) wpas_dbus_handler_p2p_rejectpeer, 3059 { 3060 { "peer", "o", ARG_IN }, 3061 END_ARGS 3062 } 3063 }, 3064 { "RemoveClient", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3065 (WPADBusMethodHandler) wpas_dbus_handler_p2p_remove_client, 3066 { 3067 { "args", "a{sv}", ARG_IN }, 3068 END_ARGS 3069 } 3070 }, 3071 { "Flush", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3072 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush, 3073 { 3074 END_ARGS 3075 } 3076 }, 3077 { "AddService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3078 (WPADBusMethodHandler) wpas_dbus_handler_p2p_add_service, 3079 { 3080 { "args", "a{sv}", ARG_IN }, 3081 END_ARGS 3082 } 3083 }, 3084 { "DeleteService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3085 (WPADBusMethodHandler) wpas_dbus_handler_p2p_delete_service, 3086 { 3087 { "args", "a{sv}", ARG_IN }, 3088 END_ARGS 3089 } 3090 }, 3091 { "FlushService", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3092 (WPADBusMethodHandler) wpas_dbus_handler_p2p_flush_service, 3093 { 3094 END_ARGS 3095 } 3096 }, 3097 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3098 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_req, 3099 { 3100 { "args", "a{sv}", ARG_IN }, 3101 { "ref", "t", ARG_OUT }, 3102 END_ARGS 3103 } 3104 }, 3105 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3106 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_res, 3107 { 3108 { "args", "a{sv}", ARG_IN }, 3109 END_ARGS 3110 } 3111 }, 3112 { "ServiceDiscoveryCancelRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3113 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_sd_cancel_req, 3114 { 3115 { "args", "t", ARG_IN }, 3116 END_ARGS 3117 } 3118 }, 3119 { "ServiceUpdate", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3120 (WPADBusMethodHandler) wpas_dbus_handler_p2p_service_update, 3121 { 3122 END_ARGS 3123 } 3124 }, 3125 { "ServiceDiscoveryExternal", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3126 (WPADBusMethodHandler) wpas_dbus_handler_p2p_serv_disc_external, 3127 { 3128 { "arg", "i", ARG_IN }, 3129 END_ARGS 3130 } 3131 }, 3132 { "AddPersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3133 (WPADBusMethodHandler) wpas_dbus_handler_add_persistent_group, 3134 { 3135 { "args", "a{sv}", ARG_IN }, 3136 { "path", "o", ARG_OUT }, 3137 END_ARGS 3138 } 3139 }, 3140 { "RemovePersistentGroup", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3141 (WPADBusMethodHandler) wpas_dbus_handler_remove_persistent_group, 3142 { 3143 { "path", "o", ARG_IN }, 3144 END_ARGS 3145 } 3146 }, 3147 { "RemoveAllPersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3148 (WPADBusMethodHandler) 3149 wpas_dbus_handler_remove_all_persistent_groups, 3150 { 3151 END_ARGS 3152 } 3153 }, 3154 #endif /* CONFIG_P2P */ 3155 { "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, 3156 (WPADBusMethodHandler) wpas_dbus_handler_flush_bss, 3157 { 3158 { "age", "u", ARG_IN }, 3159 END_ARGS 3160 } 3161 }, 3162 #ifdef CONFIG_AP 3163 { "SubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 3164 (WPADBusMethodHandler) wpas_dbus_handler_subscribe_preq, 3165 { 3166 END_ARGS 3167 } 3168 }, 3169 { "UnsubscribeProbeReq", WPAS_DBUS_NEW_IFACE_INTERFACE, 3170 (WPADBusMethodHandler) wpas_dbus_handler_unsubscribe_preq, 3171 { 3172 END_ARGS 3173 } 3174 }, 3175 #endif /* CONFIG_AP */ 3176 { "EAPLogoff", WPAS_DBUS_NEW_IFACE_INTERFACE, 3177 (WPADBusMethodHandler) wpas_dbus_handler_eap_logoff, 3178 { 3179 END_ARGS 3180 } 3181 }, 3182 { "EAPLogon", WPAS_DBUS_NEW_IFACE_INTERFACE, 3183 (WPADBusMethodHandler) wpas_dbus_handler_eap_logon, 3184 { 3185 END_ARGS 3186 } 3187 }, 3188 #ifdef CONFIG_AUTOSCAN 3189 { "AutoScan", WPAS_DBUS_NEW_IFACE_INTERFACE, 3190 (WPADBusMethodHandler) wpas_dbus_handler_autoscan, 3191 { 3192 { "arg", "s", ARG_IN }, 3193 END_ARGS 3194 } 3195 }, 3196 #endif /* CONFIG_AUTOSCAN */ 3197 #ifdef CONFIG_TDLS 3198 { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE, 3199 (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover, 3200 { 3201 { "peer_address", "s", ARG_IN }, 3202 END_ARGS 3203 } 3204 }, 3205 { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE, 3206 (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup, 3207 { 3208 { "peer_address", "s", ARG_IN }, 3209 END_ARGS 3210 } 3211 }, 3212 { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, 3213 (WPADBusMethodHandler) wpas_dbus_handler_tdls_status, 3214 { 3215 { "peer_address", "s", ARG_IN }, 3216 { "status", "s", ARG_OUT }, 3217 END_ARGS 3218 } 3219 }, 3220 { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE, 3221 (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown, 3222 { 3223 { "peer_address", "s", ARG_IN }, 3224 END_ARGS 3225 } 3226 }, 3227 { "TDLSChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE, 3228 (WPADBusMethodHandler) wpas_dbus_handler_tdls_channel_switch, 3229 { 3230 { "args", "a{sv}", ARG_IN }, 3231 END_ARGS 3232 } 3233 }, 3234 { "TDLSCancelChannelSwitch", WPAS_DBUS_NEW_IFACE_INTERFACE, 3235 (WPADBusMethodHandler) wpas_dbus_handler_tdls_cancel_channel_switch, 3236 { 3237 { "peer_address", "s", ARG_IN }, 3238 END_ARGS 3239 } 3240 }, 3241 #endif /* CONFIG_TDLS */ 3242 { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE, 3243 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add, 3244 { 3245 { "frame_id", "i", ARG_IN }, 3246 { "ielems", "ay", ARG_IN }, 3247 END_ARGS 3248 } 3249 }, 3250 { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE, 3251 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get, 3252 { 3253 { "frame_id", "i", ARG_IN }, 3254 { "ielems", "ay", ARG_OUT }, 3255 END_ARGS 3256 } 3257 }, 3258 { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE, 3259 (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove, 3260 { 3261 { "frame_id", "i", ARG_IN }, 3262 { "ielems", "ay", ARG_IN }, 3263 END_ARGS 3264 } 3265 }, 3266 #ifndef CONFIG_NO_CONFIG_WRITE 3267 { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE, 3268 (WPADBusMethodHandler) wpas_dbus_handler_save_config, 3269 { 3270 END_ARGS 3271 } 3272 }, 3273 #endif /* CONFIG_NO_CONFIG_WRITE */ 3274 { "AbortScan", WPAS_DBUS_NEW_IFACE_INTERFACE, 3275 (WPADBusMethodHandler) wpas_dbus_handler_abort_scan, 3276 { 3277 END_ARGS 3278 } 3279 }, 3280 { NULL, NULL, NULL, { END_ARGS } } 3281 }; 3282 3283 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { 3284 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}", 3285 wpas_dbus_getter_capabilities, 3286 NULL, 3287 NULL 3288 }, 3289 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3290 wpas_dbus_getter_state, 3291 NULL, 3292 NULL 3293 }, 3294 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 3295 wpas_dbus_getter_scanning, 3296 NULL, 3297 NULL 3298 }, 3299 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3300 wpas_dbus_getter_ap_scan, 3301 wpas_dbus_setter_ap_scan, 3302 NULL 3303 }, 3304 #ifdef CONFIG_IEEE80211W 3305 { "Pmf", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3306 wpas_dbus_getter_pmf, 3307 wpas_dbus_setter_pmf, 3308 NULL 3309 }, 3310 #endif /* CONFIG_IEEE80211W */ 3311 { "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3312 wpas_dbus_getter_bss_expire_age, 3313 wpas_dbus_setter_bss_expire_age, 3314 NULL 3315 }, 3316 { "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 3317 wpas_dbus_getter_bss_expire_count, 3318 wpas_dbus_setter_bss_expire_count, 3319 NULL 3320 }, 3321 { "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3322 wpas_dbus_getter_country, 3323 wpas_dbus_setter_country, 3324 NULL 3325 }, 3326 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3327 wpas_dbus_getter_ifname, 3328 NULL, 3329 NULL 3330 }, 3331 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3332 wpas_dbus_getter_driver, 3333 NULL, 3334 NULL 3335 }, 3336 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3337 wpas_dbus_getter_bridge_ifname, 3338 NULL, 3339 NULL 3340 }, 3341 { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3342 wpas_dbus_getter_config_file, 3343 NULL, 3344 NULL 3345 }, 3346 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 3347 wpas_dbus_getter_current_bss, 3348 NULL, 3349 NULL 3350 }, 3351 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 3352 wpas_dbus_getter_current_network, 3353 NULL, 3354 NULL 3355 }, 3356 { "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3357 wpas_dbus_getter_current_auth_mode, 3358 NULL, 3359 NULL 3360 }, 3361 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}", 3362 wpas_dbus_getter_blobs, 3363 NULL, 3364 NULL 3365 }, 3366 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 3367 wpas_dbus_getter_bsss, 3368 NULL, 3369 NULL 3370 }, 3371 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 3372 wpas_dbus_getter_networks, 3373 NULL, 3374 NULL 3375 }, 3376 { "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 3377 wpas_dbus_getter_fast_reauth, 3378 wpas_dbus_setter_fast_reauth, 3379 NULL 3380 }, 3381 { "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3382 wpas_dbus_getter_scan_interval, 3383 wpas_dbus_setter_scan_interval, 3384 NULL 3385 }, 3386 { "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3387 wpas_dbus_getter_pkcs11_engine_path, 3388 NULL, 3389 NULL 3390 }, 3391 { "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 3392 wpas_dbus_getter_pkcs11_module_path, 3393 NULL, 3394 NULL 3395 }, 3396 #ifdef CONFIG_WPS 3397 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b", 3398 wpas_dbus_getter_process_credentials, 3399 wpas_dbus_setter_process_credentials, 3400 NULL 3401 }, 3402 { "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s", 3403 wpas_dbus_getter_config_methods, 3404 wpas_dbus_setter_config_methods, 3405 NULL 3406 }, 3407 { 3408 "DeviceName", WPAS_DBUS_NEW_IFACE_WPS, "s", 3409 wpas_dbus_getter_wps_device_name, 3410 wpas_dbus_setter_wps_device_name, 3411 NULL 3412 }, 3413 { 3414 "Manufacturer", WPAS_DBUS_NEW_IFACE_WPS, "s", 3415 wpas_dbus_getter_wps_manufacturer, 3416 wpas_dbus_setter_wps_manufacturer, 3417 NULL 3418 }, 3419 { 3420 "ModelName", WPAS_DBUS_NEW_IFACE_WPS, "s", 3421 wpas_dbus_getter_wps_device_model_name, 3422 wpas_dbus_setter_wps_device_model_name, 3423 NULL 3424 }, 3425 { 3426 "ModelNumber", WPAS_DBUS_NEW_IFACE_WPS, "s", 3427 wpas_dbus_getter_wps_device_model_number, 3428 wpas_dbus_setter_wps_device_model_number, 3429 NULL 3430 }, 3431 { 3432 "SerialNumber", WPAS_DBUS_NEW_IFACE_WPS, "s", 3433 wpas_dbus_getter_wps_device_serial_number, 3434 wpas_dbus_setter_wps_device_serial_number, 3435 NULL 3436 }, 3437 { 3438 "DeviceType", WPAS_DBUS_NEW_IFACE_WPS, "ay", 3439 wpas_dbus_getter_wps_device_device_type, 3440 wpas_dbus_setter_wps_device_device_type, 3441 NULL 3442 }, 3443 #endif /* CONFIG_WPS */ 3444 #ifdef CONFIG_P2P 3445 { "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}", 3446 wpas_dbus_getter_p2p_device_config, 3447 wpas_dbus_setter_p2p_device_config, 3448 NULL 3449 }, 3450 { "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 3451 wpas_dbus_getter_p2p_peers, 3452 NULL, 3453 NULL 3454 }, 3455 { "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s", 3456 wpas_dbus_getter_p2p_role, 3457 NULL, 3458 NULL 3459 }, 3460 { "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 3461 wpas_dbus_getter_p2p_group, 3462 NULL, 3463 NULL 3464 }, 3465 { "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o", 3466 wpas_dbus_getter_p2p_peergo, 3467 NULL, 3468 NULL 3469 }, 3470 { "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao", 3471 wpas_dbus_getter_persistent_groups, 3472 NULL, 3473 NULL 3474 }, 3475 #endif /* CONFIG_P2P */ 3476 { "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3477 wpas_dbus_getter_disconnect_reason, 3478 NULL, 3479 NULL 3480 }, 3481 { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i", 3482 wpas_dbus_getter_assoc_status_code, 3483 NULL, 3484 NULL 3485 }, 3486 #ifdef CONFIG_MESH 3487 { "MeshPeers", WPAS_DBUS_NEW_IFACE_MESH, "aay", 3488 wpas_dbus_getter_mesh_peers, 3489 NULL, 3490 NULL 3491 }, 3492 { "MeshGroup", WPAS_DBUS_NEW_IFACE_MESH, "ay", 3493 wpas_dbus_getter_mesh_group, 3494 NULL, 3495 NULL 3496 }, 3497 #endif /* CONFIG_MESH */ 3498 { NULL, NULL, NULL, NULL, NULL, NULL } 3499 }; 3500 3501 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { 3502 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE, 3503 { 3504 { "success", "b", ARG_OUT }, 3505 END_ARGS 3506 } 3507 }, 3508 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3509 { 3510 { "path", "o", ARG_OUT }, 3511 { "properties", "a{sv}", ARG_OUT }, 3512 END_ARGS 3513 } 3514 }, 3515 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3516 { 3517 { "path", "o", ARG_OUT }, 3518 END_ARGS 3519 } 3520 }, 3521 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3522 { 3523 { "name", "s", ARG_OUT }, 3524 END_ARGS 3525 } 3526 }, 3527 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3528 { 3529 { "name", "s", ARG_OUT }, 3530 END_ARGS 3531 } 3532 }, 3533 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 3534 { 3535 { "path", "o", ARG_OUT }, 3536 { "properties", "a{sv}", ARG_OUT }, 3537 END_ARGS 3538 } 3539 }, 3540 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 3541 { 3542 { "path", "o", ARG_OUT }, 3543 END_ARGS 3544 } 3545 }, 3546 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE, 3547 { 3548 { "path", "o", ARG_OUT }, 3549 END_ARGS 3550 } 3551 }, 3552 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3553 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE, 3554 { 3555 { "properties", "a{sv}", ARG_OUT }, 3556 END_ARGS 3557 } 3558 }, 3559 #ifdef CONFIG_WPS 3560 { "Event", WPAS_DBUS_NEW_IFACE_WPS, 3561 { 3562 { "name", "s", ARG_OUT }, 3563 { "args", "a{sv}", ARG_OUT }, 3564 END_ARGS 3565 } 3566 }, 3567 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS, 3568 { 3569 { "credentials", "a{sv}", ARG_OUT }, 3570 END_ARGS 3571 } 3572 }, 3573 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 3574 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS, 3575 { 3576 { "properties", "a{sv}", ARG_OUT }, 3577 END_ARGS 3578 } 3579 }, 3580 #endif /* CONFIG_WPS */ 3581 #ifdef CONFIG_P2P 3582 { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3583 { 3584 { "path", "o", ARG_OUT }, 3585 END_ARGS 3586 } 3587 }, 3588 { "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3589 { 3590 { "path", "o", ARG_OUT }, 3591 { "properties", "a{sv}", ARG_OUT }, 3592 END_ARGS 3593 } 3594 }, 3595 { "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3596 { 3597 { "path", "o", ARG_OUT }, 3598 END_ARGS 3599 } 3600 }, 3601 { "FindStopped", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3602 { 3603 END_ARGS 3604 } 3605 }, 3606 { "ProvisionDiscoveryRequestDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3607 { 3608 { "peer_object", "o", ARG_OUT }, 3609 { "pin", "s", ARG_OUT }, 3610 END_ARGS 3611 } 3612 }, 3613 { "ProvisionDiscoveryResponseDisplayPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3614 { 3615 { "peer_object", "o", ARG_OUT }, 3616 { "pin", "s", ARG_OUT }, 3617 END_ARGS 3618 } 3619 }, 3620 { "ProvisionDiscoveryRequestEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3621 { 3622 { "peer_object", "o", ARG_OUT }, 3623 END_ARGS 3624 } 3625 }, 3626 { "ProvisionDiscoveryResponseEnterPin", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3627 { 3628 { "peer_object", "o", ARG_OUT }, 3629 END_ARGS 3630 } 3631 }, 3632 { "ProvisionDiscoveryPBCRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3633 { 3634 { "peer_object", "o", ARG_OUT }, 3635 END_ARGS 3636 } 3637 }, 3638 { "ProvisionDiscoveryPBCResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3639 { 3640 { "peer_object", "o", ARG_OUT }, 3641 END_ARGS 3642 } 3643 }, 3644 { "ProvisionDiscoveryFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3645 { 3646 { "peer_object", "o", ARG_OUT }, 3647 { "status", "i", ARG_OUT }, 3648 END_ARGS 3649 } 3650 }, 3651 { "GroupStarted", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3652 { 3653 { "properties", "a{sv}", ARG_OUT }, 3654 END_ARGS 3655 } 3656 }, 3657 { "GroupFormationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3658 { 3659 { "reason", "s", ARG_OUT }, 3660 END_ARGS 3661 } 3662 }, 3663 { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3664 { 3665 { "properties", "a{sv}", ARG_OUT }, 3666 END_ARGS 3667 } 3668 }, 3669 { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3670 { 3671 { "properties", "a{sv}", ARG_OUT }, 3672 END_ARGS 3673 } 3674 }, 3675 { "GONegotiationRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3676 { 3677 { "path", "o", ARG_OUT }, 3678 { "dev_passwd_id", "q", ARG_OUT }, 3679 { "device_go_intent", "y", ARG_OUT }, 3680 END_ARGS 3681 } 3682 }, 3683 { "InvitationResult", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3684 { 3685 { "invite_result", "a{sv}", ARG_OUT }, 3686 END_ARGS 3687 } 3688 }, 3689 { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3690 { 3691 { "properties", "a{sv}", ARG_OUT }, 3692 END_ARGS 3693 } 3694 }, 3695 { "ServiceDiscoveryRequest", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3696 { 3697 { "sd_request", "a{sv}", ARG_OUT }, 3698 END_ARGS 3699 } 3700 }, 3701 { "ServiceDiscoveryResponse", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3702 { 3703 { "sd_response", "a{sv}", ARG_OUT }, 3704 END_ARGS 3705 } 3706 }, 3707 { "PersistentGroupAdded", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3708 { 3709 { "path", "o", ARG_OUT }, 3710 { "properties", "a{sv}", ARG_OUT }, 3711 END_ARGS 3712 } 3713 }, 3714 { "PersistentGroupRemoved", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3715 { 3716 { "path", "o", ARG_OUT }, 3717 END_ARGS 3718 } 3719 }, 3720 { "WpsFailed", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3721 { 3722 { "name", "s", ARG_OUT }, 3723 { "args", "a{sv}", ARG_OUT }, 3724 END_ARGS 3725 } 3726 }, 3727 { "InvitationReceived", WPAS_DBUS_NEW_IFACE_P2PDEVICE, 3728 { 3729 { "properties", "a{sv}", ARG_OUT }, 3730 END_ARGS 3731 } 3732 }, 3733 #endif /* CONFIG_P2P */ 3734 #ifdef CONFIG_AP 3735 { "ProbeRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 3736 { 3737 { "args", "a{sv}", ARG_OUT }, 3738 END_ARGS 3739 } 3740 }, 3741 #endif /* CONFIG_AP */ 3742 { "Certification", WPAS_DBUS_NEW_IFACE_INTERFACE, 3743 { 3744 { "certification", "a{sv}", ARG_OUT }, 3745 END_ARGS 3746 } 3747 }, 3748 { "EAP", WPAS_DBUS_NEW_IFACE_INTERFACE, 3749 { 3750 { "status", "s", ARG_OUT }, 3751 { "parameter", "s", ARG_OUT }, 3752 END_ARGS 3753 } 3754 }, 3755 { "StaAuthorized", WPAS_DBUS_NEW_IFACE_INTERFACE, 3756 { 3757 { "name", "s", ARG_OUT }, 3758 END_ARGS 3759 } 3760 }, 3761 { "StaDeauthorized", WPAS_DBUS_NEW_IFACE_INTERFACE, 3762 { 3763 { "name", "s", ARG_OUT }, 3764 END_ARGS 3765 } 3766 }, 3767 { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE, 3768 { 3769 { "path", "o", ARG_OUT }, 3770 { "field", "s", ARG_OUT }, 3771 { "text", "s", ARG_OUT }, 3772 END_ARGS 3773 } 3774 }, 3775 #ifdef CONFIG_MESH 3776 { "MeshGroupStarted", WPAS_DBUS_NEW_IFACE_MESH, 3777 { 3778 { "args", "a{sv}", ARG_OUT }, 3779 END_ARGS 3780 } 3781 }, 3782 { "MeshGroupRemoved", WPAS_DBUS_NEW_IFACE_MESH, 3783 { 3784 { "args", "a{sv}", ARG_OUT }, 3785 END_ARGS 3786 } 3787 }, 3788 { "MeshPeerConnected", WPAS_DBUS_NEW_IFACE_MESH, 3789 { 3790 { "args", "a{sv}", ARG_OUT }, 3791 END_ARGS 3792 } 3793 }, 3794 { "MeshPeerDisconnected", WPAS_DBUS_NEW_IFACE_MESH, 3795 { 3796 { "args", "a{sv}", ARG_OUT }, 3797 END_ARGS 3798 } 3799 }, 3800 #endif /* CONFIG_MESH */ 3801 { NULL, NULL, { END_ARGS } } 3802 }; 3803 3804 3805 static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv) 3806 { 3807 size_t all_size; 3808 unsigned int i, j, count, num_const, num_globals; 3809 const char *global_name; 3810 static const char * const ignored_globals[] = { 3811 "bss_expiration_age", "bss_expiration_scan_count", 3812 "ap_scan", "country", "fast_reauth", 3813 "pkcs11_engine_path", "pkcs11_module_path" 3814 }; 3815 3816 /* wpas_dbus_interface_properties terminates with a NULL element */ 3817 num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1; 3818 3819 num_globals = wpa_config_get_num_global_field_names(); 3820 priv->globals_start = num_const; 3821 3822 /* allocate enough for all properties + terminating NULL element */ 3823 all_size = (num_globals + num_const + 1) * 3824 sizeof(wpas_dbus_interface_properties[0]); 3825 priv->all_interface_properties = os_zalloc(all_size); 3826 if (!priv->all_interface_properties) { 3827 wpa_printf(MSG_ERROR, 3828 "dbus: Not enough memory for interface properties"); 3829 return -1; 3830 } 3831 3832 /* Copy constant interface properties to the start of the array */ 3833 os_memcpy(priv->all_interface_properties, 3834 wpas_dbus_interface_properties, 3835 sizeof(wpas_dbus_interface_properties)); 3836 3837 /* Dynamically construct interface global properties */ 3838 for (i = 0, count = num_const; i < num_globals; i++) { 3839 struct wpa_dbus_property_desc *desc; 3840 int no_var = 0; 3841 3842 /* ignore globals that are actually just methods */ 3843 global_name = wpa_config_get_global_field_name(i, &no_var); 3844 if (no_var) 3845 continue; 3846 /* Ignore fields already explicitly exposed */ 3847 for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) { 3848 if (os_strcmp(global_name, ignored_globals[j]) == 0) 3849 break; 3850 } 3851 if (j < ARRAY_SIZE(ignored_globals)) 3852 continue; 3853 3854 desc = &priv->all_interface_properties[count++]; 3855 desc->dbus_property = uscore_to_dbus(global_name); 3856 if (!desc->dbus_property) { 3857 wpa_printf(MSG_ERROR, 3858 "dbus: Not enough memory for D-Bus property name"); 3859 goto error; 3860 } 3861 desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE; 3862 desc->type = "s"; 3863 desc->getter = wpas_dbus_getter_iface_global; 3864 desc->setter = wpas_dbus_setter_iface_global; 3865 desc->data = global_name; 3866 } 3867 3868 return 0; 3869 3870 error: 3871 wpa_dbus_ctrl_iface_props_deinit(priv); 3872 return -1; 3873 } 3874 3875 3876 /** 3877 * wpas_dbus_register_interface - Register an interface with D-Bus 3878 * @wpa_s: wpa_supplicant interface structure 3879 * Returns: 0 on success, -1 on failure 3880 */ 3881 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s) 3882 { 3883 struct wpa_dbus_object_desc *obj_desc = NULL; 3884 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus; 3885 int next; 3886 3887 /* Do nothing if the control interface is not turned on */ 3888 if (ctrl_iface == NULL) 3889 return 0; 3890 3891 /* Create and set the interface's object path */ 3892 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 3893 if (wpa_s->dbus_new_path == NULL) 3894 return -1; 3895 next = ctrl_iface->next_objid++; 3896 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX, 3897 WPAS_DBUS_NEW_PATH_INTERFACES "/%u", 3898 next); 3899 3900 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 3901 if (!obj_desc) { 3902 wpa_printf(MSG_ERROR, 3903 "Not enough memory to create object description"); 3904 goto err; 3905 } 3906 3907 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods, 3908 ctrl_iface->all_interface_properties, 3909 wpas_dbus_interface_signals); 3910 3911 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", 3912 wpa_s->dbus_new_path); 3913 if (wpa_dbus_register_object_per_iface(ctrl_iface, 3914 wpa_s->dbus_new_path, 3915 wpa_s->ifname, obj_desc)) 3916 goto err; 3917 3918 wpas_dbus_signal_interface_added(wpa_s); 3919 3920 return 0; 3921 3922 err: 3923 os_free(wpa_s->dbus_new_path); 3924 wpa_s->dbus_new_path = NULL; 3925 free_dbus_object_desc(obj_desc); 3926 return -1; 3927 } 3928 3929 3930 /** 3931 * wpas_dbus_unregister_interface - Unregister the interface from D-Bus 3932 * @wpa_s: wpa_supplicant interface structure 3933 * Returns: 0 on success, -1 on failure 3934 */ 3935 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s) 3936 { 3937 struct wpas_dbus_priv *ctrl_iface; 3938 3939 /* Do nothing if the control interface is not turned on */ 3940 if (wpa_s == NULL || wpa_s->global == NULL) 3941 return 0; 3942 ctrl_iface = wpa_s->global->dbus; 3943 if (ctrl_iface == NULL || wpa_s->dbus_new_path == NULL) 3944 return 0; 3945 3946 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'", 3947 wpa_s->dbus_new_path); 3948 3949 #ifdef CONFIG_AP 3950 if (wpa_s->preq_notify_peer) { 3951 wpas_dbus_unsubscribe_noc(ctrl_iface); 3952 os_free(wpa_s->preq_notify_peer); 3953 wpa_s->preq_notify_peer = NULL; 3954 } 3955 #endif /* CONFIG_AP */ 3956 3957 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, 3958 wpa_s->dbus_new_path)) 3959 return -1; 3960 3961 wpas_dbus_signal_interface_removed(wpa_s); 3962 3963 os_free(wpa_s->dbus_new_path); 3964 wpa_s->dbus_new_path = NULL; 3965 3966 return 0; 3967 } 3968 3969 #ifdef CONFIG_P2P 3970 3971 static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = { 3972 { "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 3973 wpas_dbus_getter_p2p_peer_device_name, 3974 NULL, 3975 NULL 3976 }, 3977 { "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 3978 wpas_dbus_getter_p2p_peer_manufacturer, 3979 NULL, 3980 NULL 3981 }, 3982 { "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 3983 wpas_dbus_getter_p2p_peer_modelname, 3984 NULL, 3985 NULL 3986 }, 3987 { "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 3988 wpas_dbus_getter_p2p_peer_modelnumber, 3989 NULL, 3990 NULL 3991 }, 3992 { "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s", 3993 wpas_dbus_getter_p2p_peer_serialnumber, 3994 NULL, 3995 NULL 3996 }, 3997 { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 3998 wpas_dbus_getter_p2p_peer_primary_device_type, 3999 NULL, 4000 NULL 4001 }, 4002 { "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q", 4003 wpas_dbus_getter_p2p_peer_config_method, 4004 NULL, 4005 NULL 4006 }, 4007 { "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i", 4008 wpas_dbus_getter_p2p_peer_level, 4009 NULL, 4010 NULL 4011 }, 4012 { "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 4013 wpas_dbus_getter_p2p_peer_device_capability, 4014 NULL, 4015 NULL 4016 }, 4017 { "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", 4018 wpas_dbus_getter_p2p_peer_group_capability, 4019 NULL, 4020 NULL 4021 }, 4022 { "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 4023 wpas_dbus_getter_p2p_peer_secondary_device_types, 4024 NULL, 4025 NULL 4026 }, 4027 { "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", 4028 wpas_dbus_getter_p2p_peer_vendor_extension, 4029 NULL, 4030 NULL 4031 }, 4032 { "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4033 wpas_dbus_getter_p2p_peer_ies, 4034 NULL, 4035 NULL 4036 }, 4037 { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", 4038 wpas_dbus_getter_p2p_peer_device_address, 4039 NULL, 4040 NULL 4041 }, 4042 { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao", 4043 wpas_dbus_getter_p2p_peer_groups, 4044 NULL, 4045 NULL 4046 }, 4047 { NULL, NULL, NULL, NULL, NULL, NULL } 4048 }; 4049 4050 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = { 4051 /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */ 4052 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER, 4053 { 4054 { "properties", "a{sv}", ARG_OUT }, 4055 END_ARGS 4056 } 4057 }, 4058 { NULL, NULL, { END_ARGS } } 4059 }; 4060 4061 /** 4062 * wpas_dbus_signal_peer - Send a peer related event signal 4063 * @wpa_s: %wpa_supplicant network interface data 4064 * @dev: peer device object 4065 * @interface: name of the interface emitting this signal. 4066 * In case of peer objects, it would be emitted by either 4067 * the "interface object" or by "peer objects" 4068 * @sig_name: signal name - DeviceFound 4069 * @properties: Whether to add a second argument with object properties 4070 * 4071 * Notify listeners about event related with p2p peer device 4072 */ 4073 static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s, 4074 const u8 *dev_addr, const char *interface, 4075 const char *sig_name, int properties) 4076 { 4077 struct wpas_dbus_priv *iface; 4078 DBusMessage *msg; 4079 DBusMessageIter iter; 4080 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 4081 4082 if (wpa_s->p2p_mgmt) 4083 wpa_s = wpa_s->parent; 4084 4085 iface = wpa_s->global->dbus; 4086 4087 /* Do nothing if the control interface is not turned on */ 4088 if (iface == NULL || !wpa_s->dbus_new_path) 4089 return; 4090 4091 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4092 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4093 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4094 4095 msg = dbus_message_new_signal(wpa_s->dbus_new_path, interface, 4096 sig_name); 4097 if (msg == NULL) 4098 return; 4099 4100 dbus_message_iter_init_append(msg, &iter); 4101 path = peer_obj_path; 4102 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 4103 &path) || 4104 (properties && !wpa_dbus_get_object_properties( 4105 iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER, 4106 &iter))) 4107 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 4108 else 4109 dbus_connection_send(iface->con, msg, NULL); 4110 4111 dbus_message_unref(msg); 4112 } 4113 4114 4115 /** 4116 * wpas_dbus_signal_peer_found - Send a peer found signal 4117 * @wpa_s: %wpa_supplicant network interface data 4118 * @dev_addr: Peer P2P Device Address 4119 * 4120 * Notify listeners about find a p2p peer device found 4121 */ 4122 void wpas_dbus_signal_peer_device_found(struct wpa_supplicant *wpa_s, 4123 const u8 *dev_addr) 4124 { 4125 wpas_dbus_signal_peer(wpa_s, dev_addr, 4126 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4127 "DeviceFound", FALSE); 4128 4129 wpas_dbus_signal_peer(wpa_s, dev_addr, 4130 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4131 "DeviceFoundProperties", TRUE); 4132 } 4133 4134 /** 4135 * wpas_dbus_signal_peer_lost - Send a peer lost signal 4136 * @wpa_s: %wpa_supplicant network interface data 4137 * @dev_addr: Peer P2P Device Address 4138 * 4139 * Notify listeners about lost a p2p peer device 4140 */ 4141 void wpas_dbus_signal_peer_device_lost(struct wpa_supplicant *wpa_s, 4142 const u8 *dev_addr) 4143 { 4144 wpas_dbus_signal_peer(wpa_s, dev_addr, 4145 WPAS_DBUS_NEW_IFACE_P2PDEVICE, 4146 "DeviceLost", FALSE); 4147 } 4148 4149 /** 4150 * wpas_dbus_register_peer - Register a discovered peer object with dbus 4151 * @wpa_s: wpa_supplicant interface structure 4152 * @dev_addr: P2P Device Address of the peer 4153 * Returns: 0 on success, -1 on failure 4154 * 4155 * Registers network representing object with dbus 4156 */ 4157 int wpas_dbus_register_peer(struct wpa_supplicant *wpa_s, const u8 *dev_addr) 4158 { 4159 struct wpas_dbus_priv *ctrl_iface; 4160 struct wpa_dbus_object_desc *obj_desc; 4161 struct peer_handler_args *arg; 4162 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4163 4164 /* Do nothing if the control interface is not turned on */ 4165 if (wpa_s == NULL || wpa_s->global == NULL) 4166 return 0; 4167 4168 ctrl_iface = wpa_s->global->dbus; 4169 if (ctrl_iface == NULL) 4170 return 0; 4171 4172 wpa_s = wpa_s->parent->parent; 4173 if (!wpa_s->dbus_new_path) 4174 return 0; 4175 4176 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4177 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4178 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4179 4180 wpa_printf(MSG_INFO, "dbus: Register peer object '%s'", 4181 peer_obj_path); 4182 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 4183 if (!obj_desc) { 4184 wpa_printf(MSG_ERROR, 4185 "Not enough memory to create object description"); 4186 goto err; 4187 } 4188 4189 /* allocate memory for handlers arguments */ 4190 arg = os_zalloc(sizeof(struct peer_handler_args)); 4191 if (!arg) { 4192 wpa_printf(MSG_ERROR, 4193 "Not enough memory to create arguments for method"); 4194 goto err; 4195 } 4196 4197 arg->wpa_s = wpa_s; 4198 os_memcpy(arg->p2p_device_addr, dev_addr, ETH_ALEN); 4199 4200 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, 4201 NULL, 4202 wpas_dbus_p2p_peer_properties, 4203 wpas_dbus_p2p_peer_signals); 4204 4205 if (wpa_dbus_register_object_per_iface(ctrl_iface, peer_obj_path, 4206 wpa_s->ifname, obj_desc)) 4207 goto err; 4208 4209 return 0; 4210 4211 err: 4212 free_dbus_object_desc(obj_desc); 4213 return -1; 4214 } 4215 4216 /** 4217 * wpas_dbus_unregister_peer - Unregister a peer object with dbus 4218 * @wpa_s: wpa_supplicant interface structure 4219 * @dev_addr: p2p device addr 4220 * Returns: 0 on success, -1 on failure 4221 * 4222 * Registers network representing object with dbus 4223 */ 4224 int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s, 4225 const u8 *dev_addr) 4226 { 4227 struct wpas_dbus_priv *ctrl_iface; 4228 char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 4229 int ret; 4230 4231 /* Do nothing if the control interface is not turned on */ 4232 if (wpa_s == NULL || wpa_s->global == NULL) 4233 return 0; 4234 4235 wpa_s = wpa_s->parent->parent; 4236 if (!wpa_s->dbus_new_path) 4237 return 0; 4238 4239 ctrl_iface = wpa_s->global->dbus; 4240 if (ctrl_iface == NULL) 4241 return 0; 4242 4243 os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 4244 "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR, 4245 wpa_s->dbus_new_path, MAC2STR(dev_addr)); 4246 4247 wpa_printf(MSG_INFO, "dbus: Unregister peer object '%s'", 4248 peer_obj_path); 4249 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, peer_obj_path); 4250 4251 return ret; 4252 } 4253 4254 4255 /** 4256 * wpas_dbus_signal_p2p_find_stopped - Send P2P Find stopped signal 4257 * @wpa_s: %wpa_supplicant network interface data 4258 * 4259 * Notify listeners about P2P Find stopped 4260 */ 4261 void wpas_dbus_signal_p2p_find_stopped(struct wpa_supplicant *wpa_s) 4262 { 4263 struct wpas_dbus_priv *iface; 4264 DBusMessage *msg; 4265 4266 iface = wpa_s->global->dbus; 4267 4268 /* Do nothing if the control interface is not turned on */ 4269 if (iface == NULL || !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