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