1 /* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com> 5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 6 * 7 * This 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 "wps/wps.h" 21 #include "../config.h" 22 #include "../wpa_supplicant_i.h" 23 #include "../bss.h" 24 #include "dbus_new_helpers.h" 25 #include "dbus_dict_helpers.h" 26 #include "dbus_new.h" 27 #include "dbus_new_handlers.h" 28 #include "dbus_common.h" 29 #include "dbus_common_i.h" 30 31 32 /** 33 * wpas_dbus_signal_interface - Send a interface related event signal 34 * @wpa_s: %wpa_supplicant network interface data 35 * @sig_name: signal name - InterfaceAdded or InterfaceRemoved 36 * @properties: Whether to add second argument with object properties 37 * 38 * Notify listeners about event related with interface 39 */ 40 static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s, 41 const char *sig_name, int properties) 42 { 43 struct wpas_dbus_priv *iface; 44 DBusMessage *msg; 45 DBusMessageIter iter, iter_dict; 46 47 iface = wpa_s->global->dbus; 48 49 /* Do nothing if the control interface is not turned on */ 50 if (iface == NULL) 51 return; 52 53 msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH, 54 WPAS_DBUS_NEW_INTERFACE, sig_name); 55 if (msg == NULL) 56 return; 57 58 dbus_message_iter_init_append(msg, &iter); 59 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 60 &wpa_s->dbus_new_path)) 61 goto err; 62 63 if (properties) { 64 if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 65 goto err; 66 67 wpa_dbus_get_object_properties(iface, wpa_s->dbus_new_path, 68 WPAS_DBUS_NEW_IFACE_INTERFACE, 69 &iter_dict); 70 71 if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 72 goto err; 73 } 74 75 dbus_connection_send(iface->con, msg, NULL); 76 dbus_message_unref(msg); 77 return; 78 79 err: 80 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 81 dbus_message_unref(msg); 82 } 83 84 85 /** 86 * wpas_dbus_signal_interface_added - Send a interface created signal 87 * @wpa_s: %wpa_supplicant network interface data 88 * 89 * Notify listeners about creating new interface 90 */ 91 static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s) 92 { 93 wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE); 94 } 95 96 97 /** 98 * wpas_dbus_signal_interface_removed - Send a interface removed signal 99 * @wpa_s: %wpa_supplicant network interface data 100 * 101 * Notify listeners about removing interface 102 */ 103 static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s) 104 { 105 wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE); 106 107 } 108 109 110 /** 111 * wpas_dbus_signal_scan_done - send scan done signal 112 * @wpa_s: %wpa_supplicant network interface data 113 * @success: indicates if scanning succeed or failed 114 * 115 * Notify listeners about finishing a scan 116 */ 117 void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success) 118 { 119 struct wpas_dbus_priv *iface; 120 DBusMessage *msg; 121 dbus_bool_t succ; 122 123 iface = wpa_s->global->dbus; 124 125 /* Do nothing if the control interface is not turned on */ 126 if (iface == NULL) 127 return; 128 129 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 130 WPAS_DBUS_NEW_IFACE_INTERFACE, 131 "ScanDone"); 132 if (msg == NULL) 133 return; 134 135 succ = success ? TRUE : FALSE; 136 if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ, 137 DBUS_TYPE_INVALID)) 138 dbus_connection_send(iface->con, msg, NULL); 139 else 140 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 141 dbus_message_unref(msg); 142 } 143 144 145 /** 146 * wpas_dbus_signal_blob - Send a BSS related event signal 147 * @wpa_s: %wpa_supplicant network interface data 148 * @bss_obj_path: BSS object path 149 * @sig_name: signal name - BSSAdded or BSSRemoved 150 * @properties: Whether to add second argument with object properties 151 * 152 * Notify listeners about event related with BSS 153 */ 154 static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s, 155 const char *bss_obj_path, 156 const char *sig_name, int properties) 157 { 158 struct wpas_dbus_priv *iface; 159 DBusMessage *msg; 160 DBusMessageIter iter, iter_dict; 161 162 iface = wpa_s->global->dbus; 163 164 /* Do nothing if the control interface is not turned on */ 165 if (iface == NULL) 166 return; 167 168 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 169 WPAS_DBUS_NEW_IFACE_INTERFACE, 170 sig_name); 171 if (msg == NULL) 172 return; 173 174 dbus_message_iter_init_append(msg, &iter); 175 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 176 &bss_obj_path)) 177 goto err; 178 179 if (properties) { 180 if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 181 goto err; 182 183 wpa_dbus_get_object_properties(iface, bss_obj_path, 184 WPAS_DBUS_NEW_IFACE_BSS, 185 &iter_dict); 186 187 if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 188 goto err; 189 } 190 191 dbus_connection_send(iface->con, msg, NULL); 192 dbus_message_unref(msg); 193 return; 194 195 err: 196 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 197 dbus_message_unref(msg); 198 } 199 200 201 /** 202 * wpas_dbus_signal_bss_added - Send a BSS added signal 203 * @wpa_s: %wpa_supplicant network interface data 204 * @bss_obj_path: new BSS object path 205 * 206 * Notify listeners about adding new BSS 207 */ 208 static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s, 209 const char *bss_obj_path) 210 { 211 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE); 212 } 213 214 215 /** 216 * wpas_dbus_signal_bss_removed - Send a BSS removed signal 217 * @wpa_s: %wpa_supplicant network interface data 218 * @bss_obj_path: BSS object path 219 * 220 * Notify listeners about removing BSS 221 */ 222 static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s, 223 const char *bss_obj_path) 224 { 225 wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE); 226 } 227 228 229 /** 230 * wpas_dbus_signal_blob - Send a blob related event signal 231 * @wpa_s: %wpa_supplicant network interface data 232 * @name: blob name 233 * @sig_name: signal name - BlobAdded or BlobRemoved 234 * 235 * Notify listeners about event related with blob 236 */ 237 static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s, 238 const char *name, const char *sig_name) 239 { 240 struct wpas_dbus_priv *iface; 241 DBusMessage *msg; 242 243 iface = wpa_s->global->dbus; 244 245 /* Do nothing if the control interface is not turned on */ 246 if (iface == NULL) 247 return; 248 249 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 250 WPAS_DBUS_NEW_IFACE_INTERFACE, 251 sig_name); 252 if (msg == NULL) 253 return; 254 255 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name, 256 DBUS_TYPE_INVALID)) 257 dbus_connection_send(iface->con, msg, NULL); 258 else 259 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 260 dbus_message_unref(msg); 261 } 262 263 264 /** 265 * wpas_dbus_signal_blob_added - Send a blob added signal 266 * @wpa_s: %wpa_supplicant network interface data 267 * @name: blob name 268 * 269 * Notify listeners about adding a new blob 270 */ 271 void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s, 272 const char *name) 273 { 274 wpas_dbus_signal_blob(wpa_s, name, "BlobAdded"); 275 } 276 277 278 /** 279 * wpas_dbus_signal_blob_removed - Send a blob removed signal 280 * @wpa_s: %wpa_supplicant network interface data 281 * @name: blob name 282 * 283 * Notify listeners about removing blob 284 */ 285 void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s, 286 const char *name) 287 { 288 wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved"); 289 } 290 291 292 /** 293 * wpas_dbus_signal_network - Send a network related event signal 294 * @wpa_s: %wpa_supplicant network interface data 295 * @id: new network id 296 * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected 297 * @properties: determines if add second argument with object properties 298 * 299 * Notify listeners about event related with configured network 300 */ 301 static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s, 302 int id, const char *sig_name, 303 int properties) 304 { 305 struct wpas_dbus_priv *iface; 306 DBusMessage *msg; 307 DBusMessageIter iter, iter_dict; 308 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path; 309 310 iface = wpa_s->global->dbus; 311 312 /* Do nothing if the control interface is not turned on */ 313 if (iface == NULL) 314 return; 315 316 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 317 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 318 wpa_s->dbus_new_path, id); 319 320 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 321 WPAS_DBUS_NEW_IFACE_INTERFACE, 322 sig_name); 323 if (msg == NULL) 324 return; 325 326 dbus_message_iter_init_append(msg, &iter); 327 path = net_obj_path; 328 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, 329 &path)) 330 goto err; 331 332 if (properties) { 333 if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 334 goto err; 335 336 wpa_dbus_get_object_properties(iface, net_obj_path, 337 WPAS_DBUS_NEW_IFACE_NETWORK, 338 &iter_dict); 339 340 if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 341 goto err; 342 } 343 344 dbus_connection_send(iface->con, msg, NULL); 345 346 dbus_message_unref(msg); 347 return; 348 349 err: 350 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 351 dbus_message_unref(msg); 352 } 353 354 355 /** 356 * wpas_dbus_signal_network_added - Send a network added signal 357 * @wpa_s: %wpa_supplicant network interface data 358 * @id: new network id 359 * 360 * Notify listeners about adding new network 361 */ 362 static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s, 363 int id) 364 { 365 wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE); 366 } 367 368 369 /** 370 * wpas_dbus_signal_network_removed - Send a network removed signal 371 * @wpa_s: %wpa_supplicant network interface data 372 * @id: network id 373 * 374 * Notify listeners about removing a network 375 */ 376 static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s, 377 int id) 378 { 379 wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE); 380 } 381 382 383 /** 384 * wpas_dbus_signal_network_selected - Send a network selected signal 385 * @wpa_s: %wpa_supplicant network interface data 386 * @id: network id 387 * 388 * Notify listeners about selecting a network 389 */ 390 void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id) 391 { 392 wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE); 393 } 394 395 396 /** 397 * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes 398 * @wpa_s: %wpa_supplicant network interface data 399 * @ssid: configured network which Enabled property has changed 400 * 401 * Sends PropertyChanged signals containing new value of Enabled property 402 * for specified network 403 */ 404 void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s, 405 struct wpa_ssid *ssid) 406 { 407 408 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 409 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 410 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 411 wpa_s->dbus_new_path, ssid->id); 412 413 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 414 WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled"); 415 } 416 417 418 #ifdef CONFIG_WPS 419 420 /** 421 * wpas_dbus_signal_wps_event_success - Signals Success WPS event 422 * @wpa_s: %wpa_supplicant network interface data 423 * 424 * Sends Event dbus signal with name "success" and empty dict as arguments 425 */ 426 void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s) 427 { 428 429 DBusMessage *msg; 430 DBusMessageIter iter, dict_iter; 431 struct wpas_dbus_priv *iface; 432 char *key = "success"; 433 434 iface = wpa_s->global->dbus; 435 436 /* Do nothing if the control interface is not turned on */ 437 if (iface == NULL) 438 return; 439 440 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 441 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 442 if (msg == NULL) 443 return; 444 445 dbus_message_iter_init_append(msg, &iter); 446 447 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 448 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 449 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 450 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 451 else 452 dbus_connection_send(iface->con, msg, NULL); 453 454 dbus_message_unref(msg); 455 } 456 457 458 /** 459 * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event 460 * @wpa_s: %wpa_supplicant network interface data 461 * 462 * Sends Event dbus signal with name "fail" and dictionary containing 463 * "msg field with fail message number (int32) as arguments 464 */ 465 void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s, 466 struct wps_event_fail *fail) 467 { 468 469 DBusMessage *msg; 470 DBusMessageIter iter, dict_iter; 471 struct wpas_dbus_priv *iface; 472 char *key = "fail"; 473 474 iface = wpa_s->global->dbus; 475 476 /* Do nothing if the control interface is not turned on */ 477 if (iface == NULL) 478 return; 479 480 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 481 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 482 if (msg == NULL) 483 return; 484 485 dbus_message_iter_init_append(msg, &iter); 486 487 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 488 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 489 !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) || 490 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 491 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 492 else 493 dbus_connection_send(iface->con, msg, NULL); 494 495 dbus_message_unref(msg); 496 } 497 498 499 /** 500 * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event 501 * @wpa_s: %wpa_supplicant network interface data 502 * 503 * Sends Event dbus signal with name "m2d" and dictionary containing 504 * fields of wps_event_m2d structure. 505 */ 506 void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s, 507 struct wps_event_m2d *m2d) 508 { 509 510 DBusMessage *msg; 511 DBusMessageIter iter, dict_iter; 512 struct wpas_dbus_priv *iface; 513 char *key = "m2d"; 514 515 iface = wpa_s->global->dbus; 516 517 /* Do nothing if the control interface is not turned on */ 518 if (iface == NULL) 519 return; 520 521 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 522 WPAS_DBUS_NEW_IFACE_WPS, "Event"); 523 if (msg == NULL) 524 return; 525 526 dbus_message_iter_init_append(msg, &iter); 527 528 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) || 529 !wpa_dbus_dict_open_write(&iter, &dict_iter) || 530 !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods", 531 m2d->config_methods) || 532 !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer", 533 (const char *) m2d->manufacturer, 534 m2d->manufacturer_len) || 535 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name", 536 (const char *) m2d->model_name, 537 m2d->model_name_len) || 538 !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number", 539 (const char *) m2d->model_number, 540 m2d->model_number_len) || 541 !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number", 542 (const char *) 543 m2d->serial_number, 544 m2d->serial_number_len) || 545 !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name", 546 (const char *) m2d->dev_name, 547 m2d->dev_name_len) || 548 !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type", 549 (const char *) 550 m2d->primary_dev_type, 8) || 551 !wpa_dbus_dict_append_uint16(&dict_iter, "config_error", 552 m2d->config_error) || 553 !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id", 554 m2d->dev_password_id) || 555 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 556 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 557 else 558 dbus_connection_send(iface->con, msg, NULL); 559 560 dbus_message_unref(msg); 561 } 562 563 564 /** 565 * wpas_dbus_signal_wps_cred - Signals new credentials 566 * @wpa_s: %wpa_supplicant network interface data 567 * 568 * Sends signal with credentials in directory argument 569 */ 570 void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s, 571 const struct wps_credential *cred) 572 { 573 DBusMessage *msg; 574 DBusMessageIter iter, dict_iter; 575 struct wpas_dbus_priv *iface; 576 char *auth_type[6]; /* we have six possible authorization types */ 577 int at_num = 0; 578 char *encr_type[4]; /* we have four possible encryption types */ 579 int et_num = 0; 580 581 iface = wpa_s->global->dbus; 582 583 /* Do nothing if the control interface is not turned on */ 584 if (iface == NULL) 585 return; 586 587 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 588 WPAS_DBUS_NEW_IFACE_WPS, 589 "Credentials"); 590 if (msg == NULL) 591 return; 592 593 dbus_message_iter_init_append(msg, &iter); 594 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) 595 goto nomem; 596 597 if (cred->auth_type & WPS_AUTH_OPEN) 598 auth_type[at_num++] = "open"; 599 if (cred->auth_type & WPS_AUTH_WPAPSK) 600 auth_type[at_num++] = "wpa-psk"; 601 if (cred->auth_type & WPS_AUTH_SHARED) 602 auth_type[at_num++] = "shared"; 603 if (cred->auth_type & WPS_AUTH_WPA) 604 auth_type[at_num++] = "wpa-eap"; 605 if (cred->auth_type & WPS_AUTH_WPA2) 606 auth_type[at_num++] = "wpa2-eap"; 607 if (cred->auth_type & WPS_AUTH_WPA2PSK) 608 auth_type[at_num++] = 609 "wpa2-psk"; 610 611 if (cred->encr_type & WPS_ENCR_NONE) 612 encr_type[et_num++] = "none"; 613 if (cred->encr_type & WPS_ENCR_WEP) 614 encr_type[et_num++] = "wep"; 615 if (cred->encr_type & WPS_ENCR_TKIP) 616 encr_type[et_num++] = "tkip"; 617 if (cred->encr_type & WPS_ENCR_AES) 618 encr_type[et_num++] = "aes"; 619 620 if (wpa_s->current_ssid) { 621 if (!wpa_dbus_dict_append_byte_array( 622 &dict_iter, "BSSID", 623 (const char *) wpa_s->current_ssid->bssid, 624 ETH_ALEN)) 625 goto nomem; 626 } 627 628 if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID", 629 (const char *) cred->ssid, 630 cred->ssid_len) || 631 !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType", 632 (const char **) auth_type, 633 at_num) || 634 !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType", 635 (const char **) encr_type, 636 et_num) || 637 !wpa_dbus_dict_append_byte_array(&dict_iter, "Key", 638 (const char *) cred->key, 639 cred->key_len) || 640 !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex", 641 cred->key_idx) || 642 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 643 goto nomem; 644 645 dbus_connection_send(iface->con, msg, NULL); 646 647 nomem: 648 dbus_message_unref(msg); 649 } 650 651 #endif /* CONFIG_WPS */ 652 653 654 /** 655 * wpas_dbus_signal_prop_changed - Signals change of property 656 * @wpa_s: %wpa_supplicant network interface data 657 * @property: indicates which property has changed 658 * 659 * Sends ProertyChanged signals with path, interface and arguments 660 * depending on which property has changed. 661 */ 662 void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s, 663 enum wpas_dbus_prop property) 664 { 665 WPADBusPropertyAccessor getter; 666 char *prop; 667 668 if (wpa_s->dbus_new_path == NULL) 669 return; /* Skip signal since D-Bus setup is not yet ready */ 670 671 switch (property) { 672 case WPAS_DBUS_PROP_AP_SCAN: 673 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan; 674 prop = "ApScan"; 675 break; 676 case WPAS_DBUS_PROP_SCANNING: 677 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning; 678 prop = "Scanning"; 679 break; 680 case WPAS_DBUS_PROP_STATE: 681 getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state; 682 prop = "State"; 683 break; 684 case WPAS_DBUS_PROP_CURRENT_BSS: 685 getter = (WPADBusPropertyAccessor) 686 wpas_dbus_getter_current_bss; 687 prop = "CurrentBSS"; 688 break; 689 case WPAS_DBUS_PROP_CURRENT_NETWORK: 690 getter = (WPADBusPropertyAccessor) 691 wpas_dbus_getter_current_network; 692 prop = "CurrentNetwork"; 693 break; 694 default: 695 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 696 __func__, property); 697 return; 698 } 699 700 wpa_dbus_mark_property_changed(wpa_s->global->dbus, 701 wpa_s->dbus_new_path, 702 WPAS_DBUS_NEW_IFACE_INTERFACE, prop); 703 } 704 705 706 /** 707 * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property 708 * @wpa_s: %wpa_supplicant network interface data 709 * @property: indicates which property has changed 710 * @id: unique BSS identifier 711 * 712 * Sends PropertyChanged signals with path, interface, and arguments depending 713 * on which property has changed. 714 */ 715 void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s, 716 enum wpas_dbus_bss_prop property, 717 unsigned int id) 718 { 719 char path[WPAS_DBUS_OBJECT_PATH_MAX]; 720 char *prop; 721 722 switch (property) { 723 case WPAS_DBUS_BSS_PROP_SIGNAL: 724 prop = "Signal"; 725 break; 726 case WPAS_DBUS_BSS_PROP_FREQ: 727 prop = "Frequency"; 728 break; 729 case WPAS_DBUS_BSS_PROP_MODE: 730 prop = "Mode"; 731 break; 732 case WPAS_DBUS_BSS_PROP_PRIVACY: 733 prop = "Privacy"; 734 break; 735 case WPAS_DBUS_BSS_PROP_RATES: 736 prop = "Rates"; 737 break; 738 case WPAS_DBUS_BSS_PROP_WPA: 739 prop = "WPA"; 740 break; 741 case WPAS_DBUS_BSS_PROP_RSN: 742 prop = "RSN"; 743 break; 744 case WPAS_DBUS_BSS_PROP_IES: 745 prop = "IEs"; 746 break; 747 default: 748 wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d", 749 __func__, property); 750 return; 751 } 752 753 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 754 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 755 wpa_s->dbus_new_path, id); 756 757 wpa_dbus_mark_property_changed(wpa_s->global->dbus, path, 758 WPAS_DBUS_NEW_IFACE_BSS, prop); 759 } 760 761 762 /** 763 * wpas_dbus_signal_debug_level_changed - Signals change of debug param 764 * @global: wpa_global structure 765 * 766 * Sends ProertyChanged signals informing that debug level has changed. 767 */ 768 void wpas_dbus_signal_debug_level_changed(struct wpa_global *global) 769 { 770 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 771 WPAS_DBUS_NEW_INTERFACE, 772 "DebugLevel"); 773 } 774 775 776 /** 777 * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param 778 * @global: wpa_global structure 779 * 780 * Sends ProertyChanged signals informing that debug timestamp has changed. 781 */ 782 void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global) 783 { 784 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 785 WPAS_DBUS_NEW_INTERFACE, 786 "DebugTimestamp"); 787 } 788 789 790 /** 791 * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param 792 * @global: wpa_global structure 793 * 794 * Sends ProertyChanged signals informing that debug show_keys has changed. 795 */ 796 void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global) 797 { 798 wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH, 799 WPAS_DBUS_NEW_INTERFACE, 800 "DebugShowKeys"); 801 } 802 803 804 static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc, 805 void *priv, 806 WPADBusArgumentFreeFunction priv_free, 807 const struct wpa_dbus_method_desc *methods, 808 const struct wpa_dbus_property_desc *properties, 809 const struct wpa_dbus_signal_desc *signals) 810 { 811 int n; 812 813 obj_desc->user_data = priv; 814 obj_desc->user_data_free_func = priv_free; 815 obj_desc->methods = methods; 816 obj_desc->properties = properties; 817 obj_desc->signals = signals; 818 819 for (n = 0; properties && properties->dbus_property; properties++) 820 n++; 821 822 obj_desc->prop_changed_flags = os_zalloc(n); 823 if (!obj_desc->prop_changed_flags) 824 wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers", 825 __func__); 826 } 827 828 829 static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = { 830 { "CreateInterface", WPAS_DBUS_NEW_INTERFACE, 831 (WPADBusMethodHandler) &wpas_dbus_handler_create_interface, 832 { 833 { "args", "a{sv}", ARG_IN }, 834 { "path", "o", ARG_OUT }, 835 END_ARGS 836 } 837 }, 838 { "RemoveInterface", WPAS_DBUS_NEW_INTERFACE, 839 (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface, 840 { 841 { "path", "o", ARG_IN }, 842 END_ARGS 843 } 844 }, 845 { "GetInterface", WPAS_DBUS_NEW_INTERFACE, 846 (WPADBusMethodHandler) &wpas_dbus_handler_get_interface, 847 { 848 { "ifname", "s", ARG_IN }, 849 { "path", "o", ARG_OUT }, 850 END_ARGS 851 } 852 }, 853 { NULL, NULL, NULL, { END_ARGS } } 854 }; 855 856 static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = { 857 { "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s", 858 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level, 859 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level, 860 RW 861 }, 862 { "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b", 863 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp, 864 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp, 865 RW 866 }, 867 { "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b", 868 (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys, 869 (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys, 870 RW 871 }, 872 { "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao", 873 (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces, 874 NULL, 875 R 876 }, 877 { "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as", 878 (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods, 879 NULL, 880 R 881 }, 882 { NULL, NULL, NULL, NULL, NULL, 0 } 883 }; 884 885 static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = { 886 { "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE, 887 { 888 { "path", "o", ARG_OUT }, 889 { "properties", "a{sv}", ARG_OUT }, 890 END_ARGS 891 } 892 }, 893 { "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE, 894 { 895 { "path", "o", ARG_OUT }, 896 END_ARGS 897 } 898 }, 899 { "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE, 900 { 901 { "properties", "a{sv}", ARG_OUT }, 902 END_ARGS 903 } 904 }, 905 { NULL, NULL, { END_ARGS } } 906 }; 907 908 909 /** 910 * wpas_dbus_ctrl_iface_init - Initialize dbus control interface 911 * @global: Pointer to global data from wpa_supplicant_init() 912 * Returns: 0 on success or -1 on failure 913 * 914 * Initialize the dbus control interface for wpa_supplicantand and start 915 * receiving commands from external programs over the bus. 916 */ 917 int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv) 918 { 919 struct wpa_dbus_object_desc *obj_desc; 920 int ret; 921 922 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 923 if (!obj_desc) { 924 wpa_printf(MSG_ERROR, "Not enough memory " 925 "to create object description"); 926 return -1; 927 } 928 929 wpas_dbus_register(obj_desc, priv->global, NULL, 930 wpas_dbus_global_methods, 931 wpas_dbus_global_properties, 932 wpas_dbus_global_signals); 933 934 wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'", 935 WPAS_DBUS_NEW_PATH); 936 ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH, 937 WPAS_DBUS_NEW_SERVICE, 938 obj_desc); 939 if (ret < 0) 940 free_dbus_object_desc(obj_desc); 941 else 942 priv->dbus_new_initialized = 1; 943 944 return ret; 945 } 946 947 948 /** 949 * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for 950 * wpa_supplicant 951 * @iface: Pointer to dbus private data from wpas_dbus_init() 952 * 953 * Deinitialize the dbus control interface that was initialized with 954 * wpas_dbus_ctrl_iface_init(). 955 */ 956 void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface) 957 { 958 if (!iface->dbus_new_initialized) 959 return; 960 wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'", 961 WPAS_DBUS_NEW_PATH); 962 dbus_connection_unregister_object_path(iface->con, 963 WPAS_DBUS_NEW_PATH); 964 } 965 966 967 static void wpa_dbus_free(void *ptr) 968 { 969 os_free(ptr); 970 } 971 972 973 static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = { 974 { "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}", 975 (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties, 976 (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties, 977 RW 978 }, 979 { "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b", 980 (WPADBusPropertyAccessor) wpas_dbus_getter_enabled, 981 (WPADBusPropertyAccessor) wpas_dbus_setter_enabled, 982 RW 983 }, 984 { NULL, NULL, NULL, NULL, NULL, 0 } 985 }; 986 987 988 static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = { 989 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK, 990 { 991 { "properties", "a{sv}", ARG_OUT }, 992 END_ARGS 993 } 994 }, 995 { NULL, NULL, { END_ARGS } } 996 }; 997 998 999 /** 1000 * wpas_dbus_register_network - Register a configured network with dbus 1001 * @wpa_s: wpa_supplicant interface structure 1002 * @ssid: network configuration data 1003 * Returns: 0 on success, -1 on failure 1004 * 1005 * Registers network representing object with dbus 1006 */ 1007 int wpas_dbus_register_network(struct wpa_supplicant *wpa_s, 1008 struct wpa_ssid *ssid) 1009 { 1010 struct wpas_dbus_priv *ctrl_iface; 1011 struct wpa_dbus_object_desc *obj_desc; 1012 struct network_handler_args *arg; 1013 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 1014 1015 /* Do nothing if the control interface is not turned on */ 1016 if (wpa_s == NULL || wpa_s->global == NULL) 1017 return 0; 1018 ctrl_iface = wpa_s->global->dbus; 1019 if (ctrl_iface == NULL) 1020 return 0; 1021 1022 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1023 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 1024 wpa_s->dbus_new_path, ssid->id); 1025 1026 wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'", 1027 net_obj_path); 1028 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 1029 if (!obj_desc) { 1030 wpa_printf(MSG_ERROR, "Not enough memory " 1031 "to create object description"); 1032 goto err; 1033 } 1034 1035 /* allocate memory for handlers arguments */ 1036 arg = os_zalloc(sizeof(struct network_handler_args)); 1037 if (!arg) { 1038 wpa_printf(MSG_ERROR, "Not enough memory " 1039 "to create arguments for method"); 1040 goto err; 1041 } 1042 1043 arg->wpa_s = wpa_s; 1044 arg->ssid = ssid; 1045 1046 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 1047 wpas_dbus_network_properties, 1048 wpas_dbus_network_signals); 1049 1050 if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path, 1051 wpa_s->ifname, obj_desc)) 1052 goto err; 1053 1054 wpas_dbus_signal_network_added(wpa_s, ssid->id); 1055 1056 return 0; 1057 1058 err: 1059 free_dbus_object_desc(obj_desc); 1060 return -1; 1061 } 1062 1063 1064 /** 1065 * wpas_dbus_unregister_network - Unregister a configured network from dbus 1066 * @wpa_s: wpa_supplicant interface structure 1067 * @nid: network id 1068 * Returns: 0 on success, -1 on failure 1069 * 1070 * Unregisters network representing object from dbus 1071 */ 1072 int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid) 1073 { 1074 struct wpas_dbus_priv *ctrl_iface; 1075 char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 1076 int ret; 1077 1078 /* Do nothing if the control interface is not turned on */ 1079 if (wpa_s == NULL || wpa_s->global == NULL || 1080 wpa_s->dbus_new_path == NULL) 1081 return 0; 1082 ctrl_iface = wpa_s->global->dbus; 1083 if (ctrl_iface == NULL) 1084 return 0; 1085 1086 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1087 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 1088 wpa_s->dbus_new_path, nid); 1089 1090 wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'", 1091 net_obj_path); 1092 ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path); 1093 1094 if (!ret) 1095 wpas_dbus_signal_network_removed(wpa_s, nid); 1096 1097 return ret; 1098 } 1099 1100 1101 static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = { 1102 { "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 1103 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid, 1104 NULL, 1105 R 1106 }, 1107 { "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay", 1108 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid, 1109 NULL, 1110 R 1111 }, 1112 { "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b", 1113 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy, 1114 NULL, 1115 R 1116 }, 1117 { "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s", 1118 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode, 1119 NULL, 1120 R 1121 }, 1122 { "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n", 1123 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal, 1124 NULL, 1125 R 1126 }, 1127 { "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q", 1128 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency, 1129 NULL, 1130 R 1131 }, 1132 { "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au", 1133 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates, 1134 NULL, 1135 R 1136 }, 1137 { "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 1138 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpa, 1139 NULL, 1140 R 1141 }, 1142 { "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}", 1143 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsn, 1144 NULL, 1145 R 1146 }, 1147 { "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay", 1148 (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ies, 1149 NULL, 1150 R 1151 }, 1152 { NULL, NULL, NULL, NULL, NULL, 0 } 1153 }; 1154 1155 1156 static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = { 1157 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS, 1158 { 1159 { "properties", "a{sv}", ARG_OUT }, 1160 END_ARGS 1161 } 1162 }, 1163 { NULL, NULL, { END_ARGS } } 1164 }; 1165 1166 1167 /** 1168 * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus 1169 * @wpa_s: wpa_supplicant interface structure 1170 * @bssid: scanned network bssid 1171 * @id: unique BSS identifier 1172 * Returns: 0 on success, -1 on failure 1173 * 1174 * Unregisters BSS representing object from dbus 1175 */ 1176 int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s, 1177 u8 bssid[ETH_ALEN], unsigned int id) 1178 { 1179 struct wpas_dbus_priv *ctrl_iface; 1180 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 1181 1182 /* Do nothing if the control interface is not turned on */ 1183 if (wpa_s == NULL || wpa_s->global == NULL) 1184 return 0; 1185 ctrl_iface = wpa_s->global->dbus; 1186 if (ctrl_iface == NULL) 1187 return 0; 1188 1189 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1190 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 1191 wpa_s->dbus_new_path, id); 1192 1193 wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'", 1194 bss_obj_path); 1195 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) { 1196 wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s", 1197 bss_obj_path); 1198 return -1; 1199 } 1200 1201 wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path); 1202 1203 return 0; 1204 } 1205 1206 1207 /** 1208 * wpas_dbus_register_bss - Register a scanned BSS with dbus 1209 * @wpa_s: wpa_supplicant interface structure 1210 * @bssid: scanned network bssid 1211 * @id: unique BSS identifier 1212 * Returns: 0 on success, -1 on failure 1213 * 1214 * Registers BSS representing object with dbus 1215 */ 1216 int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, 1217 u8 bssid[ETH_ALEN], unsigned int id) 1218 { 1219 struct wpas_dbus_priv *ctrl_iface; 1220 struct wpa_dbus_object_desc *obj_desc; 1221 char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 1222 struct bss_handler_args *arg; 1223 1224 /* Do nothing if the control interface is not turned on */ 1225 if (wpa_s == NULL || wpa_s->global == NULL) 1226 return 0; 1227 ctrl_iface = wpa_s->global->dbus; 1228 if (ctrl_iface == NULL) 1229 return 0; 1230 1231 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 1232 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 1233 wpa_s->dbus_new_path, id); 1234 1235 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 1236 if (!obj_desc) { 1237 wpa_printf(MSG_ERROR, "Not enough memory " 1238 "to create object description"); 1239 goto err; 1240 } 1241 1242 arg = os_zalloc(sizeof(struct bss_handler_args)); 1243 if (!arg) { 1244 wpa_printf(MSG_ERROR, "Not enough memory " 1245 "to create arguments for handler"); 1246 goto err; 1247 } 1248 arg->wpa_s = wpa_s; 1249 arg->id = id; 1250 1251 wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL, 1252 wpas_dbus_bss_properties, 1253 wpas_dbus_bss_signals); 1254 1255 wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'", 1256 bss_obj_path); 1257 if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path, 1258 wpa_s->ifname, obj_desc)) { 1259 wpa_printf(MSG_ERROR, 1260 "Cannot register BSSID dbus object %s.", 1261 bss_obj_path); 1262 goto err; 1263 } 1264 1265 wpas_dbus_signal_bss_added(wpa_s, bss_obj_path); 1266 1267 return 0; 1268 1269 err: 1270 free_dbus_object_desc(obj_desc); 1271 return -1; 1272 } 1273 1274 1275 static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { 1276 { "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE, 1277 (WPADBusMethodHandler) &wpas_dbus_handler_scan, 1278 { 1279 { "args", "a{sv}", ARG_IN }, 1280 END_ARGS 1281 } 1282 }, 1283 { "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE, 1284 (WPADBusMethodHandler) &wpas_dbus_handler_disconnect, 1285 { 1286 END_ARGS 1287 } 1288 }, 1289 { "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 1290 (WPADBusMethodHandler) &wpas_dbus_handler_add_network, 1291 { 1292 { "args", "a{sv}", ARG_IN }, 1293 { "path", "o", ARG_OUT }, 1294 END_ARGS 1295 } 1296 }, 1297 { "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 1298 (WPADBusMethodHandler) &wpas_dbus_handler_remove_network, 1299 { 1300 { "path", "o", ARG_IN }, 1301 END_ARGS 1302 } 1303 }, 1304 { "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, 1305 (WPADBusMethodHandler) &wpas_dbus_handler_select_network, 1306 { 1307 { "path", "o", ARG_IN }, 1308 END_ARGS 1309 } 1310 }, 1311 { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 1312 (WPADBusMethodHandler) &wpas_dbus_handler_add_blob, 1313 { 1314 { "name", "s", ARG_IN }, 1315 { "data", "ay", ARG_IN }, 1316 END_ARGS 1317 } 1318 }, 1319 { "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 1320 (WPADBusMethodHandler) &wpas_dbus_handler_get_blob, 1321 { 1322 { "name", "s", ARG_IN }, 1323 { "data", "ay", ARG_OUT }, 1324 END_ARGS 1325 } 1326 }, 1327 { "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, 1328 (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob, 1329 { 1330 { "name", "s", ARG_IN }, 1331 END_ARGS 1332 } 1333 }, 1334 #ifdef CONFIG_WPS 1335 { "Start", WPAS_DBUS_NEW_IFACE_WPS, 1336 (WPADBusMethodHandler) &wpas_dbus_handler_wps_start, 1337 { 1338 { "args", "a{sv}", ARG_IN }, 1339 { "output", "a{sv}", ARG_OUT }, 1340 END_ARGS 1341 } 1342 }, 1343 #endif /* CONFIG_WPS */ 1344 { NULL, NULL, NULL, { END_ARGS } } 1345 }; 1346 1347 static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { 1348 { "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}", 1349 (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities, 1350 NULL, R 1351 }, 1352 { "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 1353 (WPADBusPropertyAccessor) wpas_dbus_getter_state, 1354 NULL, R 1355 }, 1356 { "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b", 1357 (WPADBusPropertyAccessor) wpas_dbus_getter_scanning, 1358 NULL, R 1359 }, 1360 { "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u", 1361 (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan, 1362 (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan, 1363 RW 1364 }, 1365 { "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 1366 (WPADBusPropertyAccessor) wpas_dbus_getter_ifname, 1367 NULL, R 1368 }, 1369 { "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 1370 (WPADBusPropertyAccessor) wpas_dbus_getter_driver, 1371 NULL, R 1372 }, 1373 { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", 1374 (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname, 1375 NULL, R 1376 }, 1377 { "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 1378 (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss, 1379 NULL, R 1380 }, 1381 { "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o", 1382 (WPADBusPropertyAccessor) wpas_dbus_getter_current_network, 1383 NULL, R 1384 }, 1385 { "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}", 1386 (WPADBusPropertyAccessor) wpas_dbus_getter_blobs, 1387 NULL, R 1388 }, 1389 { "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 1390 (WPADBusPropertyAccessor) wpas_dbus_getter_bsss, 1391 NULL, R 1392 }, 1393 { "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao", 1394 (WPADBusPropertyAccessor) wpas_dbus_getter_networks, 1395 NULL, R 1396 }, 1397 #ifdef CONFIG_WPS 1398 { "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b", 1399 (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials, 1400 (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials, 1401 RW 1402 }, 1403 #endif /* CONFIG_WPS */ 1404 { NULL, NULL, NULL, NULL, NULL, 0 } 1405 }; 1406 1407 static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { 1408 { "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE, 1409 { 1410 { "success", "b", ARG_OUT }, 1411 END_ARGS 1412 } 1413 }, 1414 { "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 1415 { 1416 { "path", "o", ARG_OUT }, 1417 { "properties", "a{sv}", ARG_OUT }, 1418 END_ARGS 1419 } 1420 }, 1421 { "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 1422 { 1423 { "path", "o", ARG_OUT }, 1424 END_ARGS 1425 } 1426 }, 1427 { "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 1428 { 1429 { "name", "s", ARG_OUT }, 1430 END_ARGS 1431 } 1432 }, 1433 { "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 1434 { 1435 { "name", "s", ARG_OUT }, 1436 END_ARGS 1437 } 1438 }, 1439 { "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, 1440 { 1441 { "path", "o", ARG_OUT }, 1442 { "properties", "a{sv}", ARG_OUT }, 1443 END_ARGS 1444 } 1445 }, 1446 { "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE, 1447 { 1448 { "path", "o", ARG_OUT }, 1449 END_ARGS 1450 } 1451 }, 1452 { "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE, 1453 { 1454 { "path", "o", ARG_OUT }, 1455 END_ARGS 1456 } 1457 }, 1458 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE, 1459 { 1460 { "properties", "a{sv}", ARG_OUT }, 1461 END_ARGS 1462 } 1463 }, 1464 #ifdef CONFIG_WPS 1465 { "Event", WPAS_DBUS_NEW_IFACE_WPS, 1466 { 1467 { "name", "s", ARG_OUT }, 1468 { "args", "a{sv}", ARG_OUT }, 1469 END_ARGS 1470 } 1471 }, 1472 { "Credentials", WPAS_DBUS_NEW_IFACE_WPS, 1473 { 1474 { "credentials", "a{sv}", ARG_OUT }, 1475 END_ARGS 1476 } 1477 }, 1478 { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS, 1479 { 1480 { "properties", "a{sv}", ARG_OUT }, 1481 END_ARGS 1482 } 1483 }, 1484 #endif /* CONFIG_WPS */ 1485 { NULL, NULL, { END_ARGS } } 1486 }; 1487 1488 1489 int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s) 1490 { 1491 1492 struct wpa_dbus_object_desc *obj_desc = NULL; 1493 struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus; 1494 int next; 1495 1496 /* Do nothing if the control interface is not turned on */ 1497 if (ctrl_iface == NULL) 1498 return 0; 1499 1500 /* Create and set the interface's object path */ 1501 wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 1502 if (wpa_s->dbus_new_path == NULL) 1503 return -1; 1504 next = ctrl_iface->next_objid++; 1505 os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX, 1506 WPAS_DBUS_NEW_PATH_INTERFACES "/%u", 1507 next); 1508 1509 obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc)); 1510 if (!obj_desc) { 1511 wpa_printf(MSG_ERROR, "Not enough memory " 1512 "to create object description"); 1513 goto err; 1514 } 1515 1516 wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods, 1517 wpas_dbus_interface_properties, 1518 wpas_dbus_interface_signals); 1519 1520 wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'", 1521 wpa_s->dbus_new_path); 1522 if (wpa_dbus_register_object_per_iface(ctrl_iface, 1523 wpa_s->dbus_new_path, 1524 wpa_s->ifname, obj_desc)) 1525 goto err; 1526 1527 wpas_dbus_signal_interface_added(wpa_s); 1528 1529 return 0; 1530 1531 err: 1532 os_free(wpa_s->dbus_new_path); 1533 wpa_s->dbus_new_path = NULL; 1534 free_dbus_object_desc(obj_desc); 1535 return -1; 1536 } 1537 1538 1539 int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s) 1540 { 1541 struct wpas_dbus_priv *ctrl_iface; 1542 1543 /* Do nothing if the control interface is not turned on */ 1544 if (wpa_s == NULL || wpa_s->global == NULL) 1545 return 0; 1546 ctrl_iface = wpa_s->global->dbus; 1547 if (ctrl_iface == NULL) 1548 return 0; 1549 1550 wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'", 1551 wpa_s->dbus_new_path); 1552 if (wpa_dbus_unregister_object_per_iface(ctrl_iface, 1553 wpa_s->dbus_new_path)) 1554 return -1; 1555 1556 wpas_dbus_signal_interface_removed(wpa_s); 1557 1558 os_free(wpa_s->dbus_new_path); 1559 wpa_s->dbus_new_path = NULL; 1560 1561 return 0; 1562 } 1563