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