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