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-2015, Jouni Malinen <j@w1.fi> 6 * 7 * This software may be distributed under the terms of the BSD license. 8 * See README for more details. 9 */ 10 11 #include "includes.h" 12 13 #include "common.h" 14 #include "common/ieee802_11_defs.h" 15 #include "eap_peer/eap_methods.h" 16 #include "eapol_supp/eapol_supp_sm.h" 17 #include "rsn_supp/wpa.h" 18 #include "ap/hostapd.h" 19 #include "ap/sta_info.h" 20 #include "ap/ap_drv_ops.h" 21 #include "../config.h" 22 #include "../wpa_supplicant_i.h" 23 #include "../driver_i.h" 24 #include "../notify.h" 25 #include "../bss.h" 26 #include "../scan.h" 27 #include "../autoscan.h" 28 #include "../ap.h" 29 #include "../interworking.h" 30 #include "dbus_new_helpers.h" 31 #include "dbus_new.h" 32 #include "dbus_new_handlers.h" 33 #include "dbus_dict_helpers.h" 34 #include "dbus_common_i.h" 35 #include "drivers/driver.h" 36 #ifdef CONFIG_MESH 37 #include "ap/hostapd.h" 38 #include "ap/sta_info.h" 39 #endif /* CONFIG_MESH */ 40 41 static const char * const debug_strings[] = { 42 "excessive", "msgdump", "debug", "info", "warning", "error", NULL 43 }; 44 45 46 /** 47 * wpas_dbus_error_unknown_error - Return a new UnknownError error message 48 * @message: Pointer to incoming dbus message this error refers to 49 * @arg: Optional string appended to error message 50 * Returns: a dbus error message 51 * 52 * Convenience function to create and return an UnknownError 53 */ 54 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message, 55 const char *arg) 56 { 57 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR, 58 arg); 59 } 60 61 62 /** 63 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message 64 * @message: Pointer to incoming dbus message this error refers to 65 * Returns: A dbus error message 66 * 67 * Convenience function to create and return an invalid interface error 68 */ 69 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message) 70 { 71 return dbus_message_new_error( 72 message, WPAS_DBUS_ERROR_IFACE_UNKNOWN, 73 "wpa_supplicant knows nothing about this interface."); 74 } 75 76 77 /** 78 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message 79 * @message: Pointer to incoming dbus message this error refers to 80 * Returns: a dbus error message 81 * 82 * Convenience function to create and return an invalid network error 83 */ 84 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message) 85 { 86 return dbus_message_new_error( 87 message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN, 88 "There is no such a network in this interface."); 89 } 90 91 92 /** 93 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message 94 * @message: Pointer to incoming dbus message this error refers to 95 * Returns: a dbus error message 96 * 97 * Convenience function to create and return an invalid options error 98 */ 99 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message, 100 const char *arg) 101 { 102 DBusMessage *reply; 103 104 reply = dbus_message_new_error( 105 message, WPAS_DBUS_ERROR_INVALID_ARGS, 106 "Did not receive correct message arguments."); 107 if (arg != NULL) 108 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg, 109 DBUS_TYPE_INVALID); 110 111 return reply; 112 } 113 114 115 /** 116 * wpas_dbus_error_scan_error - Return a new ScanError error message 117 * @message: Pointer to incoming dbus message this error refers to 118 * @error: Optional string to be used as the error message 119 * Returns: a dbus error message 120 * 121 * Convenience function to create and return a scan error 122 */ 123 static DBusMessage * wpas_dbus_error_scan_error(DBusMessage *message, 124 const char *error) 125 { 126 return dbus_message_new_error(message, 127 WPAS_DBUS_ERROR_IFACE_SCAN_ERROR, 128 error); 129 } 130 131 132 DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message) 133 { 134 wpa_printf(MSG_DEBUG, "dbus: Failed to allocate memory"); 135 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL); 136 } 137 138 139 static const char * const dont_quote[] = { 140 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", 141 "bssid", "scan_freq", "freq_list", "scan_ssid", "bssid_hint", 142 "bssid_ignore", "bssid_accept", /* deprecated aliases */ 143 "bssid_blacklist", "bssid_whitelist", 144 "group_mgmt", 145 "ignore_broadcast_ssid", 146 #ifdef CONFIG_MESH 147 "mesh_basic_rates", 148 #endif /* CONFIG_MESH */ 149 #ifdef CONFIG_P2P 150 "go_p2p_dev_addr", "p2p_client_list", "psk_list", 151 #endif /* CONFIG_P2P */ 152 #ifdef CONFIG_INTERWORKING 153 "roaming_consortium", "required_roaming_consortium", 154 #endif /* CONFIG_INTERWORKING */ 155 NULL 156 }; 157 158 static dbus_bool_t should_quote_opt(const char *key) 159 { 160 int i = 0; 161 162 while (dont_quote[i] != NULL) { 163 if (os_strcmp(key, dont_quote[i]) == 0) 164 return FALSE; 165 i++; 166 } 167 return TRUE; 168 } 169 170 /** 171 * get_iface_by_dbus_path - Get a new network interface 172 * @global: Pointer to global data from wpa_supplicant_init() 173 * @path: Pointer to a dbus object path representing an interface 174 * Returns: Pointer to the interface or %NULL if not found 175 */ 176 static struct wpa_supplicant * get_iface_by_dbus_path( 177 struct wpa_global *global, const char *path) 178 { 179 struct wpa_supplicant *wpa_s; 180 181 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 182 if (wpa_s->dbus_new_path && 183 os_strcmp(wpa_s->dbus_new_path, path) == 0) 184 return wpa_s; 185 } 186 return NULL; 187 } 188 189 190 /** 191 * set_network_properties - Set properties of a configured network 192 * @wpa_s: wpa_supplicant structure for a network interface 193 * @ssid: wpa_ssid structure for a configured network 194 * @iter: DBus message iterator containing dictionary of network 195 * properties to set. 196 * @error: On failure, an error describing the failure 197 * Returns: TRUE if the request succeeds, FALSE if it failed 198 * 199 * Sets network configuration with parameters given id DBus dictionary 200 */ 201 dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, 202 struct wpa_ssid *ssid, 203 DBusMessageIter *iter, 204 DBusError *error) 205 { 206 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 207 DBusMessageIter iter_dict; 208 char *value = NULL; 209 210 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error)) 211 return FALSE; 212 213 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 214 size_t size = 50; 215 int ret; 216 217 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 218 goto error; 219 220 value = NULL; 221 if (entry.type == DBUS_TYPE_ARRAY && 222 entry.array_type == DBUS_TYPE_BYTE) { 223 if (entry.array_len <= 0) 224 goto error; 225 226 size = entry.array_len * 2 + 1; 227 value = os_zalloc(size); 228 if (value == NULL) 229 goto error; 230 231 ret = wpa_snprintf_hex(value, size, 232 (u8 *) entry.bytearray_value, 233 entry.array_len); 234 if (ret <= 0) 235 goto error; 236 } else if (entry.type == DBUS_TYPE_STRING) { 237 if (should_quote_opt(entry.key)) { 238 size = os_strlen(entry.str_value); 239 240 size += 3; 241 value = os_zalloc(size); 242 if (value == NULL) 243 goto error; 244 245 ret = os_snprintf(value, size, "\"%s\"", 246 entry.str_value); 247 if (os_snprintf_error(size, ret)) 248 goto error; 249 } else { 250 value = os_strdup(entry.str_value); 251 if (value == NULL) 252 goto error; 253 } 254 } else if (entry.type == DBUS_TYPE_UINT32) { 255 value = os_zalloc(size); 256 if (value == NULL) 257 goto error; 258 259 ret = os_snprintf(value, size, "%u", 260 entry.uint32_value); 261 if (os_snprintf_error(size, ret)) 262 goto error; 263 } else if (entry.type == DBUS_TYPE_INT32) { 264 value = os_zalloc(size); 265 if (value == NULL) 266 goto error; 267 268 ret = os_snprintf(value, size, "%d", 269 entry.int32_value); 270 if (os_snprintf_error(size, ret)) 271 goto error; 272 } else 273 goto error; 274 275 ret = wpa_config_set(ssid, entry.key, value, 0); 276 if (ret < 0) 277 goto error; 278 if (ret == 1) 279 goto skip_update; 280 281 #ifdef CONFIG_BGSCAN 282 if (os_strcmp(entry.key, "bgscan") == 0) { 283 /* 284 * Reset the bgscan parameters for the current network 285 * and continue. There's no need to flush caches for 286 * bgscan parameter changes. 287 */ 288 if (wpa_s->current_ssid == ssid && 289 wpa_s->wpa_state == WPA_COMPLETED) 290 wpa_supplicant_reset_bgscan(wpa_s); 291 os_free(value); 292 value = NULL; 293 wpa_dbus_dict_entry_clear(&entry); 294 continue; 295 } 296 #endif /* CONFIG_BGSCAN */ 297 298 if (os_strcmp(entry.key, "bssid") != 0 && 299 os_strcmp(entry.key, "priority") != 0) 300 wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); 301 302 if (wpa_s->current_ssid == ssid || 303 wpa_s->current_ssid == NULL) { 304 /* 305 * Invalidate the EAP session cache if anything in the 306 * current or previously used configuration changes. 307 */ 308 eapol_sm_invalidate_cached_session(wpa_s->eapol); 309 } 310 311 if ((os_strcmp(entry.key, "psk") == 0 && 312 value[0] == '"' && ssid->ssid_len) || 313 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase)) 314 wpa_config_update_psk(ssid); 315 else if (os_strcmp(entry.key, "priority") == 0) 316 wpa_config_update_prio_list(wpa_s->conf); 317 318 skip_update: 319 os_free(value); 320 value = NULL; 321 wpa_dbus_dict_entry_clear(&entry); 322 } 323 324 return TRUE; 325 326 error: 327 os_free(value); 328 wpa_dbus_dict_entry_clear(&entry); 329 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 330 "invalid message format"); 331 return FALSE; 332 } 333 334 335 /** 336 * set_cred_properties - Set the properties of a configured credential 337 * @wpa_s: wpa_supplicant structure for a network interface 338 * @cred: wpa_cred structure for a configured credential 339 * @iter: DBus message iterator containing dictionary of network 340 * properties to set. 341 * @error: On failure, an error describing the failure 342 * Returns: TRUE if the request succeeds, FALSE if it failed 343 */ 344 static dbus_bool_t set_cred_properties(struct wpa_supplicant *wpa_s, 345 struct wpa_cred *cred, 346 DBusMessageIter *iter, 347 DBusError *error) 348 { 349 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 350 DBusMessageIter iter_dict; 351 char *value = NULL; 352 353 if (!wpa_dbus_dict_open_read(iter, &iter_dict, error)) 354 return FALSE; 355 356 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 357 size_t size = 50; 358 int ret; 359 360 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 361 goto error; 362 363 value = NULL; 364 if (entry.type == DBUS_TYPE_ARRAY && 365 entry.array_type == DBUS_TYPE_BYTE) { 366 if (entry.array_len <= 0) 367 goto error; 368 369 size = entry.array_len * 2 + 1; 370 value = os_zalloc(size); 371 if (!value) 372 goto error; 373 374 ret = wpa_snprintf_hex(value, size, 375 (u8 *) entry.bytearray_value, 376 entry.array_len); 377 if (ret <= 0) 378 goto error; 379 } else if (entry.type == DBUS_TYPE_STRING) { 380 if (should_quote_opt(entry.key)) { 381 size = os_strlen(entry.str_value); 382 383 size += 3; 384 value = os_zalloc(size); 385 if (!value) 386 goto error; 387 388 ret = os_snprintf(value, size, "\"%s\"", 389 entry.str_value); 390 if (os_snprintf_error(size, ret)) 391 goto error; 392 } else { 393 value = os_strdup(entry.str_value); 394 if (!value) 395 goto error; 396 } 397 } else if (entry.type == DBUS_TYPE_UINT32) { 398 value = os_zalloc(size); 399 if (!value) 400 goto error; 401 402 ret = os_snprintf(value, size, "%u", 403 entry.uint32_value); 404 if (os_snprintf_error(size, ret)) 405 goto error; 406 } else if (entry.type == DBUS_TYPE_INT32) { 407 value = os_zalloc(size); 408 if (!value) 409 goto error; 410 411 ret = os_snprintf(value, size, "%d", 412 entry.int32_value); 413 if (os_snprintf_error(size, ret)) 414 goto error; 415 } else { 416 goto error; 417 } 418 419 ret = wpa_config_set_cred(cred, entry.key, value, 0); 420 if (ret < 0) 421 goto error; 422 423 os_free(value); 424 value = NULL; 425 wpa_dbus_dict_entry_clear(&entry); 426 } 427 428 return TRUE; 429 430 error: 431 os_free(value); 432 wpa_dbus_dict_entry_clear(&entry); 433 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 434 "invalid message format"); 435 return FALSE; 436 } 437 438 439 /** 440 * wpas_dbus_simple_property_getter - Get basic type property 441 * @iter: Message iter to use when appending arguments 442 * @type: DBus type of property (must be basic type) 443 * @val: pointer to place holding property value 444 * @error: On failure an error describing the failure 445 * Returns: TRUE if the request was successful, FALSE if it failed 446 * 447 * Generic getter for basic type properties. Type is required to be basic. 448 */ 449 dbus_bool_t wpas_dbus_simple_property_getter(DBusMessageIter *iter, 450 const int type, 451 const void *val, 452 DBusError *error) 453 { 454 DBusMessageIter variant_iter; 455 456 if (!dbus_type_is_basic(type)) { 457 dbus_set_error(error, DBUS_ERROR_FAILED, 458 "%s: given type is not basic", __func__); 459 return FALSE; 460 } 461 462 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 463 wpa_dbus_type_as_string(type), 464 &variant_iter) || 465 !dbus_message_iter_append_basic(&variant_iter, type, val) || 466 !dbus_message_iter_close_container(iter, &variant_iter)) { 467 dbus_set_error(error, DBUS_ERROR_FAILED, 468 "%s: error constructing reply", __func__); 469 return FALSE; 470 } 471 472 return TRUE; 473 } 474 475 476 /** 477 * wpas_dbus_simple_property_setter - Set basic type property 478 * @message: Pointer to incoming dbus message 479 * @type: DBus type of property (must be basic type) 480 * @val: pointer to place where value being set will be stored 481 * Returns: TRUE if the request was successful, FALSE if it failed 482 * 483 * Generic setter for basic type properties. Type is required to be basic. 484 */ 485 dbus_bool_t wpas_dbus_simple_property_setter(DBusMessageIter *iter, 486 DBusError *error, 487 const int type, void *val) 488 { 489 DBusMessageIter variant_iter; 490 491 if (!dbus_type_is_basic(type)) { 492 dbus_set_error(error, DBUS_ERROR_FAILED, 493 "%s: given type is not basic", __func__); 494 return FALSE; 495 } 496 497 /* Look at the new value */ 498 dbus_message_iter_recurse(iter, &variant_iter); 499 if (dbus_message_iter_get_arg_type(&variant_iter) != type) { 500 dbus_set_error_const(error, DBUS_ERROR_FAILED, 501 "wrong property type"); 502 return FALSE; 503 } 504 dbus_message_iter_get_basic(&variant_iter, val); 505 506 return TRUE; 507 } 508 509 510 /** 511 * wpas_dbus_simple_array_property_getter - Get array type property 512 * @iter: Pointer to incoming dbus message iterator 513 * @type: DBus type of property array elements (must be basic type) 514 * @array: pointer to array of elements to put into response message 515 * @array_len: length of above array 516 * @error: a pointer to an error to fill on failure 517 * Returns: TRUE if the request succeeded, FALSE if it failed 518 * 519 * Generic getter for array type properties. Array elements type is 520 * required to be basic. 521 */ 522 dbus_bool_t wpas_dbus_simple_array_property_getter(DBusMessageIter *iter, 523 const int type, 524 const void *array, 525 size_t array_len, 526 DBusError *error) 527 { 528 DBusMessageIter variant_iter, array_iter; 529 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */ 530 const char *sub_type_str; 531 size_t element_size, i; 532 533 if (!dbus_type_is_basic(type)) { 534 dbus_set_error(error, DBUS_ERROR_FAILED, 535 "%s: given type is not basic", __func__); 536 return FALSE; 537 } 538 539 sub_type_str = wpa_dbus_type_as_string(type); 540 type_str[1] = sub_type_str[0]; 541 542 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 543 type_str, &variant_iter) || 544 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 545 sub_type_str, &array_iter)) { 546 dbus_set_error(error, DBUS_ERROR_FAILED, 547 "%s: failed to construct message", __func__); 548 return FALSE; 549 } 550 551 switch (type) { 552 case DBUS_TYPE_BYTE: 553 case DBUS_TYPE_BOOLEAN: 554 element_size = 1; 555 break; 556 case DBUS_TYPE_INT16: 557 case DBUS_TYPE_UINT16: 558 element_size = sizeof(uint16_t); 559 break; 560 case DBUS_TYPE_INT32: 561 case DBUS_TYPE_UINT32: 562 element_size = sizeof(uint32_t); 563 break; 564 case DBUS_TYPE_INT64: 565 case DBUS_TYPE_UINT64: 566 element_size = sizeof(uint64_t); 567 break; 568 case DBUS_TYPE_DOUBLE: 569 element_size = sizeof(double); 570 break; 571 case DBUS_TYPE_STRING: 572 case DBUS_TYPE_OBJECT_PATH: 573 element_size = sizeof(char *); 574 break; 575 default: 576 dbus_set_error(error, DBUS_ERROR_FAILED, 577 "%s: unknown element type %d", __func__, type); 578 return FALSE; 579 } 580 581 for (i = 0; i < array_len; i++) { 582 if (!dbus_message_iter_append_basic(&array_iter, type, 583 (const char *) array + 584 i * element_size)) { 585 dbus_set_error(error, DBUS_ERROR_FAILED, 586 "%s: failed to construct message 2.5", 587 __func__); 588 return FALSE; 589 } 590 } 591 592 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) || 593 !dbus_message_iter_close_container(iter, &variant_iter)) { 594 dbus_set_error(error, DBUS_ERROR_FAILED, 595 "%s: failed to construct message 3", __func__); 596 return FALSE; 597 } 598 599 return TRUE; 600 } 601 602 603 /** 604 * wpas_dbus_simple_array_array_property_getter - Get array array type property 605 * @iter: Pointer to incoming dbus message iterator 606 * @type: DBus type of property array elements (must be basic type) 607 * @array: pointer to array of elements to put into response message 608 * @array_len: length of above array 609 * @error: a pointer to an error to fill on failure 610 * Returns: TRUE if the request succeeded, FALSE if it failed 611 * 612 * Generic getter for array type properties. Array elements type is 613 * required to be basic. 614 */ 615 dbus_bool_t wpas_dbus_simple_array_array_property_getter(DBusMessageIter *iter, 616 const int type, 617 struct wpabuf **array, 618 size_t array_len, 619 DBusError *error) 620 { 621 DBusMessageIter variant_iter, array_iter; 622 char type_str[] = "aa?"; 623 char inner_type_str[] = "a?"; 624 const char *sub_type_str; 625 size_t i; 626 627 if (!dbus_type_is_basic(type)) { 628 dbus_set_error(error, DBUS_ERROR_FAILED, 629 "%s: given type is not basic", __func__); 630 return FALSE; 631 } 632 633 sub_type_str = wpa_dbus_type_as_string(type); 634 type_str[2] = sub_type_str[0]; 635 inner_type_str[1] = sub_type_str[0]; 636 637 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 638 type_str, &variant_iter) || 639 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 640 inner_type_str, &array_iter)) { 641 dbus_set_error(error, DBUS_ERROR_FAILED, 642 "%s: failed to construct message", __func__); 643 return FALSE; 644 } 645 646 for (i = 0; i < array_len && array[i]; i++) { 647 wpa_dbus_dict_bin_array_add_element(&array_iter, 648 wpabuf_head(array[i]), 649 wpabuf_len(array[i])); 650 651 } 652 653 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) || 654 !dbus_message_iter_close_container(iter, &variant_iter)) { 655 dbus_set_error(error, DBUS_ERROR_FAILED, 656 "%s: failed to close message", __func__); 657 return FALSE; 658 } 659 660 return TRUE; 661 } 662 663 664 /** 665 * wpas_dbus_string_property_getter - Get string type property 666 * @iter: Message iter to use when appending arguments 667 * @val: Pointer to place holding property value, can be %NULL 668 * @error: On failure an error describing the failure 669 * Returns: TRUE if the request was successful, FALSE if it failed 670 * 671 * Generic getter for string type properties. %NULL is converted to an empty 672 * string. 673 */ 674 dbus_bool_t wpas_dbus_string_property_getter(DBusMessageIter *iter, 675 const void *val, 676 DBusError *error) 677 { 678 if (!val) 679 val = ""; 680 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 681 &val, error); 682 } 683 684 685 /** 686 * wpas_dbus_handler_create_interface - Request registration of a network iface 687 * @message: Pointer to incoming dbus message 688 * @global: %wpa_supplicant global data structure 689 * Returns: The object path of the new interface object, 690 * or a dbus error message with more information 691 * 692 * Handler function for "CreateInterface" method call. Handles requests 693 * by dbus clients to register a network interface that wpa_supplicant 694 * will manage. 695 */ 696 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, 697 struct wpa_global *global) 698 { 699 DBusMessageIter iter_dict; 700 DBusMessage *reply = NULL; 701 DBusMessageIter iter; 702 struct wpa_dbus_dict_entry entry; 703 char *driver = NULL; 704 char *ifname = NULL; 705 char *confname = NULL; 706 char *bridge_ifname = NULL; 707 708 dbus_message_iter_init(message, &iter); 709 710 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 711 goto error; 712 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 713 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 714 goto error; 715 if (os_strcmp(entry.key, "Driver") == 0 && 716 entry.type == DBUS_TYPE_STRING) { 717 os_free(driver); 718 driver = os_strdup(entry.str_value); 719 wpa_dbus_dict_entry_clear(&entry); 720 if (driver == NULL) 721 goto oom; 722 } else if (os_strcmp(entry.key, "Ifname") == 0 && 723 entry.type == DBUS_TYPE_STRING) { 724 os_free(ifname); 725 ifname = os_strdup(entry.str_value); 726 wpa_dbus_dict_entry_clear(&entry); 727 if (ifname == NULL) 728 goto oom; 729 } else if (os_strcmp(entry.key, "ConfigFile") == 0 && 730 entry.type == DBUS_TYPE_STRING) { 731 os_free(confname); 732 confname = os_strdup(entry.str_value); 733 wpa_dbus_dict_entry_clear(&entry); 734 if (confname == NULL) 735 goto oom; 736 } else if (os_strcmp(entry.key, "BridgeIfname") == 0 && 737 entry.type == DBUS_TYPE_STRING) { 738 os_free(bridge_ifname); 739 bridge_ifname = os_strdup(entry.str_value); 740 wpa_dbus_dict_entry_clear(&entry); 741 if (bridge_ifname == NULL) 742 goto oom; 743 } else { 744 wpa_dbus_dict_entry_clear(&entry); 745 goto error; 746 } 747 } 748 749 if (ifname == NULL) 750 goto error; /* Required Ifname argument missing */ 751 752 /* 753 * Try to get the wpa_supplicant record for this iface, return 754 * an error if we already control it. 755 */ 756 if (wpa_supplicant_get_iface(global, ifname) != NULL) { 757 reply = dbus_message_new_error( 758 message, WPAS_DBUS_ERROR_IFACE_EXISTS, 759 "wpa_supplicant already controls this interface."); 760 } else { 761 struct wpa_supplicant *wpa_s; 762 struct wpa_interface iface; 763 764 os_memset(&iface, 0, sizeof(iface)); 765 iface.driver = driver; 766 iface.ifname = ifname; 767 iface.confname = confname; 768 iface.bridge_ifname = bridge_ifname; 769 /* Otherwise, have wpa_supplicant attach to it. */ 770 wpa_s = wpa_supplicant_add_iface(global, &iface, NULL); 771 if (wpa_s && wpa_s->dbus_new_path) { 772 const char *path = wpa_s->dbus_new_path; 773 774 reply = dbus_message_new_method_return(message); 775 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 776 &path, DBUS_TYPE_INVALID); 777 } else { 778 reply = wpas_dbus_error_unknown_error( 779 message, 780 "wpa_supplicant couldn't grab this interface."); 781 } 782 } 783 784 out: 785 os_free(driver); 786 os_free(ifname); 787 os_free(confname); 788 os_free(bridge_ifname); 789 return reply; 790 791 error: 792 reply = wpas_dbus_error_invalid_args(message, NULL); 793 goto out; 794 oom: 795 reply = wpas_dbus_error_no_memory(message); 796 goto out; 797 } 798 799 800 /** 801 * wpas_dbus_handler_remove_interface - Request deregistration of an interface 802 * @message: Pointer to incoming dbus message 803 * @global: wpa_supplicant global data structure 804 * Returns: a dbus message containing a UINT32 indicating success (1) or 805 * failure (0), or returns a dbus error message with more information 806 * 807 * Handler function for "removeInterface" method call. Handles requests 808 * by dbus clients to deregister a network interface that wpa_supplicant 809 * currently manages. 810 */ 811 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message, 812 struct wpa_global *global) 813 { 814 struct wpa_supplicant *wpa_s; 815 char *path; 816 DBusMessage *reply = NULL; 817 818 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, 819 DBUS_TYPE_INVALID); 820 821 wpa_s = get_iface_by_dbus_path(global, path); 822 if (wpa_s == NULL) 823 reply = wpas_dbus_error_iface_unknown(message); 824 else if (wpa_supplicant_remove_iface(global, wpa_s, 0)) { 825 reply = wpas_dbus_error_unknown_error( 826 message, 827 "wpa_supplicant couldn't remove this interface."); 828 } 829 830 return reply; 831 } 832 833 834 /** 835 * wpas_dbus_handler_get_interface - Get the object path for an interface name 836 * @message: Pointer to incoming dbus message 837 * @global: %wpa_supplicant global data structure 838 * Returns: The object path of the interface object, 839 * or a dbus error message with more information 840 * 841 * Handler function for "getInterface" method call. 842 */ 843 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message, 844 struct wpa_global *global) 845 { 846 DBusMessage *reply = NULL; 847 const char *ifname; 848 const char *path; 849 struct wpa_supplicant *wpa_s; 850 851 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname, 852 DBUS_TYPE_INVALID); 853 854 wpa_s = wpa_supplicant_get_iface(global, ifname); 855 if (wpa_s == NULL || wpa_s->dbus_new_path == NULL) 856 return wpas_dbus_error_iface_unknown(message); 857 858 path = wpa_s->dbus_new_path; 859 reply = dbus_message_new_method_return(message); 860 if (reply == NULL) 861 return wpas_dbus_error_no_memory(message); 862 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, 863 DBUS_TYPE_INVALID)) { 864 dbus_message_unref(reply); 865 return wpas_dbus_error_no_memory(message); 866 } 867 868 return reply; 869 } 870 871 872 /** 873 * wpas_dbus_getter_debug_level - Get debug level 874 * @iter: Pointer to incoming dbus message iter 875 * @error: Location to store error on failure 876 * @user_data: Function specific data 877 * Returns: TRUE on success, FALSE on failure 878 * 879 * Getter for "DebugLevel" property. 880 */ 881 dbus_bool_t wpas_dbus_getter_debug_level( 882 const struct wpa_dbus_property_desc *property_desc, 883 DBusMessageIter *iter, DBusError *error, void *user_data) 884 { 885 const char *str; 886 int idx = wpa_debug_level; 887 888 if (idx < 0) 889 idx = 0; 890 if (idx > 5) 891 idx = 5; 892 str = debug_strings[idx]; 893 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 894 &str, error); 895 } 896 897 898 /** 899 * wpas_dbus_getter_debug_timestamp - Get debug timestamp 900 * @iter: Pointer to incoming dbus message iter 901 * @error: Location to store error on failure 902 * @user_data: Function specific data 903 * Returns: TRUE on success, FALSE on failure 904 * 905 * Getter for "DebugTimestamp" property. 906 */ 907 dbus_bool_t wpas_dbus_getter_debug_timestamp( 908 const struct wpa_dbus_property_desc *property_desc, 909 DBusMessageIter *iter, DBusError *error, void *user_data) 910 { 911 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 912 &wpa_debug_timestamp, error); 913 914 } 915 916 917 /** 918 * wpas_dbus_getter_debug_show_keys - Get debug show keys 919 * @iter: Pointer to incoming dbus message iter 920 * @error: Location to store error on failure 921 * @user_data: Function specific data 922 * Returns: TRUE on success, FALSE on failure 923 * 924 * Getter for "DebugShowKeys" property. 925 */ 926 dbus_bool_t wpas_dbus_getter_debug_show_keys( 927 const struct wpa_dbus_property_desc *property_desc, 928 DBusMessageIter *iter, DBusError *error, void *user_data) 929 { 930 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 931 &wpa_debug_show_keys, error); 932 933 } 934 935 /** 936 * wpas_dbus_setter_debug_level - Set debug level 937 * @iter: Pointer to incoming dbus message iter 938 * @error: Location to store error on failure 939 * @user_data: Function specific data 940 * Returns: TRUE on success, FALSE on failure 941 * 942 * Setter for "DebugLevel" property. 943 */ 944 dbus_bool_t wpas_dbus_setter_debug_level( 945 const struct wpa_dbus_property_desc *property_desc, 946 DBusMessageIter *iter, DBusError *error, void *user_data) 947 { 948 struct wpa_global *global = user_data; 949 const char *str = NULL; 950 int i, val = -1; 951 952 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, 953 &str)) 954 return FALSE; 955 956 for (i = 0; debug_strings[i]; i++) 957 if (os_strcmp(debug_strings[i], str) == 0) { 958 val = i; 959 break; 960 } 961 962 if (val < 0 || 963 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp, 964 wpa_debug_show_keys)) { 965 dbus_set_error_const(error, DBUS_ERROR_FAILED, 966 "wrong debug level value"); 967 return FALSE; 968 } 969 970 return TRUE; 971 } 972 973 974 /** 975 * wpas_dbus_setter_debug_timestamp - Set debug timestamp 976 * @iter: Pointer to incoming dbus message iter 977 * @error: Location to store error on failure 978 * @user_data: Function specific data 979 * Returns: TRUE on success, FALSE on failure 980 * 981 * Setter for "DebugTimestamp" property. 982 */ 983 dbus_bool_t wpas_dbus_setter_debug_timestamp( 984 const struct wpa_dbus_property_desc *property_desc, 985 DBusMessageIter *iter, DBusError *error, void *user_data) 986 { 987 struct wpa_global *global = user_data; 988 dbus_bool_t val; 989 990 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 991 &val)) 992 return FALSE; 993 994 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0, 995 wpa_debug_show_keys); 996 return TRUE; 997 } 998 999 1000 /** 1001 * wpas_dbus_setter_debug_show_keys - Set debug show keys 1002 * @iter: Pointer to incoming dbus message iter 1003 * @error: Location to store error on failure 1004 * @user_data: Function specific data 1005 * Returns: TRUE on success, FALSE on failure 1006 * 1007 * Setter for "DebugShowKeys" property. 1008 */ 1009 dbus_bool_t wpas_dbus_setter_debug_show_keys( 1010 const struct wpa_dbus_property_desc *property_desc, 1011 DBusMessageIter *iter, DBusError *error, void *user_data) 1012 { 1013 struct wpa_global *global = user_data; 1014 dbus_bool_t val; 1015 1016 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 1017 &val)) 1018 return FALSE; 1019 1020 wpa_supplicant_set_debug_params(global, wpa_debug_level, 1021 wpa_debug_timestamp, 1022 val ? 1 : 0); 1023 return TRUE; 1024 } 1025 1026 1027 /** 1028 * wpas_dbus_getter_interfaces - Request registered interfaces list 1029 * @iter: Pointer to incoming dbus message iter 1030 * @error: Location to store error on failure 1031 * @user_data: Function specific data 1032 * Returns: TRUE on success, FALSE on failure 1033 * 1034 * Getter for "Interfaces" property. Handles requests 1035 * by dbus clients to return list of registered interfaces objects 1036 * paths 1037 */ 1038 dbus_bool_t wpas_dbus_getter_interfaces( 1039 const struct wpa_dbus_property_desc *property_desc, 1040 DBusMessageIter *iter, DBusError *error, void *user_data) 1041 { 1042 struct wpa_global *global = user_data; 1043 struct wpa_supplicant *wpa_s; 1044 const char **paths; 1045 unsigned int i = 0, num = 0; 1046 dbus_bool_t success; 1047 1048 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 1049 if (wpa_s->dbus_new_path) 1050 num++; 1051 } 1052 1053 paths = os_calloc(num, sizeof(char *)); 1054 if (!paths) { 1055 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1056 return FALSE; 1057 } 1058 1059 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 1060 if (wpa_s->dbus_new_path) 1061 paths[i++] = wpa_s->dbus_new_path; 1062 } 1063 1064 success = wpas_dbus_simple_array_property_getter(iter, 1065 DBUS_TYPE_OBJECT_PATH, 1066 paths, num, error); 1067 1068 os_free(paths); 1069 return success; 1070 } 1071 1072 1073 /** 1074 * wpas_dbus_getter_eap_methods - Request supported EAP methods list 1075 * @iter: Pointer to incoming dbus message iter 1076 * @error: Location to store error on failure 1077 * @user_data: Function specific data 1078 * Returns: TRUE on success, FALSE on failure 1079 * 1080 * Getter for "EapMethods" property. Handles requests 1081 * by dbus clients to return list of strings with supported EAP methods 1082 */ 1083 dbus_bool_t wpas_dbus_getter_eap_methods( 1084 const struct wpa_dbus_property_desc *property_desc, 1085 DBusMessageIter *iter, DBusError *error, void *user_data) 1086 { 1087 char **eap_methods; 1088 size_t num_items = 0; 1089 dbus_bool_t success; 1090 1091 eap_methods = eap_get_names_as_string_array(&num_items); 1092 if (!eap_methods) { 1093 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 1094 return FALSE; 1095 } 1096 1097 success = wpas_dbus_simple_array_property_getter(iter, 1098 DBUS_TYPE_STRING, 1099 eap_methods, 1100 num_items, error); 1101 1102 while (num_items) 1103 os_free(eap_methods[--num_items]); 1104 os_free(eap_methods); 1105 return success; 1106 } 1107 1108 1109 /** 1110 * wpas_dbus_getter_global_capabilities - Request supported global capabilities 1111 * @iter: Pointer to incoming dbus message iter 1112 * @error: Location to store error on failure 1113 * @user_data: Function specific data 1114 * Returns: TRUE on success, FALSE on failure 1115 * 1116 * Getter for "Capabilities" property. Handles requests by dbus clients to 1117 * return a list of strings with supported capabilities like AP, RSN IBSS, 1118 * and P2P that are determined at compile time. 1119 */ 1120 dbus_bool_t wpas_dbus_getter_global_capabilities( 1121 const struct wpa_dbus_property_desc *property_desc, 1122 DBusMessageIter *iter, DBusError *error, void *user_data) 1123 { 1124 const char *capabilities[13]; 1125 size_t num_items = 0; 1126 struct wpa_global *global = user_data; 1127 struct wpa_supplicant *wpa_s; 1128 #ifdef CONFIG_FILS 1129 int fils_supported = 0, fils_sk_pfs_supported = 0; 1130 #endif /* CONFIG_FILS */ 1131 int ext_key_id_supported = 0; 1132 1133 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 1134 #ifdef CONFIG_FILS 1135 if (wpa_is_fils_supported(wpa_s)) 1136 fils_supported = 1; 1137 if (wpa_is_fils_sk_pfs_supported(wpa_s)) 1138 fils_sk_pfs_supported = 1; 1139 #endif /* CONFIG_FILS */ 1140 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID) 1141 ext_key_id_supported = 1; 1142 } 1143 1144 #ifdef CONFIG_AP 1145 capabilities[num_items++] = "ap"; 1146 #endif /* CONFIG_AP */ 1147 #ifdef CONFIG_IBSS_RSN 1148 capabilities[num_items++] = "ibss-rsn"; 1149 #endif /* CONFIG_IBSS_RSN */ 1150 #ifdef CONFIG_P2P 1151 capabilities[num_items++] = "p2p"; 1152 #endif /* CONFIG_P2P */ 1153 #ifdef CONFIG_INTERWORKING 1154 capabilities[num_items++] = "interworking"; 1155 #endif /* CONFIG_INTERWORKING */ 1156 capabilities[num_items++] = "pmf"; 1157 #ifdef CONFIG_MESH 1158 capabilities[num_items++] = "mesh"; 1159 #endif /* CONFIG_MESH */ 1160 #ifdef CONFIG_FILS 1161 if (fils_supported) 1162 capabilities[num_items++] = "fils"; 1163 if (fils_sk_pfs_supported) 1164 capabilities[num_items++] = "fils_sk_pfs"; 1165 #endif /* CONFIG_FILS */ 1166 #ifdef CONFIG_IEEE80211R 1167 capabilities[num_items++] = "ft"; 1168 #endif /* CONFIG_IEEE80211R */ 1169 #ifdef CONFIG_SHA384 1170 capabilities[num_items++] = "sha384"; 1171 #endif /* CONFIG_SHA384 */ 1172 #ifdef CONFIG_OWE 1173 capabilities[num_items++] = "owe"; 1174 #endif /* CONFIG_OWE */ 1175 #ifdef CONFIG_SUITEB192 1176 capabilities[num_items++] = "suiteb192"; 1177 #endif /* CONFIG_SUITEB192 */ 1178 if (ext_key_id_supported) 1179 capabilities[num_items++] = "extended_key_id"; 1180 1181 return wpas_dbus_simple_array_property_getter(iter, 1182 DBUS_TYPE_STRING, 1183 capabilities, 1184 num_items, error); 1185 } 1186 1187 1188 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var, 1189 char **type, DBusMessage **reply) 1190 { 1191 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) { 1192 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a string", 1193 __func__); 1194 *reply = wpas_dbus_error_invalid_args( 1195 message, "Wrong Type value type. String required"); 1196 return -1; 1197 } 1198 dbus_message_iter_get_basic(var, type); 1199 return 0; 1200 } 1201 1202 1203 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var, 1204 struct wpa_driver_scan_params *params, 1205 DBusMessage **reply) 1206 { 1207 struct wpa_driver_scan_ssid *ssids = params->ssids; 1208 size_t ssids_num = 0; 1209 u8 *ssid; 1210 DBusMessageIter array_iter, sub_array_iter; 1211 char *val; 1212 int len; 1213 1214 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) { 1215 wpa_printf(MSG_DEBUG, 1216 "%s[dbus]: ssids must be an array of arrays of bytes", 1217 __func__); 1218 *reply = wpas_dbus_error_invalid_args( 1219 message, 1220 "Wrong SSIDs value type. Array of arrays of bytes required"); 1221 return -1; 1222 } 1223 1224 dbus_message_iter_recurse(var, &array_iter); 1225 1226 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY || 1227 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) { 1228 wpa_printf(MSG_DEBUG, 1229 "%s[dbus]: ssids must be an array of arrays of bytes", 1230 __func__); 1231 *reply = wpas_dbus_error_invalid_args( 1232 message, 1233 "Wrong SSIDs value type. Array of arrays of bytes required"); 1234 return -1; 1235 } 1236 1237 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) { 1238 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) { 1239 wpa_printf(MSG_DEBUG, 1240 "%s[dbus]: Too many ssids specified on scan dbus call", 1241 __func__); 1242 *reply = wpas_dbus_error_invalid_args( 1243 message, 1244 "Too many ssids specified. Specify at most four"); 1245 return -1; 1246 } 1247 1248 dbus_message_iter_recurse(&array_iter, &sub_array_iter); 1249 1250 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len); 1251 1252 if (len > SSID_MAX_LEN) { 1253 wpa_printf(MSG_DEBUG, 1254 "%s[dbus]: SSID too long (len=%d max_len=%d)", 1255 __func__, len, SSID_MAX_LEN); 1256 *reply = wpas_dbus_error_invalid_args( 1257 message, "Invalid SSID: too long"); 1258 return -1; 1259 } 1260 1261 if (len != 0) { 1262 ssid = os_memdup(val, len); 1263 if (ssid == NULL) { 1264 *reply = wpas_dbus_error_no_memory(message); 1265 return -1; 1266 } 1267 } else { 1268 /* Allow zero-length SSIDs */ 1269 ssid = NULL; 1270 } 1271 1272 ssids[ssids_num].ssid = ssid; 1273 ssids[ssids_num].ssid_len = len; 1274 1275 dbus_message_iter_next(&array_iter); 1276 ssids_num++; 1277 } 1278 1279 params->num_ssids = ssids_num; 1280 return 0; 1281 } 1282 1283 1284 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var, 1285 struct wpa_driver_scan_params *params, 1286 DBusMessage **reply) 1287 { 1288 u8 *ies = NULL, *nies; 1289 size_t ies_len = 0; 1290 DBusMessageIter array_iter, sub_array_iter; 1291 char *val; 1292 int len; 1293 1294 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) { 1295 wpa_printf(MSG_DEBUG, 1296 "%s[dbus]: ies must be an array of arrays of bytes", 1297 __func__); 1298 *reply = wpas_dbus_error_invalid_args( 1299 message, 1300 "Wrong IEs value type. Array of arrays of bytes required"); 1301 return -1; 1302 } 1303 1304 dbus_message_iter_recurse(var, &array_iter); 1305 1306 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY || 1307 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) { 1308 wpa_printf(MSG_DEBUG, 1309 "%s[dbus]: ies must be an array of arrays of bytes", 1310 __func__); 1311 *reply = wpas_dbus_error_invalid_args( 1312 message, "Wrong IEs value type. Array required"); 1313 return -1; 1314 } 1315 1316 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) { 1317 dbus_message_iter_recurse(&array_iter, &sub_array_iter); 1318 1319 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len); 1320 if (len <= 0) { 1321 dbus_message_iter_next(&array_iter); 1322 continue; 1323 } 1324 1325 nies = os_realloc(ies, ies_len + len); 1326 if (nies == NULL) { 1327 os_free(ies); 1328 *reply = wpas_dbus_error_no_memory(message); 1329 return -1; 1330 } 1331 ies = nies; 1332 os_memcpy(ies + ies_len, val, len); 1333 ies_len += len; 1334 1335 dbus_message_iter_next(&array_iter); 1336 } 1337 1338 params->extra_ies = ies; 1339 params->extra_ies_len = ies_len; 1340 return 0; 1341 } 1342 1343 1344 static int wpas_dbus_get_scan_channels(DBusMessage *message, 1345 DBusMessageIter *var, 1346 struct wpa_driver_scan_params *params, 1347 DBusMessage **reply) 1348 { 1349 DBusMessageIter array_iter, sub_array_iter; 1350 int *freqs = NULL, *nfreqs; 1351 size_t freqs_num = 0; 1352 1353 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) { 1354 wpa_printf(MSG_DEBUG, 1355 "%s[dbus]: Channels must be an array of structs", 1356 __func__); 1357 *reply = wpas_dbus_error_invalid_args( 1358 message, 1359 "Wrong Channels value type. Array of structs required"); 1360 return -1; 1361 } 1362 1363 dbus_message_iter_recurse(var, &array_iter); 1364 1365 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) { 1366 wpa_printf(MSG_DEBUG, 1367 "%s[dbus]: Channels must be an array of structs", 1368 __func__); 1369 *reply = wpas_dbus_error_invalid_args( 1370 message, 1371 "Wrong Channels value type. Array of structs required"); 1372 return -1; 1373 } 1374 1375 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT) 1376 { 1377 int freq, width; 1378 1379 dbus_message_iter_recurse(&array_iter, &sub_array_iter); 1380 1381 if (dbus_message_iter_get_arg_type(&sub_array_iter) != 1382 DBUS_TYPE_UINT32) { 1383 wpa_printf(MSG_DEBUG, 1384 "%s[dbus]: Channel must by specified by struct of two UINT32s %c", 1385 __func__, 1386 dbus_message_iter_get_arg_type( 1387 &sub_array_iter)); 1388 *reply = wpas_dbus_error_invalid_args( 1389 message, 1390 "Wrong Channel struct. Two UINT32s required"); 1391 os_free(freqs); 1392 return -1; 1393 } 1394 dbus_message_iter_get_basic(&sub_array_iter, &freq); 1395 1396 if (!dbus_message_iter_next(&sub_array_iter) || 1397 dbus_message_iter_get_arg_type(&sub_array_iter) != 1398 DBUS_TYPE_UINT32) { 1399 wpa_printf(MSG_DEBUG, 1400 "%s[dbus]: Channel must by specified by struct of two UINT32s", 1401 __func__); 1402 *reply = wpas_dbus_error_invalid_args( 1403 message, 1404 "Wrong Channel struct. Two UINT32s required"); 1405 os_free(freqs); 1406 return -1; 1407 } 1408 1409 dbus_message_iter_get_basic(&sub_array_iter, &width); 1410 1411 #define FREQS_ALLOC_CHUNK 32 1412 if (freqs_num % FREQS_ALLOC_CHUNK == 0) { 1413 nfreqs = os_realloc_array( 1414 freqs, freqs_num + FREQS_ALLOC_CHUNK, 1415 sizeof(int)); 1416 if (nfreqs == NULL) 1417 os_free(freqs); 1418 freqs = nfreqs; 1419 } 1420 if (freqs == NULL) { 1421 *reply = wpas_dbus_error_no_memory(message); 1422 return -1; 1423 } 1424 1425 freqs[freqs_num] = freq; 1426 1427 freqs_num++; 1428 dbus_message_iter_next(&array_iter); 1429 } 1430 1431 nfreqs = os_realloc_array(freqs, freqs_num + 1, sizeof(int)); 1432 if (nfreqs == NULL) 1433 os_free(freqs); 1434 freqs = nfreqs; 1435 if (freqs == NULL) { 1436 *reply = wpas_dbus_error_no_memory(message); 1437 return -1; 1438 } 1439 freqs[freqs_num] = 0; 1440 1441 params->freqs = freqs; 1442 return 0; 1443 } 1444 1445 1446 static int wpas_dbus_get_scan_allow_roam(DBusMessage *message, 1447 DBusMessageIter *var, 1448 dbus_bool_t *allow, 1449 DBusMessage **reply) 1450 { 1451 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_BOOLEAN) { 1452 wpa_printf(MSG_DEBUG, "%s[dbus]: Type must be a boolean", 1453 __func__); 1454 *reply = wpas_dbus_error_invalid_args( 1455 message, "Wrong Type value type. Boolean required"); 1456 return -1; 1457 } 1458 dbus_message_iter_get_basic(var, allow); 1459 return 0; 1460 } 1461 1462 1463 /** 1464 * wpas_dbus_handler_scan - Request a wireless scan on an interface 1465 * @message: Pointer to incoming dbus message 1466 * @wpa_s: wpa_supplicant structure for a network interface 1467 * Returns: NULL indicating success or DBus error message on failure 1468 * 1469 * Handler function for "Scan" method call of a network device. Requests 1470 * that wpa_supplicant perform a wireless scan as soon as possible 1471 * on a particular wireless interface. 1472 */ 1473 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message, 1474 struct wpa_supplicant *wpa_s) 1475 { 1476 DBusMessage *reply = NULL; 1477 DBusMessageIter iter, dict_iter, entry_iter, variant_iter; 1478 char *key = NULL, *type = NULL; 1479 struct wpa_driver_scan_params params; 1480 size_t i; 1481 dbus_bool_t allow_roam = 1; 1482 1483 os_memset(¶ms, 0, sizeof(params)); 1484 1485 dbus_message_iter_init(message, &iter); 1486 1487 dbus_message_iter_recurse(&iter, &dict_iter); 1488 1489 while (dbus_message_iter_get_arg_type(&dict_iter) == 1490 DBUS_TYPE_DICT_ENTRY) { 1491 dbus_message_iter_recurse(&dict_iter, &entry_iter); 1492 dbus_message_iter_get_basic(&entry_iter, &key); 1493 dbus_message_iter_next(&entry_iter); 1494 dbus_message_iter_recurse(&entry_iter, &variant_iter); 1495 1496 if (os_strcmp(key, "Type") == 0) { 1497 if (wpas_dbus_get_scan_type(message, &variant_iter, 1498 &type, &reply) < 0) 1499 goto out; 1500 } else if (os_strcmp(key, "SSIDs") == 0) { 1501 if (wpas_dbus_get_scan_ssids(message, &variant_iter, 1502 ¶ms, &reply) < 0) 1503 goto out; 1504 } else if (os_strcmp(key, "IEs") == 0) { 1505 if (wpas_dbus_get_scan_ies(message, &variant_iter, 1506 ¶ms, &reply) < 0) 1507 goto out; 1508 } else if (os_strcmp(key, "Channels") == 0) { 1509 if (wpas_dbus_get_scan_channels(message, &variant_iter, 1510 ¶ms, &reply) < 0) 1511 goto out; 1512 } else if (os_strcmp(key, "AllowRoam") == 0) { 1513 if (wpas_dbus_get_scan_allow_roam(message, 1514 &variant_iter, 1515 &allow_roam, 1516 &reply) < 0) 1517 goto out; 1518 } else { 1519 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown argument %s", 1520 __func__, key); 1521 reply = wpas_dbus_error_invalid_args(message, key); 1522 goto out; 1523 } 1524 1525 dbus_message_iter_next(&dict_iter); 1526 } 1527 1528 if (!type) { 1529 wpa_printf(MSG_DEBUG, "%s[dbus]: Scan type not specified", 1530 __func__); 1531 reply = wpas_dbus_error_invalid_args(message, key); 1532 goto out; 1533 } 1534 1535 if (os_strcmp(type, "passive") == 0) { 1536 if (params.num_ssids || params.extra_ies_len) { 1537 wpa_printf(MSG_DEBUG, 1538 "%s[dbus]: SSIDs or IEs specified for passive scan.", 1539 __func__); 1540 reply = wpas_dbus_error_invalid_args( 1541 message, 1542 "You can specify only Channels in passive scan"); 1543 goto out; 1544 } else { 1545 if (wpa_s->sched_scanning) { 1546 wpa_printf(MSG_DEBUG, 1547 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed", 1548 __func__); 1549 wpa_supplicant_cancel_sched_scan(wpa_s); 1550 } 1551 1552 if (params.freqs && params.freqs[0]) { 1553 wpa_s->last_scan_req = MANUAL_SCAN_REQ; 1554 if (wpa_supplicant_trigger_scan(wpa_s, 1555 ¶ms)) { 1556 reply = wpas_dbus_error_scan_error( 1557 message, 1558 "Scan request rejected"); 1559 } 1560 } else { 1561 wpa_s->scan_req = MANUAL_SCAN_REQ; 1562 wpa_supplicant_req_scan(wpa_s, 0, 0); 1563 } 1564 } 1565 } else if (os_strcmp(type, "active") == 0) { 1566 if (!params.num_ssids) { 1567 /* Add wildcard ssid */ 1568 params.num_ssids++; 1569 } 1570 #ifdef CONFIG_AUTOSCAN 1571 autoscan_deinit(wpa_s); 1572 #endif /* CONFIG_AUTOSCAN */ 1573 if (wpa_s->sched_scanning) { 1574 wpa_printf(MSG_DEBUG, 1575 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed", 1576 __func__); 1577 wpa_supplicant_cancel_sched_scan(wpa_s); 1578 } 1579 1580 wpa_s->last_scan_req = MANUAL_SCAN_REQ; 1581 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) { 1582 reply = wpas_dbus_error_scan_error( 1583 message, "Scan request rejected"); 1584 } 1585 } else { 1586 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s", 1587 __func__, type); 1588 reply = wpas_dbus_error_invalid_args(message, 1589 "Wrong scan type"); 1590 goto out; 1591 } 1592 1593 if (!allow_roam) 1594 wpa_s->scan_res_handler = scan_only_handler; 1595 1596 out: 1597 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++) 1598 os_free((u8 *) params.ssids[i].ssid); 1599 os_free((u8 *) params.extra_ies); 1600 os_free(params.freqs); 1601 return reply; 1602 } 1603 1604 1605 /* 1606 * wpas_dbus_handler_abort_scan - Request an ongoing scan to be aborted 1607 * @message: Pointer to incoming dbus message 1608 * @wpa_s: wpa_supplicant structure for a network interface 1609 * Returns: Abort failed or no scan in progress DBus error message on failure 1610 * or NULL otherwise. 1611 * 1612 * Handler function for "AbortScan" method call of network interface. 1613 */ 1614 DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message, 1615 struct wpa_supplicant *wpa_s) 1616 { 1617 if (wpas_abort_ongoing_scan(wpa_s) < 0) 1618 return dbus_message_new_error( 1619 message, WPAS_DBUS_ERROR_IFACE_SCAN_ERROR, 1620 "Abort failed or no scan in progress"); 1621 1622 return NULL; 1623 } 1624 1625 1626 /** 1627 * wpas_dbus_new_iface_add_cred - Add a new credential 1628 * @message: Pointer to incoming dbus message 1629 * @wpa_s: wpa_supplicant structure for a network interface 1630 * Returns: A dbus message containing the object path of the new credential 1631 * 1632 * Handler function for "AddCred" method call of a network interface. 1633 */ 1634 DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message, 1635 struct wpa_supplicant *wpa_s) 1636 { 1637 DBusMessage *reply = NULL; 1638 DBusMessageIter iter; 1639 struct wpa_cred *cred = NULL; 1640 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 1641 DBusError error; 1642 1643 dbus_message_iter_init(message, &iter); 1644 1645 if (wpa_s->dbus_new_path) 1646 cred = wpa_config_add_cred(wpa_s->conf); 1647 if (!cred) { 1648 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new credential.", 1649 __func__); 1650 reply = wpas_dbus_error_unknown_error( 1651 message, 1652 "wpa_supplicant could not add a credential on this interface."); 1653 goto err; 1654 } 1655 1656 dbus_error_init(&error); 1657 if (!set_cred_properties(wpa_s, cred, &iter, &error)) { 1658 wpa_printf(MSG_DEBUG, 1659 "%s[dbus]: control interface couldn't set credential properties", 1660 __func__); 1661 reply = wpas_dbus_reply_new_from_error(message, &error, 1662 DBUS_ERROR_INVALID_ARGS, 1663 "Failed to add credential"); 1664 dbus_error_free(&error); 1665 goto err; 1666 } 1667 1668 /* Construct the object path for this network. */ 1669 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 1670 "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%d", 1671 wpa_s->dbus_new_path, cred->id); 1672 1673 reply = dbus_message_new_method_return(message); 1674 if (!reply) { 1675 reply = wpas_dbus_error_no_memory(message); 1676 goto err; 1677 } 1678 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, 1679 DBUS_TYPE_INVALID)) { 1680 dbus_message_unref(reply); 1681 reply = wpas_dbus_error_no_memory(message); 1682 goto err; 1683 } 1684 1685 return reply; 1686 1687 err: 1688 if (cred) 1689 wpa_config_remove_cred(wpa_s->conf, cred->id); 1690 return reply; 1691 } 1692 1693 1694 /** 1695 * wpas_dbus_handler_remove_cred - Remove a configured credential 1696 * @message: Pointer to incoming dbus message 1697 * @wpa_s: wpa_supplicant structure for a network interface 1698 * Returns: NULL on success or dbus error on failure 1699 * 1700 * Handler function for "RemoveCred" method call of a network interface. 1701 */ 1702 DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message, 1703 struct wpa_supplicant *wpa_s) 1704 { 1705 DBusMessage *reply = NULL; 1706 const char *op; 1707 char *iface, *cred_id; 1708 int id; 1709 struct wpa_cred *cred; 1710 1711 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 1712 DBUS_TYPE_INVALID); 1713 1714 /* Extract the network ID and ensure the network is actually a child of 1715 * this interface */ 1716 iface = wpas_dbus_new_decompose_object_path( 1717 op, WPAS_DBUS_NEW_CREDENTIALS_PART, &cred_id); 1718 if (!iface || !cred_id || !wpa_s->dbus_new_path || 1719 os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 1720 reply = wpas_dbus_error_invalid_args(message, op); 1721 goto out; 1722 } 1723 1724 errno = 0; 1725 id = strtoul(cred_id, NULL, 10); 1726 if (errno != 0) { 1727 reply = wpas_dbus_error_invalid_args(message, op); 1728 goto out; 1729 } 1730 1731 cred = wpa_config_get_cred(wpa_s->conf, id); 1732 if (!cred) { 1733 wpa_printf(MSG_ERROR, "%s[dbus]: could not find credential %s", 1734 __func__, op); 1735 reply = wpas_dbus_error_invalid_args( 1736 message, "could not find credential"); 1737 goto out; 1738 } 1739 1740 if (wpas_remove_cred(wpa_s, cred) < 0) { 1741 wpa_printf(MSG_ERROR, 1742 "%s[dbus]: error occurred when removing cred %d", 1743 __func__, id); 1744 reply = wpas_dbus_error_unknown_error( 1745 message, 1746 "error removing the specified credential on its interface."); 1747 goto out; 1748 } 1749 1750 out: 1751 os_free(iface); 1752 return reply; 1753 } 1754 1755 1756 /** 1757 * wpas_dbus_handler_remove_all_creds - Remove all the configured credentials 1758 * @message: Pointer to incoming dbus message 1759 * @wpa_s: wpa_supplicant structure for a network interface 1760 * Returns: NULL indicating success or DBus error message on failure 1761 * 1762 * Handler function for "RemoveAllCreds" method call of a network interface. 1763 */ 1764 DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message, 1765 struct wpa_supplicant *wpa_s) 1766 { 1767 int res; 1768 DBusMessage *reply = NULL; 1769 1770 res = wpas_remove_all_creds(wpa_s); 1771 if (res < 0) { 1772 wpa_printf(MSG_ERROR, 1773 "%s[dbus]: failed to remove all credentials", 1774 __func__); 1775 reply = wpas_dbus_error_unknown_error( 1776 message, "failed to remove all credentials"); 1777 } 1778 1779 return reply; 1780 } 1781 1782 1783 #ifdef CONFIG_INTERWORKING 1784 DBusMessage * 1785 wpas_dbus_handler_interworking_select(DBusMessage *message, 1786 struct wpa_supplicant *wpa_s) 1787 { 1788 int result; 1789 DBusMessage *reply = NULL; 1790 1791 /* Automatic selection is disabled and no constraint on channels */ 1792 result = interworking_select(wpa_s, 0, NULL); 1793 if (result < 0) { 1794 wpa_printf(MSG_ERROR, 1795 "%s[dbus]: failed to start Interworking selection", 1796 __func__); 1797 reply = wpas_dbus_error_scan_error( 1798 message, 1799 "error starting Interworking selection."); 1800 } 1801 1802 return reply; 1803 } 1804 #endif /* CONFIG_INTERWORKING */ 1805 1806 1807 /** 1808 * wpas_dbus_handler_signal_poll - Request immediate signal properties 1809 * @message: Pointer to incoming dbus message 1810 * @wpa_s: wpa_supplicant structure for a network interface 1811 * Returns: NULL indicating success or DBus error message on failure 1812 * 1813 * Handler function for "SignalPoll" method call of a network device. Requests 1814 * that wpa_supplicant read signal properties like RSSI, noise, and link 1815 * speed and return them. 1816 */ 1817 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message, 1818 struct wpa_supplicant *wpa_s) 1819 { 1820 struct wpa_signal_info si; 1821 DBusMessage *reply = NULL; 1822 DBusMessageIter iter, iter_dict, variant_iter; 1823 int ret; 1824 1825 ret = wpa_drv_signal_poll(wpa_s, &si); 1826 if (ret) { 1827 return dbus_message_new_error(message, DBUS_ERROR_FAILED, 1828 "Failed to read signal"); 1829 } 1830 1831 reply = dbus_message_new_method_return(message); 1832 if (reply == NULL) 1833 goto nomem; 1834 1835 dbus_message_iter_init_append(reply, &iter); 1836 1837 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, 1838 "a{sv}", &variant_iter) || 1839 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) || 1840 !wpa_dbus_dict_append_int32(&iter_dict, "rssi", 1841 si.current_signal) || 1842 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed", 1843 si.current_txrate / 1000) || 1844 !wpa_dbus_dict_append_int32(&iter_dict, "noise", 1845 si.current_noise) || 1846 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency", 1847 si.frequency) || 1848 (si.chanwidth != CHAN_WIDTH_UNKNOWN && 1849 !wpa_dbus_dict_append_string( 1850 &iter_dict, "width", 1851 channel_width_to_string(si.chanwidth))) || 1852 (si.center_frq1 > 0 && si.center_frq2 > 0 && 1853 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1", 1854 si.center_frq1) || 1855 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2", 1856 si.center_frq2))) || 1857 (si.avg_signal && 1858 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi", 1859 si.avg_signal)) || 1860 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || 1861 !dbus_message_iter_close_container(&iter, &variant_iter)) 1862 goto nomem; 1863 1864 return reply; 1865 1866 nomem: 1867 if (reply) 1868 dbus_message_unref(reply); 1869 return wpas_dbus_error_no_memory(message); 1870 } 1871 1872 1873 /* 1874 * wpas_dbus_handler_disconnect - Terminate the current connection 1875 * @message: Pointer to incoming dbus message 1876 * @wpa_s: wpa_supplicant structure for a network interface 1877 * Returns: NotConnected DBus error message if already not connected 1878 * or NULL otherwise. 1879 * 1880 * Handler function for "Disconnect" method call of network interface. 1881 */ 1882 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message, 1883 struct wpa_supplicant *wpa_s) 1884 { 1885 if (wpa_s->current_ssid != NULL) { 1886 wpas_request_disconnection(wpa_s); 1887 return NULL; 1888 } 1889 1890 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED, 1891 "This interface is not connected"); 1892 } 1893 1894 1895 /** 1896 * wpas_dbus_new_iface_add_network - Add a new configured network 1897 * @message: Pointer to incoming dbus message 1898 * @wpa_s: wpa_supplicant structure for a network interface 1899 * Returns: A dbus message containing the object path of the new network 1900 * 1901 * Handler function for "AddNetwork" method call of a network interface. 1902 */ 1903 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message, 1904 struct wpa_supplicant *wpa_s) 1905 { 1906 DBusMessage *reply = NULL; 1907 DBusMessageIter iter; 1908 struct wpa_ssid *ssid = NULL; 1909 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 1910 DBusError error; 1911 1912 dbus_message_iter_init(message, &iter); 1913 1914 if (wpa_s->dbus_new_path) 1915 ssid = wpa_supplicant_add_network(wpa_s); 1916 if (ssid == NULL) { 1917 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.", 1918 __func__); 1919 reply = wpas_dbus_error_unknown_error( 1920 message, 1921 "wpa_supplicant could not add a network on this interface."); 1922 goto err; 1923 } 1924 1925 dbus_error_init(&error); 1926 if (!set_network_properties(wpa_s, ssid, &iter, &error)) { 1927 wpa_printf(MSG_DEBUG, 1928 "%s[dbus]: control interface couldn't set network properties", 1929 __func__); 1930 reply = wpas_dbus_reply_new_from_error(message, &error, 1931 DBUS_ERROR_INVALID_ARGS, 1932 "Failed to add network"); 1933 dbus_error_free(&error); 1934 goto err; 1935 } 1936 1937 /* Construct the object path for this network. */ 1938 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 1939 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 1940 wpa_s->dbus_new_path, ssid->id); 1941 1942 reply = dbus_message_new_method_return(message); 1943 if (reply == NULL) { 1944 reply = wpas_dbus_error_no_memory(message); 1945 goto err; 1946 } 1947 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, 1948 DBUS_TYPE_INVALID)) { 1949 dbus_message_unref(reply); 1950 reply = wpas_dbus_error_no_memory(message); 1951 goto err; 1952 } 1953 1954 return reply; 1955 1956 err: 1957 if (ssid) { 1958 wpas_notify_network_removed(wpa_s, ssid); 1959 wpa_config_remove_network(wpa_s->conf, ssid->id); 1960 } 1961 return reply; 1962 } 1963 1964 1965 /** 1966 * wpas_dbus_handler_reassociate - Reassociate 1967 * @message: Pointer to incoming dbus message 1968 * @wpa_s: wpa_supplicant structure for a network interface 1969 * Returns: InterfaceDisabled DBus error message if disabled 1970 * or NULL otherwise. 1971 * 1972 * Handler function for "Reassociate" method call of network interface. 1973 */ 1974 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message, 1975 struct wpa_supplicant *wpa_s) 1976 { 1977 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) { 1978 wpas_request_connection(wpa_s); 1979 return NULL; 1980 } 1981 1982 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED, 1983 "This interface is disabled"); 1984 } 1985 1986 1987 /** 1988 * wpas_dbus_handler_expect_disconnect - ExpectDisconnect 1989 * @message: Pointer to incoming dbus message 1990 * @global: %wpa_supplicant global data structure 1991 * Returns: NULL 1992 * 1993 * Handler function for notifying system there will be a expected disconnect. 1994 * This will prevent wpa_supplicant from adding the BSSID to the ignore list 1995 * upon next disconnect. 1996 */ 1997 DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message, 1998 struct wpa_global *global) 1999 { 2000 struct wpa_supplicant *wpa_s = global->ifaces; 2001 2002 for (; wpa_s; wpa_s = wpa_s->next) 2003 if (wpa_s->wpa_state >= WPA_ASSOCIATED) 2004 wpa_s->own_disconnect_req = 1; 2005 return NULL; 2006 } 2007 2008 2009 /** 2010 * wpas_dbus_handler_reattach - Reattach to current AP 2011 * @message: Pointer to incoming dbus message 2012 * @wpa_s: wpa_supplicant structure for a network interface 2013 * Returns: NotConnected DBus error message if not connected 2014 * or NULL otherwise. 2015 * 2016 * Handler function for "Reattach" method call of network interface. 2017 */ 2018 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message, 2019 struct wpa_supplicant *wpa_s) 2020 { 2021 if (wpa_s->current_ssid != NULL) { 2022 wpa_s->reattach = 1; 2023 wpas_request_connection(wpa_s); 2024 return NULL; 2025 } 2026 2027 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED, 2028 "This interface is not connected"); 2029 } 2030 2031 2032 /** 2033 * wpas_dbus_handler_reconnect - Reconnect if disconnected 2034 * @message: Pointer to incoming dbus message 2035 * @wpa_s: wpa_supplicant structure for a network interface 2036 * Returns: InterfaceDisabled DBus error message if disabled 2037 * or NULL otherwise. 2038 * 2039 * Handler function for "Reconnect" method call of network interface. 2040 */ 2041 DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message, 2042 struct wpa_supplicant *wpa_s) 2043 { 2044 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 2045 return dbus_message_new_error(message, 2046 WPAS_DBUS_ERROR_IFACE_DISABLED, 2047 "This interface is disabled"); 2048 } 2049 2050 if (wpa_s->disconnected) 2051 wpas_request_connection(wpa_s); 2052 return NULL; 2053 } 2054 2055 2056 /** 2057 * wpas_dbus_handler_remove_network - Remove a configured network 2058 * @message: Pointer to incoming dbus message 2059 * @wpa_s: wpa_supplicant structure for a network interface 2060 * Returns: NULL on success or dbus error on failure 2061 * 2062 * Handler function for "RemoveNetwork" method call of a network interface. 2063 */ 2064 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message, 2065 struct wpa_supplicant *wpa_s) 2066 { 2067 DBusMessage *reply = NULL; 2068 const char *op; 2069 char *iface, *net_id; 2070 int id; 2071 int result; 2072 2073 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 2074 DBUS_TYPE_INVALID); 2075 2076 /* Extract the network ID and ensure the network */ 2077 /* is actually a child of this interface */ 2078 iface = wpas_dbus_new_decompose_object_path(op, 2079 WPAS_DBUS_NEW_NETWORKS_PART, 2080 &net_id); 2081 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path || 2082 os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 2083 reply = wpas_dbus_error_invalid_args(message, op); 2084 goto out; 2085 } 2086 2087 errno = 0; 2088 id = strtoul(net_id, NULL, 10); 2089 if (errno != 0) { 2090 reply = wpas_dbus_error_invalid_args(message, op); 2091 goto out; 2092 } 2093 2094 result = wpa_supplicant_remove_network(wpa_s, id); 2095 if (result == -1) { 2096 reply = wpas_dbus_error_network_unknown(message); 2097 goto out; 2098 } 2099 if (result == -2) { 2100 wpa_printf(MSG_ERROR, 2101 "%s[dbus]: error occurred when removing network %d", 2102 __func__, id); 2103 reply = wpas_dbus_error_unknown_error( 2104 message, 2105 "error removing the specified network on is interface."); 2106 goto out; 2107 } 2108 2109 out: 2110 os_free(iface); 2111 return reply; 2112 } 2113 2114 2115 /** 2116 * wpas_dbus_handler_remove_all_networks - Remove all configured networks 2117 * @message: Pointer to incoming dbus message 2118 * @wpa_s: wpa_supplicant structure for a network interface 2119 * Returns: NULL on success or dbus error on failure 2120 * 2121 * Handler function for "RemoveAllNetworks" method call of a network interface. 2122 */ 2123 DBusMessage * wpas_dbus_handler_remove_all_networks( 2124 DBusMessage *message, struct wpa_supplicant *wpa_s) 2125 { 2126 /* NB: could check for failure and return an error */ 2127 wpa_supplicant_remove_all_networks(wpa_s); 2128 return NULL; 2129 } 2130 2131 2132 /** 2133 * wpas_dbus_handler_select_network - Attempt association with a network 2134 * @message: Pointer to incoming dbus message 2135 * @wpa_s: wpa_supplicant structure for a network interface 2136 * Returns: NULL on success or dbus error on failure 2137 * 2138 * Handler function for "SelectNetwork" method call of network interface. 2139 */ 2140 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message, 2141 struct wpa_supplicant *wpa_s) 2142 { 2143 DBusMessage *reply = NULL; 2144 const char *op; 2145 char *iface, *net_id; 2146 int id; 2147 struct wpa_ssid *ssid; 2148 2149 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 2150 DBUS_TYPE_INVALID); 2151 2152 /* Extract the network ID and ensure the network */ 2153 /* is actually a child of this interface */ 2154 iface = wpas_dbus_new_decompose_object_path(op, 2155 WPAS_DBUS_NEW_NETWORKS_PART, 2156 &net_id); 2157 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path || 2158 os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 2159 reply = wpas_dbus_error_invalid_args(message, op); 2160 goto out; 2161 } 2162 2163 errno = 0; 2164 id = strtoul(net_id, NULL, 10); 2165 if (errno != 0) { 2166 reply = wpas_dbus_error_invalid_args(message, op); 2167 goto out; 2168 } 2169 2170 ssid = wpa_config_get_network(wpa_s->conf, id); 2171 if (ssid == NULL) { 2172 reply = wpas_dbus_error_network_unknown(message); 2173 goto out; 2174 } 2175 2176 /* Finally, associate with the network */ 2177 wpa_supplicant_select_network(wpa_s, ssid); 2178 2179 out: 2180 os_free(iface); 2181 return reply; 2182 } 2183 2184 2185 /** 2186 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal 2187 * @message: Pointer to incoming dbus message 2188 * @wpa_s: wpa_supplicant structure for a network interface 2189 * Returns: NULL on success or dbus error on failure 2190 * 2191 * Handler function for "NetworkReply" method call of network interface. 2192 */ 2193 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message, 2194 struct wpa_supplicant *wpa_s) 2195 { 2196 #ifdef IEEE8021X_EAPOL 2197 DBusMessage *reply = NULL; 2198 const char *op, *field, *value; 2199 char *iface, *net_id; 2200 int id; 2201 struct wpa_ssid *ssid; 2202 2203 if (!dbus_message_get_args(message, NULL, 2204 DBUS_TYPE_OBJECT_PATH, &op, 2205 DBUS_TYPE_STRING, &field, 2206 DBUS_TYPE_STRING, &value, 2207 DBUS_TYPE_INVALID)) 2208 return wpas_dbus_error_invalid_args(message, NULL); 2209 2210 /* Extract the network ID and ensure the network */ 2211 /* is actually a child of this interface */ 2212 iface = wpas_dbus_new_decompose_object_path(op, 2213 WPAS_DBUS_NEW_NETWORKS_PART, 2214 &net_id); 2215 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path || 2216 os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 2217 reply = wpas_dbus_error_invalid_args(message, op); 2218 goto out; 2219 } 2220 2221 errno = 0; 2222 id = strtoul(net_id, NULL, 10); 2223 if (errno != 0) { 2224 reply = wpas_dbus_error_invalid_args(message, net_id); 2225 goto out; 2226 } 2227 2228 ssid = wpa_config_get_network(wpa_s->conf, id); 2229 if (ssid == NULL) { 2230 reply = wpas_dbus_error_network_unknown(message); 2231 goto out; 2232 } 2233 2234 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, 2235 field, value) < 0) 2236 reply = wpas_dbus_error_invalid_args(message, field); 2237 else { 2238 /* Tell EAP to retry immediately */ 2239 eapol_sm_notify_ctrl_response(wpa_s->eapol); 2240 } 2241 2242 out: 2243 os_free(iface); 2244 return reply; 2245 #else /* IEEE8021X_EAPOL */ 2246 wpa_printf(MSG_DEBUG, "dbus: 802.1X not included"); 2247 return wpas_dbus_error_unknown_error(message, "802.1X not included"); 2248 #endif /* IEEE8021X_EAPOL */ 2249 } 2250 2251 2252 /** 2253 * wpas_dbus_handler_roam - Initiate a roam to another BSS within the ESS 2254 * @message: Pointer to incoming dbus message 2255 * @wpa_s: wpa_supplicant structure for a network interface 2256 * Returns: NULL on success or dbus error on failure 2257 * 2258 * Handler function for "Roam" method call of network interface. 2259 */ 2260 DBusMessage * wpas_dbus_handler_roam(DBusMessage *message, 2261 struct wpa_supplicant *wpa_s) 2262 { 2263 #ifdef CONFIG_NO_SCAN_PROCESSING 2264 return wpas_dbus_error_unknown_error(message, 2265 "scan processing not included"); 2266 #else /* CONFIG_NO_SCAN_PROCESSING */ 2267 u8 bssid[ETH_ALEN]; 2268 struct wpa_bss *bss; 2269 struct wpa_ssid *ssid = wpa_s->current_ssid; 2270 char *addr; 2271 struct wpa_radio_work *already_connecting; 2272 2273 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &addr, 2274 DBUS_TYPE_INVALID)) 2275 return wpas_dbus_error_invalid_args(message, NULL); 2276 2277 if (hwaddr_aton(addr, bssid)) 2278 return wpas_dbus_error_invalid_args( 2279 message, "Invalid hardware address format"); 2280 2281 wpa_printf(MSG_DEBUG, "dbus: Roam " MACSTR, MAC2STR(bssid)); 2282 2283 if (!ssid) 2284 return dbus_message_new_error( 2285 message, WPAS_DBUS_ERROR_NOT_CONNECTED, 2286 "This interface is not connected"); 2287 2288 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); 2289 if (!bss) { 2290 wpa_printf(MSG_DEBUG, "dbus: Roam: Target BSS not found"); 2291 return wpas_dbus_error_invalid_args( 2292 message, "Target BSS not found"); 2293 } 2294 2295 already_connecting = radio_work_pending(wpa_s, "sme-connect"); 2296 wpa_s->reassociate = 1; 2297 wpa_supplicant_connect(wpa_s, bss, ssid); 2298 2299 /* 2300 * Indicate that an explicitly requested roam is in progress so scan 2301 * results that come in before the 'sme-connect' radio work gets 2302 * executed do not override the original connection attempt. 2303 */ 2304 if (!already_connecting && radio_work_pending(wpa_s, "sme-connect")) 2305 wpa_s->roam_in_progress = true; 2306 2307 return NULL; 2308 #endif /* CONFIG_NO_SCAN_PROCESSING */ 2309 } 2310 2311 #ifndef CONFIG_NO_CONFIG_BLOBS 2312 2313 /** 2314 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates) 2315 * @message: Pointer to incoming dbus message 2316 * @wpa_s: %wpa_supplicant data structure 2317 * Returns: A dbus message containing an error on failure or NULL on success 2318 * 2319 * Asks wpa_supplicant to internally store a binary blobs. 2320 */ 2321 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message, 2322 struct wpa_supplicant *wpa_s) 2323 { 2324 DBusMessage *reply = NULL; 2325 DBusMessageIter iter, array_iter; 2326 2327 char *blob_name; 2328 u8 *blob_data; 2329 int blob_len; 2330 struct wpa_config_blob *blob = NULL; 2331 2332 dbus_message_iter_init(message, &iter); 2333 dbus_message_iter_get_basic(&iter, &blob_name); 2334 2335 if (wpa_config_get_blob(wpa_s->conf, blob_name)) { 2336 return dbus_message_new_error(message, 2337 WPAS_DBUS_ERROR_BLOB_EXISTS, 2338 NULL); 2339 } 2340 2341 dbus_message_iter_next(&iter); 2342 dbus_message_iter_recurse(&iter, &array_iter); 2343 2344 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len); 2345 2346 blob = os_zalloc(sizeof(*blob)); 2347 if (!blob) { 2348 reply = wpas_dbus_error_no_memory(message); 2349 goto err; 2350 } 2351 2352 blob->data = os_memdup(blob_data, blob_len); 2353 blob->name = os_strdup(blob_name); 2354 if (!blob->data || !blob->name) { 2355 reply = wpas_dbus_error_no_memory(message); 2356 goto err; 2357 } 2358 blob->len = blob_len; 2359 2360 wpa_config_set_blob(wpa_s->conf, blob); 2361 wpas_notify_blob_added(wpa_s, blob->name); 2362 2363 return reply; 2364 2365 err: 2366 if (blob) { 2367 os_free(blob->name); 2368 os_free(blob->data); 2369 os_free(blob); 2370 } 2371 return reply; 2372 } 2373 2374 2375 /** 2376 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates) 2377 * @message: Pointer to incoming dbus message 2378 * @wpa_s: %wpa_supplicant data structure 2379 * Returns: A dbus message containing array of bytes (blob) 2380 * 2381 * Gets one wpa_supplicant's binary blobs. 2382 */ 2383 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message, 2384 struct wpa_supplicant *wpa_s) 2385 { 2386 DBusMessage *reply = NULL; 2387 DBusMessageIter iter, array_iter; 2388 2389 char *blob_name; 2390 const struct wpa_config_blob *blob; 2391 2392 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name, 2393 DBUS_TYPE_INVALID); 2394 2395 blob = wpa_config_get_blob(wpa_s->conf, blob_name); 2396 if (!blob) { 2397 return dbus_message_new_error(message, 2398 WPAS_DBUS_ERROR_BLOB_UNKNOWN, 2399 "Blob id not set"); 2400 } 2401 2402 reply = dbus_message_new_method_return(message); 2403 if (!reply) 2404 return wpas_dbus_error_no_memory(message); 2405 2406 dbus_message_iter_init_append(reply, &iter); 2407 2408 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 2409 DBUS_TYPE_BYTE_AS_STRING, 2410 &array_iter) || 2411 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE, 2412 &(blob->data), blob->len) || 2413 !dbus_message_iter_close_container(&iter, &array_iter)) { 2414 dbus_message_unref(reply); 2415 reply = wpas_dbus_error_no_memory(message); 2416 } 2417 2418 return reply; 2419 } 2420 2421 2422 /** 2423 * wpas_remove_handler_remove_blob - Remove named binary blob 2424 * @message: Pointer to incoming dbus message 2425 * @wpa_s: %wpa_supplicant data structure 2426 * Returns: NULL on success or dbus error 2427 * 2428 * Asks wpa_supplicant to internally remove a binary blobs. 2429 */ 2430 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message, 2431 struct wpa_supplicant *wpa_s) 2432 { 2433 DBusMessage *reply = NULL; 2434 char *blob_name; 2435 2436 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name, 2437 DBUS_TYPE_INVALID); 2438 2439 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) { 2440 return dbus_message_new_error(message, 2441 WPAS_DBUS_ERROR_BLOB_UNKNOWN, 2442 "Blob id not set"); 2443 } 2444 wpas_notify_blob_removed(wpa_s, blob_name); 2445 2446 return reply; 2447 2448 } 2449 2450 #endif /* CONFIG_NO_CONFIG_BLOBS */ 2451 2452 2453 /* 2454 * wpas_dbus_handler_flush_bss - Flush the BSS cache 2455 * @message: Pointer to incoming dbus message 2456 * @wpa_s: wpa_supplicant structure for a network interface 2457 * Returns: NULL 2458 * 2459 * Handler function for "FlushBSS" method call of network interface. 2460 */ 2461 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message, 2462 struct wpa_supplicant *wpa_s) 2463 { 2464 dbus_uint32_t age; 2465 2466 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age, 2467 DBUS_TYPE_INVALID); 2468 2469 if (age == 0) 2470 wpa_bss_flush(wpa_s); 2471 else 2472 wpa_bss_flush_by_age(wpa_s, age); 2473 2474 return NULL; 2475 } 2476 2477 2478 #ifdef CONFIG_AUTOSCAN 2479 /** 2480 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface 2481 * @message: Pointer to incoming dbus message 2482 * @wpa_s: wpa_supplicant structure for a network interface 2483 * Returns: NULL 2484 * 2485 * Handler function for "AutoScan" method call of network interface. 2486 */ 2487 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message, 2488 struct wpa_supplicant *wpa_s) 2489 { 2490 DBusMessage *reply = NULL; 2491 enum wpa_states state = wpa_s->wpa_state; 2492 char *arg; 2493 2494 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, 2495 DBUS_TYPE_INVALID); 2496 2497 if (arg != NULL && os_strlen(arg) > 0) { 2498 char *tmp; 2499 2500 tmp = os_strdup(arg); 2501 if (tmp == NULL) { 2502 reply = wpas_dbus_error_no_memory(message); 2503 } else { 2504 os_free(wpa_s->conf->autoscan); 2505 wpa_s->conf->autoscan = tmp; 2506 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 2507 autoscan_init(wpa_s, 1); 2508 else if (state == WPA_SCANNING) 2509 wpa_supplicant_reinit_autoscan(wpa_s); 2510 } 2511 } else if (arg != NULL && os_strlen(arg) == 0) { 2512 os_free(wpa_s->conf->autoscan); 2513 wpa_s->conf->autoscan = NULL; 2514 autoscan_deinit(wpa_s); 2515 } else 2516 reply = dbus_message_new_error(message, 2517 DBUS_ERROR_INVALID_ARGS, 2518 NULL); 2519 2520 return reply; 2521 } 2522 #endif /* CONFIG_AUTOSCAN */ 2523 2524 2525 /* 2526 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff 2527 * @message: Pointer to incoming dbus message 2528 * @wpa_s: wpa_supplicant structure for a network interface 2529 * Returns: NULL 2530 * 2531 * Handler function for "EAPLogoff" method call of network interface. 2532 */ 2533 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message, 2534 struct wpa_supplicant *wpa_s) 2535 { 2536 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 2537 return NULL; 2538 } 2539 2540 2541 /* 2542 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon 2543 * @message: Pointer to incoming dbus message 2544 * @wpa_s: wpa_supplicant structure for a network interface 2545 * Returns: NULL 2546 * 2547 * Handler function for "EAPLogin" method call of network interface. 2548 */ 2549 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message, 2550 struct wpa_supplicant *wpa_s) 2551 { 2552 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 2553 return NULL; 2554 } 2555 2556 2557 #ifdef CONFIG_TDLS 2558 2559 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name, 2560 u8 *peer_address, DBusMessage **error) 2561 { 2562 const char *peer_string; 2563 2564 *error = NULL; 2565 2566 if (!dbus_message_get_args(message, NULL, 2567 DBUS_TYPE_STRING, &peer_string, 2568 DBUS_TYPE_INVALID)) { 2569 *error = wpas_dbus_error_invalid_args(message, NULL); 2570 return -1; 2571 } 2572 2573 if (hwaddr_aton(peer_string, peer_address)) { 2574 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'", 2575 func_name, peer_string); 2576 *error = wpas_dbus_error_invalid_args( 2577 message, "Invalid hardware address format"); 2578 return -1; 2579 } 2580 2581 return 0; 2582 } 2583 2584 2585 /* 2586 * wpas_dbus_handler_tdls_discover - Discover TDLS peer 2587 * @message: Pointer to incoming dbus message 2588 * @wpa_s: wpa_supplicant structure for a network interface 2589 * Returns: NULL indicating success or DBus error message on failure 2590 * 2591 * Handler function for "TDLSDiscover" method call of network interface. 2592 */ 2593 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message, 2594 struct wpa_supplicant *wpa_s) 2595 { 2596 u8 peer[ETH_ALEN]; 2597 DBusMessage *error_reply; 2598 int ret; 2599 2600 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0) 2601 return error_reply; 2602 2603 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer)); 2604 2605 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2606 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 2607 else 2608 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 2609 2610 if (ret) { 2611 return wpas_dbus_error_unknown_error( 2612 message, "error performing TDLS discovery"); 2613 } 2614 2615 return NULL; 2616 } 2617 2618 2619 /* 2620 * wpas_dbus_handler_tdls_setup - Setup TDLS session 2621 * @message: Pointer to incoming dbus message 2622 * @wpa_s: wpa_supplicant structure for a network interface 2623 * Returns: NULL indicating success or DBus error message on failure 2624 * 2625 * Handler function for "TDLSSetup" method call of network interface. 2626 */ 2627 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message, 2628 struct wpa_supplicant *wpa_s) 2629 { 2630 u8 peer[ETH_ALEN]; 2631 DBusMessage *error_reply; 2632 int ret; 2633 2634 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0) 2635 return error_reply; 2636 2637 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer)); 2638 2639 wpa_tdls_remove(wpa_s->wpa, peer); 2640 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2641 ret = wpa_tdls_start(wpa_s->wpa, peer); 2642 else 2643 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 2644 2645 if (ret) { 2646 return wpas_dbus_error_unknown_error( 2647 message, "error performing TDLS setup"); 2648 } 2649 2650 return NULL; 2651 } 2652 2653 2654 /* 2655 * wpas_dbus_handler_tdls_status - Return TDLS session status 2656 * @message: Pointer to incoming dbus message 2657 * @wpa_s: wpa_supplicant structure for a network interface 2658 * Returns: A string representing the state of the link to this TDLS peer 2659 * 2660 * Handler function for "TDLSStatus" method call of network interface. 2661 */ 2662 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message, 2663 struct wpa_supplicant *wpa_s) 2664 { 2665 u8 peer[ETH_ALEN]; 2666 DBusMessage *reply; 2667 const char *tdls_status; 2668 2669 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0) 2670 return reply; 2671 2672 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer)); 2673 2674 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer); 2675 2676 reply = dbus_message_new_method_return(message); 2677 dbus_message_append_args(reply, DBUS_TYPE_STRING, 2678 &tdls_status, DBUS_TYPE_INVALID); 2679 return reply; 2680 } 2681 2682 2683 /* 2684 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session 2685 * @message: Pointer to incoming dbus message 2686 * @wpa_s: wpa_supplicant structure for a network interface 2687 * Returns: NULL indicating success or DBus error message on failure 2688 * 2689 * Handler function for "TDLSTeardown" method call of network interface. 2690 */ 2691 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message, 2692 struct wpa_supplicant *wpa_s) 2693 { 2694 u8 peer[ETH_ALEN]; 2695 DBusMessage *error_reply; 2696 int ret; 2697 2698 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0) 2699 return error_reply; 2700 2701 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer)); 2702 2703 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2704 ret = wpa_tdls_teardown_link( 2705 wpa_s->wpa, peer, 2706 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 2707 else 2708 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 2709 2710 if (ret) { 2711 return wpas_dbus_error_unknown_error( 2712 message, "error performing TDLS teardown"); 2713 } 2714 2715 return NULL; 2716 } 2717 2718 /* 2719 * wpas_dbus_handler_tdls_channel_switch - Enable channel switching with TDLS peer 2720 * @message: Pointer to incoming dbus message 2721 * @wpa_s: wpa_supplicant structure for a network interface 2722 * Returns: NULL indicating success or DBus error message on failure 2723 * 2724 * Handler function for "TDLSChannelSwitch" method call of network interface. 2725 */ 2726 DBusMessage * 2727 wpas_dbus_handler_tdls_channel_switch(DBusMessage *message, 2728 struct wpa_supplicant *wpa_s) 2729 { 2730 DBusMessageIter iter, iter_dict; 2731 struct wpa_dbus_dict_entry entry; 2732 u8 peer[ETH_ALEN]; 2733 struct hostapd_freq_params freq_params; 2734 u8 oper_class = 0; 2735 int ret; 2736 int is_peer_present = 0; 2737 2738 if (!wpa_tdls_is_external_setup(wpa_s->wpa)) { 2739 wpa_printf(MSG_INFO, 2740 "tdls_chanswitch: Only supported with external setup"); 2741 return wpas_dbus_error_unknown_error(message, "TDLS is not using external setup"); 2742 } 2743 2744 os_memset(&freq_params, 0, sizeof(freq_params)); 2745 2746 dbus_message_iter_init(message, &iter); 2747 2748 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 2749 return wpas_dbus_error_invalid_args(message, NULL); 2750 2751 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 2752 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 2753 return wpas_dbus_error_invalid_args(message, NULL); 2754 2755 if (os_strcmp(entry.key, "PeerAddress") == 0 && 2756 entry.type == DBUS_TYPE_STRING) { 2757 if (hwaddr_aton(entry.str_value, peer)) { 2758 wpa_printf(MSG_DEBUG, 2759 "tdls_chanswitch: Invalid address '%s'", 2760 entry.str_value); 2761 wpa_dbus_dict_entry_clear(&entry); 2762 return wpas_dbus_error_invalid_args(message, 2763 NULL); 2764 } 2765 2766 is_peer_present = 1; 2767 } else if (os_strcmp(entry.key, "OperClass") == 0 && 2768 entry.type == DBUS_TYPE_BYTE) { 2769 oper_class = entry.byte_value; 2770 } else if (os_strcmp(entry.key, "Frequency") == 0 && 2771 entry.type == DBUS_TYPE_UINT32) { 2772 freq_params.freq = entry.uint32_value; 2773 } else if (os_strcmp(entry.key, "SecChannelOffset") == 0 && 2774 entry.type == DBUS_TYPE_UINT32) { 2775 freq_params.sec_channel_offset = entry.uint32_value; 2776 } else if (os_strcmp(entry.key, "CenterFrequency1") == 0 && 2777 entry.type == DBUS_TYPE_UINT32) { 2778 freq_params.center_freq1 = entry.uint32_value; 2779 } else if (os_strcmp(entry.key, "CenterFrequency2") == 0 && 2780 entry.type == DBUS_TYPE_UINT32) { 2781 freq_params.center_freq2 = entry.uint32_value; 2782 } else if (os_strcmp(entry.key, "Bandwidth") == 0 && 2783 entry.type == DBUS_TYPE_UINT32) { 2784 freq_params.bandwidth = entry.uint32_value; 2785 } else if (os_strcmp(entry.key, "HT") == 0 && 2786 entry.type == DBUS_TYPE_BOOLEAN) { 2787 freq_params.ht_enabled = entry.bool_value; 2788 } else if (os_strcmp(entry.key, "VHT") == 0 && 2789 entry.type == DBUS_TYPE_BOOLEAN) { 2790 freq_params.vht_enabled = entry.bool_value; 2791 } else { 2792 wpa_dbus_dict_entry_clear(&entry); 2793 return wpas_dbus_error_invalid_args(message, NULL); 2794 } 2795 2796 wpa_dbus_dict_entry_clear(&entry); 2797 } 2798 2799 if (oper_class == 0) { 2800 wpa_printf(MSG_INFO, 2801 "tdls_chanswitch: Invalid op class provided"); 2802 return wpas_dbus_error_invalid_args( 2803 message, "Invalid op class provided"); 2804 } 2805 2806 if (freq_params.freq == 0) { 2807 wpa_printf(MSG_INFO, 2808 "tdls_chanswitch: Invalid freq provided"); 2809 return wpas_dbus_error_invalid_args(message, 2810 "Invalid freq provided"); 2811 } 2812 2813 if (is_peer_present == 0) { 2814 wpa_printf(MSG_DEBUG, 2815 "tdls_chanswitch: peer address not provided"); 2816 return wpas_dbus_error_invalid_args( 2817 message, "peer address not provided"); 2818 } 2819 2820 wpa_printf(MSG_DEBUG, "dbus: TDLS_CHAN_SWITCH " MACSTR 2821 " OP CLASS %d FREQ %d CENTER1 %d CENTER2 %d BW %d SEC_OFFSET %d%s%s", 2822 MAC2STR(peer), oper_class, freq_params.freq, 2823 freq_params.center_freq1, freq_params.center_freq2, 2824 freq_params.bandwidth, freq_params.sec_channel_offset, 2825 freq_params.ht_enabled ? " HT" : "", 2826 freq_params.vht_enabled ? " VHT" : ""); 2827 2828 ret = wpa_tdls_enable_chan_switch(wpa_s->wpa, peer, oper_class, 2829 &freq_params); 2830 if (ret) 2831 return wpas_dbus_error_unknown_error( 2832 message, "error processing TDLS channel switch"); 2833 2834 return NULL; 2835 } 2836 2837 /* 2838 * wpas_dbus_handler_tdls_cancel_channel_switch - Disable channel switching with TDLS peer 2839 * @message: Pointer to incoming dbus message 2840 * @wpa_s: wpa_supplicant structure for a network interface 2841 * Returns: NULL indicating success or DBus error message on failure 2842 * 2843 * Handler function for "TDLSCancelChannelSwitch" method call of network 2844 * interface. 2845 */ 2846 DBusMessage * 2847 wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message, 2848 struct wpa_supplicant *wpa_s) 2849 { 2850 u8 peer[ETH_ALEN]; 2851 DBusMessage *error_reply; 2852 int ret; 2853 2854 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0) 2855 return error_reply; 2856 2857 wpa_printf(MSG_DEBUG, "dbus: TDLS_CANCEL_CHAN_SWITCH " MACSTR, 2858 MAC2STR(peer)); 2859 2860 ret = wpa_tdls_disable_chan_switch(wpa_s->wpa, peer); 2861 if (ret) 2862 return wpas_dbus_error_unknown_error( 2863 message, "error canceling TDLS channel switch"); 2864 2865 return NULL; 2866 } 2867 2868 #endif /* CONFIG_TDLS */ 2869 2870 2871 #ifndef CONFIG_NO_CONFIG_WRITE 2872 /** 2873 * wpas_dbus_handler_save_config - Save configuration to configuration file 2874 * @message: Pointer to incoming dbus message 2875 * @wpa_s: wpa_supplicant structure for a network interface 2876 * Returns: NULL on Success, Otherwise error message 2877 * 2878 * Handler function for "SaveConfig" method call of network interface. 2879 */ 2880 DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message, 2881 struct wpa_supplicant *wpa_s) 2882 { 2883 int ret; 2884 2885 if (!wpa_s->conf->update_config) { 2886 return wpas_dbus_error_unknown_error( 2887 message, 2888 "Not allowed to update configuration (update_config=0)"); 2889 } 2890 2891 ret = wpa_config_write(wpa_s->confname, wpa_s->conf); 2892 if (ret) 2893 return wpas_dbus_error_unknown_error( 2894 message, "Failed to update configuration"); 2895 return NULL; 2896 } 2897 #endif /* CONFIG_NO_CONFIG_WRITE */ 2898 2899 2900 /** 2901 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path 2902 * @message: Pointer to incoming dbus message 2903 * @wpa_s: %wpa_supplicant data structure 2904 * Returns: A dbus message containing an error on failure or NULL on success 2905 * 2906 * Sets the PKCS #11 engine and module path. 2907 */ 2908 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path( 2909 DBusMessage *message, struct wpa_supplicant *wpa_s) 2910 { 2911 DBusMessageIter iter; 2912 char *value = NULL; 2913 char *pkcs11_engine_path = NULL; 2914 char *pkcs11_module_path = NULL; 2915 2916 dbus_message_iter_init(message, &iter); 2917 dbus_message_iter_get_basic(&iter, &value); 2918 if (value == NULL) { 2919 return dbus_message_new_error( 2920 message, DBUS_ERROR_INVALID_ARGS, 2921 "Invalid pkcs11_engine_path argument"); 2922 } 2923 /* Empty path defaults to NULL */ 2924 if (os_strlen(value)) 2925 pkcs11_engine_path = value; 2926 2927 dbus_message_iter_next(&iter); 2928 dbus_message_iter_get_basic(&iter, &value); 2929 if (value == NULL) { 2930 os_free(pkcs11_engine_path); 2931 return dbus_message_new_error( 2932 message, DBUS_ERROR_INVALID_ARGS, 2933 "Invalid pkcs11_module_path argument"); 2934 } 2935 /* Empty path defaults to NULL */ 2936 if (os_strlen(value)) 2937 pkcs11_module_path = value; 2938 2939 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path, 2940 pkcs11_module_path)) 2941 return dbus_message_new_error( 2942 message, DBUS_ERROR_FAILED, 2943 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed."); 2944 2945 if (wpa_s->dbus_new_path) { 2946 wpa_dbus_mark_property_changed( 2947 wpa_s->global->dbus, wpa_s->dbus_new_path, 2948 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath"); 2949 wpa_dbus_mark_property_changed( 2950 wpa_s->global->dbus, wpa_s->dbus_new_path, 2951 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath"); 2952 } 2953 2954 return NULL; 2955 } 2956 2957 2958 /** 2959 * wpas_dbus_getter_capabilities - Return interface capabilities 2960 * @iter: Pointer to incoming dbus message iter 2961 * @error: Location to store error on failure 2962 * @user_data: Function specific data 2963 * Returns: TRUE on success, FALSE on failure 2964 * 2965 * Getter for "Capabilities" property of an interface. 2966 */ 2967 dbus_bool_t wpas_dbus_getter_capabilities( 2968 const struct wpa_dbus_property_desc *property_desc, 2969 DBusMessageIter *iter, DBusError *error, void *user_data) 2970 { 2971 struct wpa_supplicant *wpa_s = user_data; 2972 struct wpa_driver_capa capa; 2973 int res; 2974 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array, 2975 variant_iter; 2976 const char *scans[] = { "active", "passive", "ssid" }; 2977 2978 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 2979 "a{sv}", &variant_iter) || 2980 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 2981 goto nomem; 2982 2983 res = wpa_drv_get_capa(wpa_s, &capa); 2984 2985 /***** pairwise cipher */ 2986 if (res < 0) { 2987 #ifdef CONFIG_NO_TKIP 2988 const char *args[] = {"ccmp", "none"}; 2989 #else /* CONFIG_NO_TKIP */ 2990 const char *args[] = {"ccmp", "tkip", "none"}; 2991 #endif /* CONFIG_NO_TKIP */ 2992 2993 if (!wpa_dbus_dict_append_string_array( 2994 &iter_dict, "Pairwise", args, 2995 ARRAY_SIZE(args))) 2996 goto nomem; 2997 } else { 2998 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise", 2999 &iter_dict_entry, 3000 &iter_dict_val, 3001 &iter_array) || 3002 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) && 3003 !wpa_dbus_dict_string_array_add_element( 3004 &iter_array, "ccmp-256")) || 3005 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) && 3006 !wpa_dbus_dict_string_array_add_element( 3007 &iter_array, "gcmp-256")) || 3008 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) && 3009 !wpa_dbus_dict_string_array_add_element( 3010 &iter_array, "ccmp")) || 3011 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) && 3012 !wpa_dbus_dict_string_array_add_element( 3013 &iter_array, "gcmp")) || 3014 #ifndef CONFIG_NO_TKIP 3015 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && 3016 !wpa_dbus_dict_string_array_add_element( 3017 &iter_array, "tkip")) || 3018 #endif /* CONFIG_NO_TKIP */ 3019 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) && 3020 !wpa_dbus_dict_string_array_add_element( 3021 &iter_array, "none")) || 3022 !wpa_dbus_dict_end_string_array(&iter_dict, 3023 &iter_dict_entry, 3024 &iter_dict_val, 3025 &iter_array)) 3026 goto nomem; 3027 } 3028 3029 /***** group cipher */ 3030 if (res < 0) { 3031 const char *args[] = { 3032 "ccmp", 3033 #ifndef CONFIG_NO_TKIP 3034 "tkip", 3035 #endif /* CONFIG_NO_TKIP */ 3036 #ifdef CONFIG_WEP 3037 "wep104", "wep40" 3038 #endif /* CONFIG_WEP */ 3039 }; 3040 3041 if (!wpa_dbus_dict_append_string_array( 3042 &iter_dict, "Group", args, 3043 ARRAY_SIZE(args))) 3044 goto nomem; 3045 } else { 3046 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group", 3047 &iter_dict_entry, 3048 &iter_dict_val, 3049 &iter_array) || 3050 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) && 3051 !wpa_dbus_dict_string_array_add_element( 3052 &iter_array, "ccmp-256")) || 3053 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) && 3054 !wpa_dbus_dict_string_array_add_element( 3055 &iter_array, "gcmp-256")) || 3056 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) && 3057 !wpa_dbus_dict_string_array_add_element( 3058 &iter_array, "ccmp")) || 3059 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) && 3060 !wpa_dbus_dict_string_array_add_element( 3061 &iter_array, "gcmp")) || 3062 #ifndef CONFIG_NO_TKIP 3063 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && 3064 !wpa_dbus_dict_string_array_add_element( 3065 &iter_array, "tkip")) || 3066 #endif /* CONFIG_NO_TKIP */ 3067 #ifdef CONFIG_WEP 3068 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) && 3069 !wpa_dbus_dict_string_array_add_element( 3070 &iter_array, "wep104")) || 3071 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) && 3072 !wpa_dbus_dict_string_array_add_element( 3073 &iter_array, "wep40")) || 3074 #endif /* CONFIG_WEP */ 3075 !wpa_dbus_dict_end_string_array(&iter_dict, 3076 &iter_dict_entry, 3077 &iter_dict_val, 3078 &iter_array)) 3079 goto nomem; 3080 } 3081 3082 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "GroupMgmt", 3083 &iter_dict_entry, 3084 &iter_dict_val, 3085 &iter_array) || 3086 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP) && 3087 !wpa_dbus_dict_string_array_add_element( 3088 &iter_array, "aes-128-cmac")) || 3089 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_128) && 3090 !wpa_dbus_dict_string_array_add_element( 3091 &iter_array, "bip-gmac-128")) || 3092 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_GMAC_256) && 3093 !wpa_dbus_dict_string_array_add_element( 3094 &iter_array, "bip-gmac-256")) || 3095 (res == 0 && (capa.enc & WPA_DRIVER_CAPA_ENC_BIP_CMAC_256) && 3096 !wpa_dbus_dict_string_array_add_element( 3097 &iter_array, "bip-cmac-256")) || 3098 !wpa_dbus_dict_end_string_array(&iter_dict, 3099 &iter_dict_entry, 3100 &iter_dict_val, 3101 &iter_array)) 3102 goto nomem; 3103 3104 /***** key management */ 3105 if (res < 0) { 3106 const char *args[] = { 3107 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none", 3108 #ifdef CONFIG_WPS 3109 "wps", 3110 #endif /* CONFIG_WPS */ 3111 "none" 3112 }; 3113 if (!wpa_dbus_dict_append_string_array( 3114 &iter_dict, "KeyMgmt", args, 3115 ARRAY_SIZE(args))) 3116 goto nomem; 3117 } else { 3118 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt", 3119 &iter_dict_entry, 3120 &iter_dict_val, 3121 &iter_array) || 3122 !wpa_dbus_dict_string_array_add_element(&iter_array, 3123 "none") || 3124 !wpa_dbus_dict_string_array_add_element(&iter_array, 3125 "ieee8021x")) 3126 goto nomem; 3127 3128 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 3129 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 3130 if (!wpa_dbus_dict_string_array_add_element( 3131 &iter_array, "wpa-eap") || 3132 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) && 3133 !wpa_dbus_dict_string_array_add_element( 3134 &iter_array, "wpa-ft-eap"))) 3135 goto nomem; 3136 3137 /* TODO: Ensure that driver actually supports sha256 encryption. */ 3138 if (!wpa_dbus_dict_string_array_add_element( 3139 &iter_array, "wpa-eap-sha256")) 3140 goto nomem; 3141 } 3142 3143 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 3144 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 3145 if (!wpa_dbus_dict_string_array_add_element( 3146 &iter_array, "wpa-psk") || 3147 ((capa.key_mgmt & 3148 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) && 3149 !wpa_dbus_dict_string_array_add_element( 3150 &iter_array, "wpa-ft-psk"))) 3151 goto nomem; 3152 3153 /* TODO: Ensure that driver actually supports sha256 encryption. */ 3154 if (!wpa_dbus_dict_string_array_add_element( 3155 &iter_array, "wpa-psk-sha256")) 3156 goto nomem; 3157 } 3158 3159 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) && 3160 !wpa_dbus_dict_string_array_add_element(&iter_array, 3161 "wpa-none")) 3162 goto nomem; 3163 3164 3165 #ifdef CONFIG_WPS 3166 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 3167 "wps")) 3168 goto nomem; 3169 #endif /* CONFIG_WPS */ 3170 3171 #ifdef CONFIG_SAE 3172 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) && 3173 !wpa_dbus_dict_string_array_add_element(&iter_array, "sae")) 3174 goto nomem; 3175 #endif /* CONFIG_SAE */ 3176 3177 #ifdef CONFIG_OWE 3178 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) && 3179 !wpa_dbus_dict_string_array_add_element(&iter_array, "owe")) 3180 goto nomem; 3181 #endif /* CONFIG_OWE */ 3182 3183 if (!wpa_dbus_dict_end_string_array(&iter_dict, 3184 &iter_dict_entry, 3185 &iter_dict_val, 3186 &iter_array)) 3187 goto nomem; 3188 } 3189 3190 /***** WPA protocol */ 3191 if (res < 0) { 3192 const char *args[] = { "rsn", "wpa" }; 3193 3194 if (!wpa_dbus_dict_append_string_array( 3195 &iter_dict, "Protocol", args, 3196 ARRAY_SIZE(args))) 3197 goto nomem; 3198 } else { 3199 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol", 3200 &iter_dict_entry, 3201 &iter_dict_val, 3202 &iter_array) || 3203 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 3204 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) && 3205 !wpa_dbus_dict_string_array_add_element( 3206 &iter_array, "rsn")) || 3207 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 3208 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) && 3209 !wpa_dbus_dict_string_array_add_element( 3210 &iter_array, "wpa")) || 3211 !wpa_dbus_dict_end_string_array(&iter_dict, 3212 &iter_dict_entry, 3213 &iter_dict_val, 3214 &iter_array)) 3215 goto nomem; 3216 } 3217 3218 /***** auth alg */ 3219 if (res < 0) { 3220 const char *args[] = { "open", "shared", "leap" }; 3221 3222 if (!wpa_dbus_dict_append_string_array( 3223 &iter_dict, "AuthAlg", args, 3224 ARRAY_SIZE(args))) 3225 goto nomem; 3226 } else { 3227 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg", 3228 &iter_dict_entry, 3229 &iter_dict_val, 3230 &iter_array)) 3231 goto nomem; 3232 3233 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) && 3234 !wpa_dbus_dict_string_array_add_element( 3235 &iter_array, "open")) || 3236 ((capa.auth & WPA_DRIVER_AUTH_SHARED) && 3237 !wpa_dbus_dict_string_array_add_element( 3238 &iter_array, "shared")) || 3239 ((capa.auth & WPA_DRIVER_AUTH_LEAP) && 3240 !wpa_dbus_dict_string_array_add_element( 3241 &iter_array, "leap")) || 3242 !wpa_dbus_dict_end_string_array(&iter_dict, 3243 &iter_dict_entry, 3244 &iter_dict_val, 3245 &iter_array)) 3246 goto nomem; 3247 } 3248 3249 /***** Scan */ 3250 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans, 3251 ARRAY_SIZE(scans))) 3252 goto nomem; 3253 3254 /***** Modes */ 3255 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes", 3256 &iter_dict_entry, 3257 &iter_dict_val, 3258 &iter_array) || 3259 !wpa_dbus_dict_string_array_add_element( 3260 &iter_array, "infrastructure") || 3261 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_IBSS) && 3262 !wpa_dbus_dict_string_array_add_element( 3263 &iter_array, "ad-hoc")) || 3264 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) && 3265 !wpa_dbus_dict_string_array_add_element( 3266 &iter_array, "ap")) || 3267 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) && 3268 !wpa_s->conf->p2p_disabled && 3269 !wpa_dbus_dict_string_array_add_element( 3270 &iter_array, "p2p")) || 3271 #ifdef CONFIG_MESH 3272 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_MESH) && 3273 !wpa_dbus_dict_string_array_add_element( 3274 &iter_array, "mesh")) || 3275 #endif /* CONFIG_MESH */ 3276 !wpa_dbus_dict_end_string_array(&iter_dict, 3277 &iter_dict_entry, 3278 &iter_dict_val, 3279 &iter_array)) 3280 goto nomem; 3281 /***** Modes end */ 3282 3283 if (res >= 0) { 3284 dbus_int32_t max_scan_ssid = capa.max_scan_ssids; 3285 3286 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID", 3287 max_scan_ssid)) 3288 goto nomem; 3289 } 3290 3291 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || 3292 !dbus_message_iter_close_container(iter, &variant_iter)) 3293 goto nomem; 3294 3295 return TRUE; 3296 3297 nomem: 3298 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3299 return FALSE; 3300 } 3301 3302 3303 /** 3304 * wpas_dbus_getter_state - Get interface state 3305 * @iter: Pointer to incoming dbus message iter 3306 * @error: Location to store error on failure 3307 * @user_data: Function specific data 3308 * Returns: TRUE on success, FALSE on failure 3309 * 3310 * Getter for "State" property. 3311 */ 3312 dbus_bool_t wpas_dbus_getter_state( 3313 const struct wpa_dbus_property_desc *property_desc, 3314 DBusMessageIter *iter, DBusError *error, void *user_data) 3315 { 3316 struct wpa_supplicant *wpa_s = user_data; 3317 const char *str_state; 3318 char *state_ls, *tmp; 3319 dbus_bool_t success = FALSE; 3320 3321 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 3322 3323 /* make state string lowercase to fit new DBus API convention 3324 */ 3325 state_ls = tmp = os_strdup(str_state); 3326 if (!tmp) { 3327 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3328 return FALSE; 3329 } 3330 while (*tmp) { 3331 *tmp = tolower(*tmp); 3332 tmp++; 3333 } 3334 3335 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3336 &state_ls, error); 3337 3338 os_free(state_ls); 3339 3340 return success; 3341 } 3342 3343 3344 /** 3345 * wpas_dbus_new_iface_get_scanning - Get interface scanning state 3346 * @iter: Pointer to incoming dbus message iter 3347 * @error: Location to store error on failure 3348 * @user_data: Function specific data 3349 * Returns: TRUE on success, FALSE on failure 3350 * 3351 * Getter for "scanning" property. 3352 */ 3353 dbus_bool_t wpas_dbus_getter_scanning( 3354 const struct wpa_dbus_property_desc *property_desc, 3355 DBusMessageIter *iter, DBusError *error, void *user_data) 3356 { 3357 struct wpa_supplicant *wpa_s = user_data; 3358 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 3359 3360 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3361 &scanning, error); 3362 } 3363 3364 3365 /** 3366 * wpas_dbus_getter_ap_scan - Control roaming mode 3367 * @iter: Pointer to incoming dbus message iter 3368 * @error: Location to store error on failure 3369 * @user_data: Function specific data 3370 * Returns: TRUE on success, FALSE on failure 3371 * 3372 * Getter function for "ApScan" property. 3373 */ 3374 dbus_bool_t wpas_dbus_getter_ap_scan( 3375 const struct wpa_dbus_property_desc *property_desc, 3376 DBusMessageIter *iter, DBusError *error, void *user_data) 3377 { 3378 struct wpa_supplicant *wpa_s = user_data; 3379 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan; 3380 3381 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 3382 &ap_scan, error); 3383 } 3384 3385 3386 /** 3387 * wpas_dbus_setter_ap_scan - Control roaming mode 3388 * @iter: Pointer to incoming dbus message iter 3389 * @error: Location to store error on failure 3390 * @user_data: Function specific data 3391 * Returns: TRUE on success, FALSE on failure 3392 * 3393 * Setter function for "ApScan" property. 3394 */ 3395 dbus_bool_t wpas_dbus_setter_ap_scan( 3396 const struct wpa_dbus_property_desc *property_desc, 3397 DBusMessageIter *iter, DBusError *error, void *user_data) 3398 { 3399 struct wpa_supplicant *wpa_s = user_data; 3400 dbus_uint32_t ap_scan; 3401 3402 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 3403 &ap_scan)) 3404 return FALSE; 3405 3406 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 3407 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3408 "ap_scan must be 0, 1, or 2"); 3409 return FALSE; 3410 } 3411 return TRUE; 3412 } 3413 3414 3415 /** 3416 * wpas_dbus_getter_fast_reauth - Control fast 3417 * reauthentication (TLS session resumption) 3418 * @iter: Pointer to incoming dbus message iter 3419 * @error: Location to store error on failure 3420 * @user_data: Function specific data 3421 * Returns: TRUE on success, FALSE on failure 3422 * 3423 * Getter function for "FastReauth" property. 3424 */ 3425 dbus_bool_t wpas_dbus_getter_fast_reauth( 3426 const struct wpa_dbus_property_desc *property_desc, 3427 DBusMessageIter *iter, DBusError *error, void *user_data) 3428 { 3429 struct wpa_supplicant *wpa_s = user_data; 3430 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE; 3431 3432 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3433 &fast_reauth, error); 3434 } 3435 3436 3437 /** 3438 * wpas_dbus_setter_fast_reauth - Control fast 3439 * reauthentication (TLS session resumption) 3440 * @iter: Pointer to incoming dbus message iter 3441 * @error: Location to store error on failure 3442 * @user_data: Function specific data 3443 * Returns: TRUE on success, FALSE on failure 3444 * 3445 * Setter function for "FastReauth" property. 3446 */ 3447 dbus_bool_t wpas_dbus_setter_fast_reauth( 3448 const struct wpa_dbus_property_desc *property_desc, 3449 DBusMessageIter *iter, DBusError *error, void *user_data) 3450 { 3451 struct wpa_supplicant *wpa_s = user_data; 3452 dbus_bool_t fast_reauth; 3453 3454 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 3455 &fast_reauth)) 3456 return FALSE; 3457 3458 wpa_s->conf->fast_reauth = fast_reauth; 3459 return TRUE; 3460 } 3461 3462 3463 /** 3464 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect 3465 * @iter: Pointer to incoming dbus message iter 3466 * @error: Location to store error on failure 3467 * @user_data: Function specific data 3468 * Returns: TRUE on success, FALSE on failure 3469 * 3470 * Getter for "DisconnectReason" property. The reason is negative if it is 3471 * locally generated. 3472 */ 3473 dbus_bool_t wpas_dbus_getter_disconnect_reason( 3474 const struct wpa_dbus_property_desc *property_desc, 3475 DBusMessageIter *iter, DBusError *error, void *user_data) 3476 { 3477 struct wpa_supplicant *wpa_s = user_data; 3478 dbus_int32_t reason = wpa_s->disconnect_reason; 3479 3480 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 3481 &reason, error); 3482 } 3483 3484 3485 /** 3486 * wpas_dbus_getter_auth_status_code - Get most recent auth status code 3487 * @iter: Pointer to incoming dbus message iter 3488 * @error: Location to store error on failure 3489 * @user_data: Function specific data 3490 * Returns: TRUE on success, FALSE on failure 3491 * 3492 * Getter for "AuthStatusCode" property. 3493 */ 3494 dbus_bool_t wpas_dbus_getter_auth_status_code( 3495 const struct wpa_dbus_property_desc *property_desc, 3496 DBusMessageIter *iter, DBusError *error, void *user_data) 3497 { 3498 struct wpa_supplicant *wpa_s = user_data; 3499 dbus_int32_t reason = wpa_s->auth_status_code; 3500 3501 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 3502 &reason, error); 3503 } 3504 3505 3506 /** 3507 * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code 3508 * @iter: Pointer to incoming dbus message iter 3509 * @error: Location to store error on failure 3510 * @user_data: Function specific data 3511 * Returns: TRUE on success, FALSE on failure 3512 * 3513 * Getter for "AssocStatusCode" property. 3514 */ 3515 dbus_bool_t wpas_dbus_getter_assoc_status_code( 3516 const struct wpa_dbus_property_desc *property_desc, 3517 DBusMessageIter *iter, DBusError *error, void *user_data) 3518 { 3519 struct wpa_supplicant *wpa_s = user_data; 3520 dbus_int32_t status_code = wpa_s->assoc_status_code; 3521 3522 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 3523 &status_code, error); 3524 } 3525 3526 3527 /** 3528 * wpas_dbus_getter_roam_time - Get most recent roam time 3529 * @iter: Pointer to incoming dbus message iter 3530 * @error: Location to store error on failure 3531 * @user_data: Function specific data 3532 * Returns: TRUE on success, FALSE on failure 3533 * 3534 * Getter for "RoamTime" property. 3535 */ 3536 dbus_bool_t wpas_dbus_getter_roam_time( 3537 const struct wpa_dbus_property_desc *property_desc, 3538 DBusMessageIter *iter, DBusError *error, void *user_data) 3539 { 3540 struct wpa_supplicant *wpa_s = user_data; 3541 dbus_uint32_t roam_time = wpa_s->roam_time.sec * 1000 + 3542 wpa_s->roam_time.usec / 1000; 3543 3544 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 3545 &roam_time, error); 3546 } 3547 3548 3549 /** 3550 * wpas_dbus_getter_roam_complete - Get most recent roam success or failure 3551 * @iter: Pointer to incoming dbus message iter 3552 * @error: Location to store error on failure 3553 * @user_data: Function specific data 3554 * Returns: TRUE on success, FALSE on failure 3555 * 3556 * Getter for "RoamComplete" property. 3557 */ 3558 dbus_bool_t wpas_dbus_getter_roam_complete( 3559 const struct wpa_dbus_property_desc *property_desc, 3560 DBusMessageIter *iter, DBusError *error, void *user_data) 3561 { 3562 struct wpa_supplicant *wpa_s = user_data; 3563 dbus_bool_t roam_complete = os_reltime_initialized(&wpa_s->roam_time); 3564 3565 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3566 &roam_complete, error); 3567 } 3568 3569 3570 /** 3571 * wpas_dbus_getter_session_length - Get most recent BSS session length 3572 * @iter: Pointer to incoming dbus message iter 3573 * @error: Location to store error on failure 3574 * @user_data: Function specific data 3575 * Returns: TRUE on success, FALSE on failure 3576 * 3577 * Getter for "SessionLength" property. 3578 */ 3579 dbus_bool_t wpas_dbus_getter_session_length( 3580 const struct wpa_dbus_property_desc *property_desc, 3581 DBusMessageIter *iter, DBusError *error, void *user_data) 3582 { 3583 struct wpa_supplicant *wpa_s = user_data; 3584 dbus_uint32_t session_length = wpa_s->session_length.sec * 1000 + 3585 wpa_s->session_length.usec / 1000; 3586 3587 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 3588 &session_length, error); 3589 } 3590 3591 3592 /** 3593 * wpas_dbus_getter_bss_tm_status - Get most BSS Transition Management request 3594 * status code 3595 * @iter: Pointer to incoming dbus message iter 3596 * @error: Location to store error on failure 3597 * @user_data: Function specific data 3598 * Returns: TRUE on success, FALSE on failure 3599 * 3600 * Getter for "BSSTMStatus" property. 3601 */ 3602 dbus_bool_t wpas_dbus_getter_bss_tm_status( 3603 const struct wpa_dbus_property_desc *property_desc, 3604 DBusMessageIter *iter, DBusError *error, void *user_data) 3605 { 3606 #ifdef CONFIG_WNM 3607 struct wpa_supplicant *wpa_s = user_data; 3608 dbus_uint32_t bss_tm_status = wpa_s->bss_tm_status; 3609 #else /* CONFIG_WNM */ 3610 dbus_uint32_t bss_tm_status = 0; 3611 #endif /* CONFIG_WNM */ 3612 3613 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 3614 &bss_tm_status, error); 3615 } 3616 3617 3618 /** 3619 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age 3620 * @iter: Pointer to incoming dbus message iter 3621 * @error: Location to store error on failure 3622 * @user_data: Function specific data 3623 * Returns: TRUE on success, FALSE on failure 3624 * 3625 * Getter function for "BSSExpireAge" property. 3626 */ 3627 dbus_bool_t wpas_dbus_getter_bss_expire_age( 3628 const struct wpa_dbus_property_desc *property_desc, 3629 DBusMessageIter *iter, DBusError *error, void *user_data) 3630 { 3631 struct wpa_supplicant *wpa_s = user_data; 3632 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age; 3633 3634 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 3635 &expire_age, error); 3636 } 3637 3638 3639 /** 3640 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age 3641 * @iter: Pointer to incoming dbus message iter 3642 * @error: Location to store error on failure 3643 * @user_data: Function specific data 3644 * Returns: TRUE on success, FALSE on failure 3645 * 3646 * Setter function for "BSSExpireAge" property. 3647 */ 3648 dbus_bool_t wpas_dbus_setter_bss_expire_age( 3649 const struct wpa_dbus_property_desc *property_desc, 3650 DBusMessageIter *iter, DBusError *error, void *user_data) 3651 { 3652 struct wpa_supplicant *wpa_s = user_data; 3653 dbus_uint32_t expire_age; 3654 3655 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 3656 &expire_age)) 3657 return FALSE; 3658 3659 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) { 3660 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3661 "BSSExpireAge must be >= 10"); 3662 return FALSE; 3663 } 3664 return TRUE; 3665 } 3666 3667 3668 /** 3669 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count 3670 * @iter: Pointer to incoming dbus message iter 3671 * @error: Location to store error on failure 3672 * @user_data: Function specific data 3673 * Returns: TRUE on success, FALSE on failure 3674 * 3675 * Getter function for "BSSExpireCount" property. 3676 */ 3677 dbus_bool_t wpas_dbus_getter_bss_expire_count( 3678 const struct wpa_dbus_property_desc *property_desc, 3679 DBusMessageIter *iter, DBusError *error, void *user_data) 3680 { 3681 struct wpa_supplicant *wpa_s = user_data; 3682 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count; 3683 3684 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 3685 &expire_count, error); 3686 } 3687 3688 3689 /** 3690 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count 3691 * @iter: Pointer to incoming dbus message iter 3692 * @error: Location to store error on failure 3693 * @user_data: Function specific data 3694 * Returns: TRUE on success, FALSE on failure 3695 * 3696 * Setter function for "BSSExpireCount" property. 3697 */ 3698 dbus_bool_t wpas_dbus_setter_bss_expire_count( 3699 const struct wpa_dbus_property_desc *property_desc, 3700 DBusMessageIter *iter, DBusError *error, void *user_data) 3701 { 3702 struct wpa_supplicant *wpa_s = user_data; 3703 dbus_uint32_t expire_count; 3704 3705 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 3706 &expire_count)) 3707 return FALSE; 3708 3709 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) { 3710 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3711 "BSSExpireCount must be > 0"); 3712 return FALSE; 3713 } 3714 return TRUE; 3715 } 3716 3717 3718 /** 3719 * wpas_dbus_getter_country - Control country code 3720 * @iter: Pointer to incoming dbus message iter 3721 * @error: Location to store error on failure 3722 * @user_data: Function specific data 3723 * Returns: TRUE on success, FALSE on failure 3724 * 3725 * Getter function for "Country" property. 3726 */ 3727 dbus_bool_t wpas_dbus_getter_country( 3728 const struct wpa_dbus_property_desc *property_desc, 3729 DBusMessageIter *iter, DBusError *error, void *user_data) 3730 { 3731 struct wpa_supplicant *wpa_s = user_data; 3732 char country[3]; 3733 char *str = country; 3734 3735 country[0] = wpa_s->conf->country[0]; 3736 country[1] = wpa_s->conf->country[1]; 3737 country[2] = '\0'; 3738 3739 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3740 &str, error); 3741 } 3742 3743 3744 /** 3745 * wpas_dbus_setter_country - Control country code 3746 * @iter: Pointer to incoming dbus message iter 3747 * @error: Location to store error on failure 3748 * @user_data: Function specific data 3749 * Returns: TRUE on success, FALSE on failure 3750 * 3751 * Setter function for "Country" property. 3752 */ 3753 dbus_bool_t wpas_dbus_setter_country( 3754 const struct wpa_dbus_property_desc *property_desc, 3755 DBusMessageIter *iter, DBusError *error, void *user_data) 3756 { 3757 struct wpa_supplicant *wpa_s = user_data; 3758 const char *country; 3759 3760 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, 3761 &country)) 3762 return FALSE; 3763 3764 if (!country[0] || !country[1]) { 3765 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3766 "invalid country code"); 3767 return FALSE; 3768 } 3769 3770 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) { 3771 wpa_printf(MSG_DEBUG, "Failed to set country"); 3772 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3773 "failed to set country code"); 3774 return FALSE; 3775 } 3776 3777 wpa_s->conf->country[0] = country[0]; 3778 wpa_s->conf->country[1] = country[1]; 3779 return TRUE; 3780 } 3781 3782 3783 /** 3784 * wpas_dbus_getter_scan_interval - Get scan interval 3785 * @iter: Pointer to incoming dbus message iter 3786 * @error: Location to store error on failure 3787 * @user_data: Function specific data 3788 * Returns: TRUE on success, FALSE on failure 3789 * 3790 * Getter function for "ScanInterval" property. 3791 */ 3792 dbus_bool_t wpas_dbus_getter_scan_interval( 3793 const struct wpa_dbus_property_desc *property_desc, 3794 DBusMessageIter *iter, DBusError *error, void *user_data) 3795 { 3796 struct wpa_supplicant *wpa_s = user_data; 3797 dbus_int32_t scan_interval = wpa_s->scan_interval; 3798 3799 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 3800 &scan_interval, error); 3801 } 3802 3803 3804 /** 3805 * wpas_dbus_setter_scan_interval - Control scan interval 3806 * @iter: Pointer to incoming dbus message iter 3807 * @error: Location to store error on failure 3808 * @user_data: Function specific data 3809 * Returns: TRUE on success, FALSE on failure 3810 * 3811 * Setter function for "ScanInterval" property. 3812 */ 3813 dbus_bool_t wpas_dbus_setter_scan_interval( 3814 const struct wpa_dbus_property_desc *property_desc, 3815 DBusMessageIter *iter, DBusError *error, void *user_data) 3816 { 3817 struct wpa_supplicant *wpa_s = user_data; 3818 dbus_int32_t scan_interval; 3819 3820 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32, 3821 &scan_interval)) 3822 return FALSE; 3823 3824 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) { 3825 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3826 "scan_interval must be >= 0"); 3827 return FALSE; 3828 } 3829 return TRUE; 3830 } 3831 3832 3833 /** 3834 * wpas_dbus_getter_ifname - Get interface name 3835 * @iter: Pointer to incoming dbus message iter 3836 * @error: Location to store error on failure 3837 * @user_data: Function specific data 3838 * Returns: TRUE on success, FALSE on failure 3839 * 3840 * Getter for "Ifname" property. 3841 */ 3842 dbus_bool_t wpas_dbus_getter_ifname( 3843 const struct wpa_dbus_property_desc *property_desc, 3844 DBusMessageIter *iter, DBusError *error, void *user_data) 3845 { 3846 struct wpa_supplicant *wpa_s = user_data; 3847 3848 return wpas_dbus_string_property_getter(iter, wpa_s->ifname, error); 3849 } 3850 3851 3852 /** 3853 * wpas_dbus_getter_driver - Get interface name 3854 * @iter: Pointer to incoming dbus message iter 3855 * @error: Location to store error on failure 3856 * @user_data: Function specific data 3857 * Returns: TRUE on success, FALSE on failure 3858 * 3859 * Getter for "Driver" property. 3860 */ 3861 dbus_bool_t wpas_dbus_getter_driver( 3862 const struct wpa_dbus_property_desc *property_desc, 3863 DBusMessageIter *iter, DBusError *error, void *user_data) 3864 { 3865 struct wpa_supplicant *wpa_s = user_data; 3866 3867 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) { 3868 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set", 3869 __func__); 3870 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set", 3871 __func__); 3872 return FALSE; 3873 } 3874 3875 return wpas_dbus_string_property_getter(iter, wpa_s->driver->name, 3876 error); 3877 } 3878 3879 3880 /** 3881 * wpas_dbus_getter_current_bss - Get current bss object path 3882 * @iter: Pointer to incoming dbus message iter 3883 * @error: Location to store error on failure 3884 * @user_data: Function specific data 3885 * Returns: TRUE on success, FALSE on failure 3886 * 3887 * Getter for "CurrentBSS" property. 3888 */ 3889 dbus_bool_t wpas_dbus_getter_current_bss( 3890 const struct wpa_dbus_property_desc *property_desc, 3891 DBusMessageIter *iter, DBusError *error, void *user_data) 3892 { 3893 struct wpa_supplicant *wpa_s = user_data; 3894 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf; 3895 3896 if (wpa_s->current_bss && wpa_s->dbus_new_path) 3897 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3898 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 3899 wpa_s->dbus_new_path, wpa_s->current_bss->id); 3900 else 3901 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 3902 3903 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 3904 &bss_obj_path, error); 3905 } 3906 3907 3908 /** 3909 * wpas_dbus_getter_current_network - Get current network object path 3910 * @iter: Pointer to incoming dbus message iter 3911 * @error: Location to store error on failure 3912 * @user_data: Function specific data 3913 * Returns: TRUE on success, FALSE on failure 3914 * 3915 * Getter for "CurrentNetwork" property. 3916 */ 3917 dbus_bool_t wpas_dbus_getter_current_network( 3918 const struct wpa_dbus_property_desc *property_desc, 3919 DBusMessageIter *iter, DBusError *error, void *user_data) 3920 { 3921 struct wpa_supplicant *wpa_s = user_data; 3922 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf; 3923 3924 if (wpa_s->current_ssid && wpa_s->dbus_new_path) 3925 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3926 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 3927 wpa_s->dbus_new_path, wpa_s->current_ssid->id); 3928 else 3929 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 3930 3931 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 3932 &net_obj_path, error); 3933 } 3934 3935 3936 /** 3937 * wpas_dbus_getter_current_auth_mode - Get current authentication type 3938 * @iter: Pointer to incoming dbus message iter 3939 * @error: Location to store error on failure 3940 * @user_data: Function specific data 3941 * Returns: TRUE on success, FALSE on failure 3942 * 3943 * Getter for "CurrentAuthMode" property. 3944 */ 3945 dbus_bool_t wpas_dbus_getter_current_auth_mode( 3946 const struct wpa_dbus_property_desc *property_desc, 3947 DBusMessageIter *iter, DBusError *error, void *user_data) 3948 { 3949 struct wpa_supplicant *wpa_s = user_data; 3950 const char *eap_mode; 3951 const char *auth_mode; 3952 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX]; 3953 3954 if (wpa_s->wpa_state != WPA_COMPLETED) { 3955 auth_mode = "INACTIVE"; 3956 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || 3957 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 3958 eap_mode = wpa_supplicant_get_eap_mode(wpa_s); 3959 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX, 3960 "EAP-%s", eap_mode); 3961 auth_mode = eap_mode_buf; 3962 3963 } else if (wpa_s->current_ssid) { 3964 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt, 3965 wpa_s->current_ssid->proto); 3966 } else { 3967 auth_mode = "UNKNOWN"; 3968 } 3969 3970 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3971 &auth_mode, error); 3972 } 3973 3974 3975 /** 3976 * wpas_dbus_getter_bridge_ifname - Get interface name 3977 * @iter: Pointer to incoming dbus message iter 3978 * @error: Location to store error on failure 3979 * @user_data: Function specific data 3980 * Returns: TRUE on success, FALSE on failure 3981 * 3982 * Getter for "BridgeIfname" property. 3983 */ 3984 dbus_bool_t wpas_dbus_getter_bridge_ifname( 3985 const struct wpa_dbus_property_desc *property_desc, 3986 DBusMessageIter *iter, DBusError *error, void *user_data) 3987 { 3988 struct wpa_supplicant *wpa_s = user_data; 3989 3990 return wpas_dbus_string_property_getter(iter, wpa_s->bridge_ifname, 3991 error); 3992 } 3993 3994 3995 dbus_bool_t wpas_dbus_setter_bridge_ifname( 3996 const struct wpa_dbus_property_desc *property_desc, 3997 DBusMessageIter *iter, DBusError *error, void *user_data) 3998 { 3999 struct wpa_supplicant *wpa_s = user_data; 4000 const char *bridge_ifname = NULL; 4001 const char *msg; 4002 int r; 4003 4004 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, 4005 &bridge_ifname)) 4006 return FALSE; 4007 4008 r = wpa_supplicant_update_bridge_ifname(wpa_s, bridge_ifname); 4009 if (r != 0) { 4010 switch (r) { 4011 case -EINVAL: 4012 msg = "invalid interface name"; 4013 break; 4014 case -EBUSY: 4015 msg = "interface is busy"; 4016 break; 4017 case -EIO: 4018 msg = "socket error"; 4019 break; 4020 default: 4021 msg = "unknown error"; 4022 break; 4023 } 4024 dbus_set_error_const(error, DBUS_ERROR_FAILED, msg); 4025 return FALSE; 4026 } 4027 4028 return TRUE; 4029 } 4030 4031 4032 /** 4033 * wpas_dbus_getter_config_file - Get interface configuration file path 4034 * @iter: Pointer to incoming dbus message iter 4035 * @error: Location to store error on failure 4036 * @user_data: Function specific data 4037 * Returns: TRUE on success, FALSE on failure 4038 * 4039 * Getter for "ConfigFile" property. 4040 */ 4041 dbus_bool_t wpas_dbus_getter_config_file( 4042 const struct wpa_dbus_property_desc *property_desc, 4043 DBusMessageIter *iter, DBusError *error, void *user_data) 4044 { 4045 struct wpa_supplicant *wpa_s = user_data; 4046 4047 return wpas_dbus_string_property_getter(iter, wpa_s->confname, error); 4048 } 4049 4050 4051 /** 4052 * wpas_dbus_getter_bsss - Get array of BSSs objects 4053 * @iter: Pointer to incoming dbus message iter 4054 * @error: Location to store error on failure 4055 * @user_data: Function specific data 4056 * Returns: TRUE on success, FALSE on failure 4057 * 4058 * Getter for "BSSs" property. 4059 */ 4060 dbus_bool_t wpas_dbus_getter_bsss( 4061 const struct wpa_dbus_property_desc *property_desc, 4062 DBusMessageIter *iter, DBusError *error, void *user_data) 4063 { 4064 struct wpa_supplicant *wpa_s = user_data; 4065 struct wpa_bss *bss; 4066 char **paths; 4067 unsigned int i = 0; 4068 dbus_bool_t success = FALSE; 4069 4070 if (!wpa_s->dbus_new_path) { 4071 dbus_set_error(error, DBUS_ERROR_FAILED, 4072 "%s: no D-Bus interface", __func__); 4073 return FALSE; 4074 } 4075 4076 paths = os_calloc(wpa_s->num_bss, sizeof(char *)); 4077 if (!paths) { 4078 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4079 return FALSE; 4080 } 4081 4082 /* Loop through scan results and append each result's object path */ 4083 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 4084 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 4085 if (paths[i] == NULL) { 4086 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 4087 "no memory"); 4088 goto out; 4089 } 4090 /* Construct the object path for this BSS. */ 4091 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 4092 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 4093 wpa_s->dbus_new_path, bss->id); 4094 } 4095 4096 success = wpas_dbus_simple_array_property_getter(iter, 4097 DBUS_TYPE_OBJECT_PATH, 4098 paths, wpa_s->num_bss, 4099 error); 4100 4101 out: 4102 while (i) 4103 os_free(paths[--i]); 4104 os_free(paths); 4105 return success; 4106 } 4107 4108 4109 /** 4110 * wpas_dbus_getter_networks - Get array of networks objects 4111 * @iter: Pointer to incoming dbus message iter 4112 * @error: Location to store error on failure 4113 * @user_data: Function specific data 4114 * Returns: TRUE on success, FALSE on failure 4115 * 4116 * Getter for "Networks" property. 4117 */ 4118 dbus_bool_t wpas_dbus_getter_networks( 4119 const struct wpa_dbus_property_desc *property_desc, 4120 DBusMessageIter *iter, DBusError *error, void *user_data) 4121 { 4122 struct wpa_supplicant *wpa_s = user_data; 4123 struct wpa_ssid *ssid; 4124 char **paths; 4125 unsigned int i = 0, num = 0; 4126 dbus_bool_t success = FALSE; 4127 4128 if (!wpa_s->dbus_new_path) { 4129 dbus_set_error(error, DBUS_ERROR_FAILED, 4130 "%s: no D-Bus interface", __func__); 4131 return FALSE; 4132 } 4133 4134 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 4135 if (!network_is_persistent_group(ssid)) 4136 num++; 4137 4138 paths = os_calloc(num, sizeof(char *)); 4139 if (!paths) { 4140 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4141 return FALSE; 4142 } 4143 4144 /* Loop through configured networks and append object path of each */ 4145 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 4146 if (network_is_persistent_group(ssid)) 4147 continue; 4148 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 4149 if (paths[i] == NULL) { 4150 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, 4151 "no memory"); 4152 goto out; 4153 } 4154 4155 /* Construct the object path for this network. */ 4156 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 4157 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 4158 wpa_s->dbus_new_path, ssid->id); 4159 } 4160 4161 success = wpas_dbus_simple_array_property_getter(iter, 4162 DBUS_TYPE_OBJECT_PATH, 4163 paths, num, error); 4164 4165 out: 4166 while (i) 4167 os_free(paths[--i]); 4168 os_free(paths); 4169 return success; 4170 } 4171 4172 4173 /** 4174 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path 4175 * @iter: Pointer to incoming dbus message iter 4176 * @error: Location to store error on failure 4177 * @user_data: Function specific data 4178 * Returns: A dbus message containing the PKCS #11 engine path 4179 * 4180 * Getter for "PKCS11EnginePath" property. 4181 */ 4182 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path( 4183 const struct wpa_dbus_property_desc *property_desc, 4184 DBusMessageIter *iter, DBusError *error, void *user_data) 4185 { 4186 struct wpa_supplicant *wpa_s = user_data; 4187 4188 return wpas_dbus_string_property_getter(iter, 4189 wpa_s->conf->pkcs11_engine_path, 4190 error); 4191 } 4192 4193 4194 /** 4195 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path 4196 * @iter: Pointer to incoming dbus message iter 4197 * @error: Location to store error on failure 4198 * @user_data: Function specific data 4199 * Returns: A dbus message containing the PKCS #11 module path 4200 * 4201 * Getter for "PKCS11ModulePath" property. 4202 */ 4203 dbus_bool_t wpas_dbus_getter_pkcs11_module_path( 4204 const struct wpa_dbus_property_desc *property_desc, 4205 DBusMessageIter *iter, DBusError *error, void *user_data) 4206 { 4207 struct wpa_supplicant *wpa_s = user_data; 4208 4209 return wpas_dbus_string_property_getter(iter, 4210 wpa_s->conf->pkcs11_module_path, 4211 error); 4212 } 4213 4214 4215 /** 4216 * wpas_dbus_getter_blobs - Get all blobs defined for this interface 4217 * @iter: Pointer to incoming dbus message iter 4218 * @error: Location to store error on failure 4219 * @user_data: Function specific data 4220 * Returns: TRUE on success, FALSE on failure 4221 * 4222 * Getter for "Blobs" property. 4223 */ 4224 dbus_bool_t wpas_dbus_getter_blobs( 4225 const struct wpa_dbus_property_desc *property_desc, 4226 DBusMessageIter *iter, DBusError *error, void *user_data) 4227 { 4228 struct wpa_supplicant *wpa_s = user_data; 4229 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter; 4230 struct wpa_config_blob *blob; 4231 4232 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 4233 "a{say}", &variant_iter) || 4234 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 4235 "{say}", &dict_iter)) { 4236 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4237 return FALSE; 4238 } 4239 4240 blob = wpa_s->conf->blobs; 4241 while (blob) { 4242 if (!dbus_message_iter_open_container(&dict_iter, 4243 DBUS_TYPE_DICT_ENTRY, 4244 NULL, &entry_iter) || 4245 !dbus_message_iter_append_basic(&entry_iter, 4246 DBUS_TYPE_STRING, 4247 &(blob->name)) || 4248 !dbus_message_iter_open_container(&entry_iter, 4249 DBUS_TYPE_ARRAY, 4250 DBUS_TYPE_BYTE_AS_STRING, 4251 &array_iter) || 4252 !dbus_message_iter_append_fixed_array(&array_iter, 4253 DBUS_TYPE_BYTE, 4254 &(blob->data), 4255 blob->len) || 4256 !dbus_message_iter_close_container(&entry_iter, 4257 &array_iter) || 4258 !dbus_message_iter_close_container(&dict_iter, 4259 &entry_iter)) { 4260 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 4261 "no memory"); 4262 return FALSE; 4263 } 4264 4265 blob = blob->next; 4266 } 4267 4268 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) || 4269 !dbus_message_iter_close_container(iter, &variant_iter)) { 4270 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4271 return FALSE; 4272 } 4273 4274 return TRUE; 4275 } 4276 4277 4278 dbus_bool_t wpas_dbus_getter_iface_global( 4279 const struct wpa_dbus_property_desc *property_desc, 4280 DBusMessageIter *iter, DBusError *error, void *user_data) 4281 { 4282 struct wpa_supplicant *wpa_s = user_data; 4283 int ret; 4284 char buf[250]; 4285 char *p = buf; 4286 4287 if (!property_desc->data) { 4288 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, 4289 "Unhandled interface property %s", 4290 property_desc->dbus_property); 4291 return FALSE; 4292 } 4293 4294 ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf, 4295 sizeof(buf)); 4296 if (ret < 0) 4297 *p = '\0'; 4298 4299 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p, 4300 error); 4301 } 4302 4303 4304 dbus_bool_t wpas_dbus_setter_iface_global( 4305 const struct wpa_dbus_property_desc *property_desc, 4306 DBusMessageIter *iter, DBusError *error, void *user_data) 4307 { 4308 struct wpa_supplicant *wpa_s = user_data; 4309 const char *new_value = NULL; 4310 char buf[250]; 4311 size_t combined_len; 4312 int ret; 4313 4314 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, 4315 &new_value)) 4316 return FALSE; 4317 4318 combined_len = os_strlen(property_desc->data) + os_strlen(new_value) + 4319 3; 4320 if (combined_len >= sizeof(buf)) { 4321 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, 4322 "Interface property %s value too large", 4323 property_desc->dbus_property); 4324 return FALSE; 4325 } 4326 4327 if (!new_value[0]) 4328 new_value = "NULL"; 4329 4330 ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data, 4331 new_value); 4332 if (os_snprintf_error(combined_len, ret)) { 4333 dbus_set_error(error, WPAS_DBUS_ERROR_UNKNOWN_ERROR, 4334 "Failed to construct new interface property %s", 4335 property_desc->dbus_property); 4336 return FALSE; 4337 } 4338 4339 ret = wpa_config_process_global(wpa_s->conf, buf, -1); 4340 if (ret < 0) { 4341 dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, 4342 "Failed to set interface property %s", 4343 property_desc->dbus_property); 4344 return FALSE; 4345 } else if (ret == 0) { 4346 wpa_supplicant_update_config(wpa_s); 4347 } 4348 return TRUE; 4349 } 4350 4351 4352 /** 4353 * wpas_dbus_getter_stas - Get connected stations for an interface 4354 * @iter: Pointer to incoming dbus message iter 4355 * @error: Location to store error on failure 4356 * @user_data: Function specific data 4357 * Returns: a list of stations 4358 * 4359 * Getter for "Stations" property. 4360 */ 4361 dbus_bool_t wpas_dbus_getter_stas( 4362 const struct wpa_dbus_property_desc *property_desc, 4363 DBusMessageIter *iter, DBusError *error, void *user_data) 4364 { 4365 struct wpa_supplicant *wpa_s = user_data; 4366 struct sta_info *sta = NULL; 4367 char **paths = NULL; 4368 unsigned int i = 0, num = 0; 4369 dbus_bool_t success = FALSE; 4370 4371 if (!wpa_s->dbus_new_path) { 4372 dbus_set_error(error, DBUS_ERROR_FAILED, 4373 "%s: no D-Bus interface", __func__); 4374 return FALSE; 4375 } 4376 4377 #ifdef CONFIG_AP 4378 if (wpa_s->ap_iface) { 4379 struct hostapd_data *hapd; 4380 4381 hapd = wpa_s->ap_iface->bss[0]; 4382 sta = hapd->sta_list; 4383 num = hapd->num_sta; 4384 } 4385 #endif /* CONFIG_AP */ 4386 4387 paths = os_calloc(num, sizeof(char *)); 4388 if (!paths) { 4389 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4390 return FALSE; 4391 } 4392 4393 /* Loop through scan results and append each result's object path */ 4394 for (; sta; sta = sta->next) { 4395 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 4396 if (!paths[i]) { 4397 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 4398 "no memory"); 4399 goto out; 4400 } 4401 /* Construct the object path for this BSS. */ 4402 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 4403 "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR, 4404 wpa_s->dbus_new_path, MAC2STR(sta->addr)); 4405 } 4406 4407 success = wpas_dbus_simple_array_property_getter(iter, 4408 DBUS_TYPE_OBJECT_PATH, 4409 paths, num, 4410 error); 4411 4412 out: 4413 while (i) 4414 os_free(paths[--i]); 4415 os_free(paths); 4416 return success; 4417 } 4418 4419 4420 /** 4421 * wpas_dbus_setter_mac_address_randomization_mask - Set masks used for 4422 * MAC address randomization 4423 * @iter: Pointer to incoming dbus message iter 4424 * @error: Location to store error on failure 4425 * @user_data: Function specific data 4426 * Returns: TRUE on success, FALSE on failure 4427 * 4428 * Setter for "MACAddressRandomizationMask" property. 4429 */ 4430 dbus_bool_t wpas_dbus_setter_mac_address_randomization_mask( 4431 const struct wpa_dbus_property_desc *property_desc, 4432 DBusMessageIter *iter, DBusError *error, void *user_data) 4433 { 4434 struct wpa_supplicant *wpa_s = user_data; 4435 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter; 4436 const char *key; 4437 unsigned int rand_type = 0; 4438 const u8 *mask; 4439 int mask_len; 4440 unsigned int rand_types_to_disable = MAC_ADDR_RAND_ALL; 4441 4442 dbus_message_iter_recurse(iter, &variant_iter); 4443 if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY) { 4444 dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, 4445 "invalid message format"); 4446 return FALSE; 4447 } 4448 dbus_message_iter_recurse(&variant_iter, &dict_iter); 4449 while (dbus_message_iter_get_arg_type(&dict_iter) == 4450 DBUS_TYPE_DICT_ENTRY) { 4451 dbus_message_iter_recurse(&dict_iter, &entry_iter); 4452 if (dbus_message_iter_get_arg_type(&entry_iter) != 4453 DBUS_TYPE_STRING) { 4454 dbus_set_error(error, DBUS_ERROR_FAILED, 4455 "%s: key not a string", __func__); 4456 return FALSE; 4457 } 4458 dbus_message_iter_get_basic(&entry_iter, &key); 4459 dbus_message_iter_next(&entry_iter); 4460 if (dbus_message_iter_get_arg_type(&entry_iter) != 4461 DBUS_TYPE_ARRAY || 4462 dbus_message_iter_get_element_type(&entry_iter) != 4463 DBUS_TYPE_BYTE) { 4464 dbus_set_error(error, DBUS_ERROR_FAILED, 4465 "%s: mask was not a byte array", 4466 __func__); 4467 return FALSE; 4468 } 4469 dbus_message_iter_recurse(&entry_iter, &array_iter); 4470 dbus_message_iter_get_fixed_array(&array_iter, &mask, 4471 &mask_len); 4472 4473 if (os_strcmp(key, "scan") == 0) { 4474 rand_type = MAC_ADDR_RAND_SCAN; 4475 } else if (os_strcmp(key, "sched_scan") == 0) { 4476 rand_type = MAC_ADDR_RAND_SCHED_SCAN; 4477 } else if (os_strcmp(key, "pno") == 0) { 4478 rand_type = MAC_ADDR_RAND_PNO; 4479 } else { 4480 dbus_set_error(error, DBUS_ERROR_FAILED, 4481 "%s: bad scan type \"%s\"", 4482 __func__, key); 4483 return FALSE; 4484 } 4485 4486 if (mask_len != ETH_ALEN) { 4487 dbus_set_error(error, DBUS_ERROR_FAILED, 4488 "%s: malformed MAC mask given", 4489 __func__); 4490 return FALSE; 4491 } 4492 4493 if (wpas_enable_mac_addr_randomization( 4494 wpa_s, rand_type, wpa_s->perm_addr, mask)) { 4495 dbus_set_error(error, DBUS_ERROR_FAILED, 4496 "%s: failed to set up MAC address randomization for %s", 4497 __func__, key); 4498 return FALSE; 4499 } 4500 4501 wpa_printf(MSG_DEBUG, 4502 "%s: Enabled MAC address randomization for %s with mask: " 4503 MACSTR, wpa_s->ifname, key, MAC2STR(mask)); 4504 rand_types_to_disable &= ~rand_type; 4505 dbus_message_iter_next(&dict_iter); 4506 } 4507 4508 if (rand_types_to_disable && 4509 wpas_disable_mac_addr_randomization(wpa_s, rand_types_to_disable)) { 4510 dbus_set_error(error, DBUS_ERROR_FAILED, 4511 "%s: failed to disable MAC address randomization", 4512 __func__); 4513 return FALSE; 4514 } 4515 4516 return TRUE; 4517 } 4518 4519 4520 dbus_bool_t wpas_dbus_getter_mac_address_randomization_mask( 4521 const struct wpa_dbus_property_desc *property_desc, 4522 DBusMessageIter *iter, DBusError *error, void *user_data) 4523 { 4524 struct wpa_supplicant *wpa_s = user_data; 4525 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter; 4526 unsigned int i; 4527 u8 mask_buf[ETH_ALEN]; 4528 /* Read docs on dbus_message_iter_append_fixed_array() for why this 4529 * is necessary... */ 4530 u8 *mask = mask_buf; 4531 static const struct { 4532 const char *key; 4533 unsigned int type; 4534 } types[] = { 4535 { "scan", MAC_ADDR_RAND_SCAN }, 4536 { "sched_scan", MAC_ADDR_RAND_SCHED_SCAN }, 4537 { "pno", MAC_ADDR_RAND_PNO } 4538 }; 4539 4540 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 4541 "a{say}", &variant_iter) || 4542 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 4543 "{say}", &dict_iter)) { 4544 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4545 return FALSE; 4546 } 4547 4548 for (i = 0; i < ARRAY_SIZE(types); i++) { 4549 if (wpas_mac_addr_rand_scan_get_mask(wpa_s, types[i].type, 4550 mask)) 4551 continue; 4552 4553 if (!dbus_message_iter_open_container(&dict_iter, 4554 DBUS_TYPE_DICT_ENTRY, 4555 NULL, &entry_iter) || 4556 !dbus_message_iter_append_basic(&entry_iter, 4557 DBUS_TYPE_STRING, 4558 &types[i].key) || 4559 !dbus_message_iter_open_container(&entry_iter, 4560 DBUS_TYPE_ARRAY, 4561 DBUS_TYPE_BYTE_AS_STRING, 4562 &array_iter) || 4563 !dbus_message_iter_append_fixed_array(&array_iter, 4564 DBUS_TYPE_BYTE, 4565 &mask, 4566 ETH_ALEN) || 4567 !dbus_message_iter_close_container(&entry_iter, 4568 &array_iter) || 4569 !dbus_message_iter_close_container(&dict_iter, 4570 &entry_iter)) { 4571 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 4572 "no memory"); 4573 return FALSE; 4574 } 4575 } 4576 4577 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) || 4578 !dbus_message_iter_close_container(iter, &variant_iter)) { 4579 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4580 return FALSE; 4581 } 4582 4583 return TRUE; 4584 } 4585 4586 4587 /** 4588 * wpas_dbus_getter_sta_address - Return the address of a connected station 4589 * @iter: Pointer to incoming dbus message iter 4590 * @error: Location to store error on failure 4591 * @user_data: Function specific data 4592 * Returns: TRUE on success, FALSE on failure 4593 * 4594 * Getter for "Address" property. 4595 */ 4596 dbus_bool_t wpas_dbus_getter_sta_address( 4597 const struct wpa_dbus_property_desc *property_desc, 4598 DBusMessageIter *iter, DBusError *error, void *user_data) 4599 { 4600 #ifdef CONFIG_AP 4601 struct sta_handler_args *args = user_data; 4602 struct sta_info *sta; 4603 4604 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta); 4605 if (!sta) 4606 return FALSE; 4607 4608 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 4609 sta->addr, ETH_ALEN, 4610 error); 4611 #else /* CONFIG_AP */ 4612 return FALSE; 4613 #endif /* CONFIG_AP */ 4614 } 4615 4616 4617 /** 4618 * wpas_dbus_getter_sta_aid - Return the AID of a connected station 4619 * @iter: Pointer to incoming dbus message iter 4620 * @error: Location to store error on failure 4621 * @user_data: Function specific data 4622 * Returns: TRUE on success, FALSE on failure 4623 * 4624 * Getter for "AID" property. 4625 */ 4626 dbus_bool_t wpas_dbus_getter_sta_aid( 4627 const struct wpa_dbus_property_desc *property_desc, 4628 DBusMessageIter *iter, DBusError *error, void *user_data) 4629 { 4630 #ifdef CONFIG_AP 4631 struct sta_handler_args *args = user_data; 4632 struct sta_info *sta; 4633 4634 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta); 4635 if (!sta) 4636 return FALSE; 4637 4638 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 4639 &sta->aid, 4640 error); 4641 #else /* CONFIG_AP */ 4642 return FALSE; 4643 #endif /* CONFIG_AP */ 4644 } 4645 4646 4647 /** 4648 * wpas_dbus_getter_sta_caps - Return the capabilities of a station 4649 * @iter: Pointer to incoming dbus message iter 4650 * @error: Location to store error on failure 4651 * @user_data: Function specific data 4652 * Returns: TRUE on success, FALSE on failure 4653 * 4654 * Getter for "Capabilities" property. 4655 */ 4656 dbus_bool_t wpas_dbus_getter_sta_caps( 4657 const struct wpa_dbus_property_desc *property_desc, 4658 DBusMessageIter *iter, DBusError *error, void *user_data) 4659 { 4660 #ifdef CONFIG_AP 4661 struct sta_handler_args *args = user_data; 4662 struct sta_info *sta; 4663 4664 sta = ap_get_sta(args->wpa_s->ap_iface->bss[0], args->sta); 4665 if (!sta) 4666 return FALSE; 4667 4668 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 4669 &sta->capability, 4670 error); 4671 #else /* CONFIG_AP */ 4672 return FALSE; 4673 #endif /* CONFIG_AP */ 4674 } 4675 4676 4677 /** 4678 * wpas_dbus_getter_rx_packets - Return the received packets for a station 4679 * @iter: Pointer to incoming dbus message iter 4680 * @error: Location to store error on failure 4681 * @user_data: Function specific data 4682 * Returns: TRUE on success, FALSE on failure 4683 * 4684 * Getter for "RxPackets" property. 4685 */ 4686 dbus_bool_t wpas_dbus_getter_sta_rx_packets( 4687 const struct wpa_dbus_property_desc *property_desc, 4688 DBusMessageIter *iter, DBusError *error, void *user_data) 4689 { 4690 #ifdef CONFIG_AP 4691 struct sta_handler_args *args = user_data; 4692 struct sta_info *sta; 4693 struct hostap_sta_driver_data data; 4694 struct hostapd_data *hapd; 4695 4696 if (!args->wpa_s->ap_iface) 4697 return FALSE; 4698 4699 hapd = args->wpa_s->ap_iface->bss[0]; 4700 sta = ap_get_sta(hapd, args->sta); 4701 if (!sta) 4702 return FALSE; 4703 4704 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) 4705 return FALSE; 4706 4707 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64, 4708 &data.rx_packets, 4709 error); 4710 #else /* CONFIG_AP */ 4711 return FALSE; 4712 #endif /* CONFIG_AP */ 4713 } 4714 4715 4716 /** 4717 * wpas_dbus_getter_tx_packets - Return the transmitted packets for a station 4718 * @iter: Pointer to incoming dbus message iter 4719 * @error: Location to store error on failure 4720 * @user_data: Function specific data 4721 * Returns: TRUE on success, FALSE on failure 4722 * 4723 * Getter for "TxPackets" property. 4724 */ 4725 dbus_bool_t wpas_dbus_getter_sta_tx_packets( 4726 const struct wpa_dbus_property_desc *property_desc, 4727 DBusMessageIter *iter, DBusError *error, void *user_data) 4728 { 4729 #ifdef CONFIG_AP 4730 struct sta_handler_args *args = user_data; 4731 struct sta_info *sta; 4732 struct hostap_sta_driver_data data; 4733 struct hostapd_data *hapd; 4734 4735 if (!args->wpa_s->ap_iface) 4736 return FALSE; 4737 4738 hapd = args->wpa_s->ap_iface->bss[0]; 4739 sta = ap_get_sta(hapd, args->sta); 4740 if (!sta) 4741 return FALSE; 4742 4743 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) 4744 return FALSE; 4745 4746 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64, 4747 &data.tx_packets, 4748 error); 4749 #else /* CONFIG_AP */ 4750 return FALSE; 4751 #endif /* CONFIG_AP */ 4752 } 4753 4754 4755 /** 4756 * wpas_dbus_getter_tx_bytes - Return the transmitted bytes for a station 4757 * @iter: Pointer to incoming dbus message iter 4758 * @error: Location to store error on failure 4759 * @user_data: Function specific data 4760 * Returns: TRUE on success, FALSE on failure 4761 * 4762 * Getter for "TxBytes" property. 4763 */ 4764 dbus_bool_t wpas_dbus_getter_sta_tx_bytes( 4765 const struct wpa_dbus_property_desc *property_desc, 4766 DBusMessageIter *iter, DBusError *error, void *user_data) 4767 { 4768 #ifdef CONFIG_AP 4769 struct sta_handler_args *args = user_data; 4770 struct sta_info *sta; 4771 struct hostap_sta_driver_data data; 4772 struct hostapd_data *hapd; 4773 4774 if (!args->wpa_s->ap_iface) 4775 return FALSE; 4776 4777 hapd = args->wpa_s->ap_iface->bss[0]; 4778 sta = ap_get_sta(hapd, args->sta); 4779 if (!sta) 4780 return FALSE; 4781 4782 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) 4783 return FALSE; 4784 4785 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64, 4786 &data.tx_bytes, 4787 error); 4788 #else /* CONFIG_AP */ 4789 return FALSE; 4790 #endif /* CONFIG_AP */ 4791 } 4792 4793 4794 /** 4795 * wpas_dbus_getter_rx_bytes - Return the received bytes for a station 4796 * @iter: Pointer to incoming dbus message iter 4797 * @error: Location to store error on failure 4798 * @user_data: Function specific data 4799 * Returns: TRUE on success, FALSE on failure 4800 * 4801 * Getter for "RxBytes" property. 4802 */ 4803 dbus_bool_t wpas_dbus_getter_sta_rx_bytes( 4804 const struct wpa_dbus_property_desc *property_desc, 4805 DBusMessageIter *iter, DBusError *error, void *user_data) 4806 { 4807 #ifdef CONFIG_AP 4808 struct sta_handler_args *args = user_data; 4809 struct sta_info *sta; 4810 struct hostap_sta_driver_data data; 4811 struct hostapd_data *hapd; 4812 4813 if (!args->wpa_s->ap_iface) 4814 return FALSE; 4815 4816 hapd = args->wpa_s->ap_iface->bss[0]; 4817 sta = ap_get_sta(hapd, args->sta); 4818 if (!sta) 4819 return FALSE; 4820 4821 if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0) 4822 return FALSE; 4823 4824 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT64, 4825 &data.rx_bytes, 4826 error); 4827 #else /* CONFIG_AP */ 4828 return FALSE; 4829 #endif /* CONFIG_AP */ 4830 } 4831 4832 4833 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args, 4834 DBusError *error, const char *func_name) 4835 { 4836 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id); 4837 4838 if (!res) { 4839 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found", 4840 func_name, args->id); 4841 dbus_set_error(error, DBUS_ERROR_FAILED, 4842 "%s: BSS %d not found", 4843 func_name, args->id); 4844 } 4845 4846 return res; 4847 } 4848 4849 4850 /** 4851 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS 4852 * @iter: Pointer to incoming dbus message iter 4853 * @error: Location to store error on failure 4854 * @user_data: Function specific data 4855 * Returns: TRUE on success, FALSE on failure 4856 * 4857 * Getter for "BSSID" property. 4858 */ 4859 dbus_bool_t wpas_dbus_getter_bss_bssid( 4860 const struct wpa_dbus_property_desc *property_desc, 4861 DBusMessageIter *iter, DBusError *error, void *user_data) 4862 { 4863 struct bss_handler_args *args = user_data; 4864 struct wpa_bss *res; 4865 4866 res = get_bss_helper(args, error, __func__); 4867 if (!res) 4868 return FALSE; 4869 4870 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 4871 res->bssid, ETH_ALEN, 4872 error); 4873 } 4874 4875 4876 /** 4877 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS 4878 * @iter: Pointer to incoming dbus message iter 4879 * @error: Location to store error on failure 4880 * @user_data: Function specific data 4881 * Returns: TRUE on success, FALSE on failure 4882 * 4883 * Getter for "SSID" property. 4884 */ 4885 dbus_bool_t wpas_dbus_getter_bss_ssid( 4886 const struct wpa_dbus_property_desc *property_desc, 4887 DBusMessageIter *iter, DBusError *error, void *user_data) 4888 { 4889 struct bss_handler_args *args = user_data; 4890 struct wpa_bss *res; 4891 4892 res = get_bss_helper(args, error, __func__); 4893 if (!res) 4894 return FALSE; 4895 4896 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 4897 res->ssid, res->ssid_len, 4898 error); 4899 } 4900 4901 4902 /** 4903 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS 4904 * @iter: Pointer to incoming dbus message iter 4905 * @error: Location to store error on failure 4906 * @user_data: Function specific data 4907 * Returns: TRUE on success, FALSE on failure 4908 * 4909 * Getter for "Privacy" property. 4910 */ 4911 dbus_bool_t wpas_dbus_getter_bss_privacy( 4912 const struct wpa_dbus_property_desc *property_desc, 4913 DBusMessageIter *iter, DBusError *error, void *user_data) 4914 { 4915 struct bss_handler_args *args = user_data; 4916 struct wpa_bss *res; 4917 dbus_bool_t privacy; 4918 4919 res = get_bss_helper(args, error, __func__); 4920 if (!res) 4921 return FALSE; 4922 4923 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE; 4924 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 4925 &privacy, error); 4926 } 4927 4928 4929 /** 4930 * wpas_dbus_getter_bss_mode - Return the mode of a BSS 4931 * @iter: Pointer to incoming dbus message iter 4932 * @error: Location to store error on failure 4933 * @user_data: Function specific data 4934 * Returns: TRUE on success, FALSE on failure 4935 * 4936 * Getter for "Mode" property. 4937 */ 4938 dbus_bool_t wpas_dbus_getter_bss_mode( 4939 const struct wpa_dbus_property_desc *property_desc, 4940 DBusMessageIter *iter, DBusError *error, void *user_data) 4941 { 4942 struct bss_handler_args *args = user_data; 4943 struct wpa_bss *res; 4944 const char *mode; 4945 const u8 *mesh; 4946 4947 res = get_bss_helper(args, error, __func__); 4948 if (!res) 4949 return FALSE; 4950 if (bss_is_dmg(res)) { 4951 switch (res->caps & IEEE80211_CAP_DMG_MASK) { 4952 case IEEE80211_CAP_DMG_PBSS: 4953 case IEEE80211_CAP_DMG_IBSS: 4954 mode = "ad-hoc"; 4955 break; 4956 case IEEE80211_CAP_DMG_AP: 4957 mode = "infrastructure"; 4958 break; 4959 default: 4960 mode = ""; 4961 break; 4962 } 4963 } else { 4964 mesh = wpa_bss_get_ie(res, WLAN_EID_MESH_ID); 4965 if (mesh) 4966 mode = "mesh"; 4967 else if (res->caps & IEEE80211_CAP_IBSS) 4968 mode = "ad-hoc"; 4969 else 4970 mode = "infrastructure"; 4971 } 4972 4973 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 4974 &mode, error); 4975 } 4976 4977 4978 /** 4979 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS 4980 * @iter: Pointer to incoming dbus message iter 4981 * @error: Location to store error on failure 4982 * @user_data: Function specific data 4983 * Returns: TRUE on success, FALSE on failure 4984 * 4985 * Getter for "Level" property. 4986 */ 4987 dbus_bool_t wpas_dbus_getter_bss_signal( 4988 const struct wpa_dbus_property_desc *property_desc, 4989 DBusMessageIter *iter, DBusError *error, void *user_data) 4990 { 4991 struct bss_handler_args *args = user_data; 4992 struct wpa_bss *res; 4993 s16 level; 4994 4995 res = get_bss_helper(args, error, __func__); 4996 if (!res) 4997 return FALSE; 4998 4999 level = (s16) res->level; 5000 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16, 5001 &level, error); 5002 } 5003 5004 5005 /** 5006 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS 5007 * @iter: Pointer to incoming dbus message iter 5008 * @error: Location to store error on failure 5009 * @user_data: Function specific data 5010 * Returns: TRUE on success, FALSE on failure 5011 * 5012 * Getter for "Frequency" property. 5013 */ 5014 dbus_bool_t wpas_dbus_getter_bss_frequency( 5015 const struct wpa_dbus_property_desc *property_desc, 5016 DBusMessageIter *iter, DBusError *error, void *user_data) 5017 { 5018 struct bss_handler_args *args = user_data; 5019 struct wpa_bss *res; 5020 u16 freq; 5021 5022 res = get_bss_helper(args, error, __func__); 5023 if (!res) 5024 return FALSE; 5025 5026 freq = (u16) res->freq; 5027 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 5028 &freq, error); 5029 } 5030 5031 5032 static int cmp_u8s_desc(const void *a, const void *b) 5033 { 5034 return (*(u8 *) b - *(u8 *) a); 5035 } 5036 5037 5038 /** 5039 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS 5040 * @iter: Pointer to incoming dbus message iter 5041 * @error: Location to store error on failure 5042 * @user_data: Function specific data 5043 * Returns: TRUE on success, FALSE on failure 5044 * 5045 * Getter for "Rates" property. 5046 */ 5047 dbus_bool_t wpas_dbus_getter_bss_rates( 5048 const struct wpa_dbus_property_desc *property_desc, 5049 DBusMessageIter *iter, DBusError *error, void *user_data) 5050 { 5051 struct bss_handler_args *args = user_data; 5052 struct wpa_bss *res; 5053 u8 *ie_rates = NULL; 5054 u32 *real_rates; 5055 int rates_num, i; 5056 dbus_bool_t success = FALSE; 5057 5058 res = get_bss_helper(args, error, __func__); 5059 if (!res) 5060 return FALSE; 5061 5062 rates_num = wpa_bss_get_bit_rates(res, &ie_rates); 5063 if (rates_num < 0) 5064 return FALSE; 5065 5066 qsort(ie_rates, rates_num, 1, cmp_u8s_desc); 5067 5068 real_rates = os_malloc(sizeof(u32) * rates_num); 5069 if (!real_rates) { 5070 os_free(ie_rates); 5071 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 5072 return FALSE; 5073 } 5074 5075 for (i = 0; i < rates_num; i++) 5076 real_rates[i] = ie_rates[i] * 500000; 5077 5078 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32, 5079 real_rates, rates_num, 5080 error); 5081 5082 os_free(ie_rates); 5083 os_free(real_rates); 5084 return success; 5085 } 5086 5087 5088 static dbus_bool_t wpas_dbus_get_bss_security_prop( 5089 const struct wpa_dbus_property_desc *property_desc, 5090 DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error) 5091 { 5092 DBusMessageIter iter_dict, variant_iter; 5093 const char *group; 5094 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */ 5095 const char *key_mgmt[16]; /* max 16 key managements may be supported */ 5096 int n; 5097 5098 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 5099 "a{sv}", &variant_iter)) 5100 goto nomem; 5101 5102 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 5103 goto nomem; 5104 5105 /* 5106 * KeyMgmt 5107 * 5108 * When adding a new entry here, please take care to extend key_mgmt[] 5109 * and keep documentation in doc/dbus.doxygen up to date. 5110 */ 5111 n = 0; 5112 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK) 5113 key_mgmt[n++] = "wpa-psk"; 5114 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK) 5115 key_mgmt[n++] = "wpa-ft-psk"; 5116 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 5117 key_mgmt[n++] = "wpa-psk-sha256"; 5118 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X) 5119 key_mgmt[n++] = "wpa-eap"; 5120 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 5121 key_mgmt[n++] = "wpa-ft-eap"; 5122 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 5123 key_mgmt[n++] = "wpa-eap-sha256"; 5124 #ifdef CONFIG_SUITEB 5125 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) 5126 key_mgmt[n++] = "wpa-eap-suite-b"; 5127 #endif /* CONFIG_SUITEB */ 5128 #ifdef CONFIG_SUITEB192 5129 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 5130 key_mgmt[n++] = "wpa-eap-suite-b-192"; 5131 #endif /* CONFIG_SUITEB192 */ 5132 #ifdef CONFIG_FILS 5133 if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA256) 5134 key_mgmt[n++] = "wpa-fils-sha256"; 5135 if (ie_data->key_mgmt & WPA_KEY_MGMT_FILS_SHA384) 5136 key_mgmt[n++] = "wpa-fils-sha384"; 5137 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) 5138 key_mgmt[n++] = "wpa-ft-fils-sha256"; 5139 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) 5140 key_mgmt[n++] = "wpa-ft-fils-sha384"; 5141 #endif /* CONFIG_FILS */ 5142 #ifdef CONFIG_SAE 5143 if (ie_data->key_mgmt & WPA_KEY_MGMT_SAE) 5144 key_mgmt[n++] = "sae"; 5145 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_SAE) 5146 key_mgmt[n++] = "ft-sae"; 5147 #endif /* CONFIG_SAE */ 5148 #ifdef CONFIG_OWE 5149 if (ie_data->key_mgmt & WPA_KEY_MGMT_OWE) 5150 key_mgmt[n++] = "owe"; 5151 #endif /* CONFIG_OWE */ 5152 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE) 5153 key_mgmt[n++] = "wpa-none"; 5154 5155 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt", 5156 key_mgmt, n)) 5157 goto nomem; 5158 5159 /* Group */ 5160 switch (ie_data->group_cipher) { 5161 #ifdef CONFIG_WEP 5162 case WPA_CIPHER_WEP40: 5163 group = "wep40"; 5164 break; 5165 case WPA_CIPHER_WEP104: 5166 group = "wep104"; 5167 break; 5168 #endif /* CONFIG_WEP */ 5169 #ifndef CONFIG_NO_TKIP 5170 case WPA_CIPHER_TKIP: 5171 group = "tkip"; 5172 break; 5173 #endif /* CONFIG_NO_TKIP */ 5174 case WPA_CIPHER_CCMP: 5175 group = "ccmp"; 5176 break; 5177 case WPA_CIPHER_GCMP: 5178 group = "gcmp"; 5179 break; 5180 case WPA_CIPHER_CCMP_256: 5181 group = "ccmp-256"; 5182 break; 5183 case WPA_CIPHER_GCMP_256: 5184 group = "gcmp-256"; 5185 break; 5186 default: 5187 group = ""; 5188 break; 5189 } 5190 5191 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group)) 5192 goto nomem; 5193 5194 /* Pairwise */ 5195 n = 0; 5196 #ifndef CONFIG_NO_TKIP 5197 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP) 5198 pairwise[n++] = "tkip"; 5199 #endif /* CONFIG_NO_TKIP */ 5200 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP) 5201 pairwise[n++] = "ccmp"; 5202 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP) 5203 pairwise[n++] = "gcmp"; 5204 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256) 5205 pairwise[n++] = "ccmp-256"; 5206 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256) 5207 pairwise[n++] = "gcmp-256"; 5208 5209 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise", 5210 pairwise, n)) 5211 goto nomem; 5212 5213 /* Management group (RSN only) */ 5214 if (ie_data->proto == WPA_PROTO_RSN) { 5215 switch (ie_data->mgmt_group_cipher) { 5216 case WPA_CIPHER_AES_128_CMAC: 5217 group = "aes128cmac"; 5218 break; 5219 default: 5220 group = ""; 5221 break; 5222 } 5223 5224 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup", 5225 group)) 5226 goto nomem; 5227 } 5228 5229 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || 5230 !dbus_message_iter_close_container(iter, &variant_iter)) 5231 goto nomem; 5232 5233 return TRUE; 5234 5235 nomem: 5236 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 5237 return FALSE; 5238 } 5239 5240 5241 /** 5242 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS 5243 * @iter: Pointer to incoming dbus message iter 5244 * @error: Location to store error on failure 5245 * @user_data: Function specific data 5246 * Returns: TRUE on success, FALSE on failure 5247 * 5248 * Getter for "WPA" property. 5249 */ 5250 dbus_bool_t wpas_dbus_getter_bss_wpa( 5251 const struct wpa_dbus_property_desc *property_desc, 5252 DBusMessageIter *iter, DBusError *error, void *user_data) 5253 { 5254 struct bss_handler_args *args = user_data; 5255 struct wpa_bss *res; 5256 struct wpa_ie_data wpa_data; 5257 const u8 *ie; 5258 5259 res = get_bss_helper(args, error, __func__); 5260 if (!res) 5261 return FALSE; 5262 5263 os_memset(&wpa_data, 0, sizeof(wpa_data)); 5264 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); 5265 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { 5266 dbus_set_error_const(error, DBUS_ERROR_FAILED, 5267 "failed to parse WPA IE"); 5268 return FALSE; 5269 } 5270 5271 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error); 5272 } 5273 5274 5275 /** 5276 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS 5277 * @iter: Pointer to incoming dbus message iter 5278 * @error: Location to store error on failure 5279 * @user_data: Function specific data 5280 * Returns: TRUE on success, FALSE on failure 5281 * 5282 * Getter for "RSN" property. 5283 */ 5284 dbus_bool_t wpas_dbus_getter_bss_rsn( 5285 const struct wpa_dbus_property_desc *property_desc, 5286 DBusMessageIter *iter, DBusError *error, void *user_data) 5287 { 5288 struct bss_handler_args *args = user_data; 5289 struct wpa_bss *res; 5290 struct wpa_ie_data wpa_data; 5291 const u8 *ie; 5292 5293 res = get_bss_helper(args, error, __func__); 5294 if (!res) 5295 return FALSE; 5296 5297 os_memset(&wpa_data, 0, sizeof(wpa_data)); 5298 ie = wpa_bss_get_ie(res, WLAN_EID_RSN); 5299 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { 5300 dbus_set_error_const(error, DBUS_ERROR_FAILED, 5301 "failed to parse RSN IE"); 5302 return FALSE; 5303 } 5304 5305 return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error); 5306 } 5307 5308 5309 /** 5310 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS 5311 * @iter: Pointer to incoming dbus message iter 5312 * @error: Location to store error on failure 5313 * @user_data: Function specific data 5314 * Returns: TRUE on success, FALSE on failure 5315 * 5316 * Getter for "WPS" property. 5317 */ 5318 dbus_bool_t wpas_dbus_getter_bss_wps( 5319 const struct wpa_dbus_property_desc *property_desc, 5320 DBusMessageIter *iter, DBusError *error, void *user_data) 5321 { 5322 struct bss_handler_args *args = user_data; 5323 struct wpa_bss *res; 5324 #ifdef CONFIG_WPS 5325 struct wpabuf *wps_ie; 5326 #endif /* CONFIG_WPS */ 5327 DBusMessageIter iter_dict, variant_iter; 5328 int wps_support = 0; 5329 const char *type = ""; 5330 5331 res = get_bss_helper(args, error, __func__); 5332 if (!res) 5333 return FALSE; 5334 5335 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 5336 "a{sv}", &variant_iter) || 5337 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 5338 goto nomem; 5339 5340 #ifdef CONFIG_WPS 5341 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE); 5342 if (wps_ie) { 5343 wps_support = 1; 5344 if (wps_is_selected_pbc_registrar(wps_ie)) 5345 type = "pbc"; 5346 else if (wps_is_selected_pin_registrar(wps_ie)) 5347 type = "pin"; 5348 5349 wpabuf_free(wps_ie); 5350 } 5351 #endif /* CONFIG_WPS */ 5352 5353 if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) || 5354 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || 5355 !dbus_message_iter_close_container(iter, &variant_iter)) 5356 goto nomem; 5357 5358 return TRUE; 5359 5360 nomem: 5361 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 5362 return FALSE; 5363 } 5364 5365 5366 /** 5367 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS 5368 * @iter: Pointer to incoming dbus message iter 5369 * @error: Location to store error on failure 5370 * @user_data: Function specific data 5371 * Returns: TRUE on success, FALSE on failure 5372 * 5373 * Getter for "IEs" property. 5374 */ 5375 dbus_bool_t wpas_dbus_getter_bss_ies( 5376 const struct wpa_dbus_property_desc *property_desc, 5377 DBusMessageIter *iter, DBusError *error, void *user_data) 5378 { 5379 struct bss_handler_args *args = user_data; 5380 struct wpa_bss *res; 5381 5382 res = get_bss_helper(args, error, __func__); 5383 if (!res) 5384 return FALSE; 5385 5386 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 5387 wpa_bss_ie_ptr(res), 5388 res->ie_len, error); 5389 } 5390 5391 5392 /** 5393 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen 5394 * @iter: Pointer to incoming dbus message iter 5395 * @error: Location to store error on failure 5396 * @user_data: Function specific data 5397 * Returns: TRUE on success, FALSE on failure 5398 * 5399 * Getter for BSS age 5400 */ 5401 dbus_bool_t wpas_dbus_getter_bss_age( 5402 const struct wpa_dbus_property_desc *property_desc, 5403 DBusMessageIter *iter, DBusError *error, void *user_data) 5404 { 5405 struct bss_handler_args *args = user_data; 5406 struct wpa_bss *res; 5407 struct os_reltime now, diff = { 0, 0 }; 5408 u32 age; 5409 5410 res = get_bss_helper(args, error, __func__); 5411 if (!res) 5412 return FALSE; 5413 5414 os_get_reltime(&now); 5415 os_reltime_sub(&now, &res->last_update, &diff); 5416 age = diff.sec > 0 ? diff.sec : 0; 5417 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age, 5418 error); 5419 } 5420 5421 5422 /** 5423 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled 5424 * @iter: Pointer to incoming dbus message iter 5425 * @error: Location to store error on failure 5426 * @user_data: Function specific data 5427 * Returns: TRUE on success, FALSE on failure 5428 * 5429 * Getter for "enabled" property of a configured network. 5430 */ 5431 dbus_bool_t wpas_dbus_getter_enabled( 5432 const struct wpa_dbus_property_desc *property_desc, 5433 DBusMessageIter *iter, DBusError *error, void *user_data) 5434 { 5435 struct network_handler_args *net = user_data; 5436 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE; 5437 5438 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 5439 &enabled, error); 5440 } 5441 5442 5443 /** 5444 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled 5445 * @iter: Pointer to incoming dbus message iter 5446 * @error: Location to store error on failure 5447 * @user_data: Function specific data 5448 * Returns: TRUE on success, FALSE on failure 5449 * 5450 * Setter for "Enabled" property of a configured network. 5451 */ 5452 dbus_bool_t wpas_dbus_setter_enabled( 5453 const struct wpa_dbus_property_desc *property_desc, 5454 DBusMessageIter *iter, DBusError *error, void *user_data) 5455 { 5456 struct network_handler_args *net = user_data; 5457 struct wpa_supplicant *wpa_s; 5458 struct wpa_ssid *ssid; 5459 dbus_bool_t enable; 5460 5461 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 5462 &enable)) 5463 return FALSE; 5464 5465 wpa_s = net->wpa_s; 5466 ssid = net->ssid; 5467 5468 if (enable) 5469 wpa_supplicant_enable_network(wpa_s, ssid); 5470 else 5471 wpa_supplicant_disable_network(wpa_s, ssid); 5472 5473 return TRUE; 5474 } 5475 5476 5477 /** 5478 * wpas_dbus_getter_network_properties - Get options for a configured network 5479 * @iter: Pointer to incoming dbus message iter 5480 * @error: Location to store error on failure 5481 * @user_data: Function specific data 5482 * Returns: TRUE on success, FALSE on failure 5483 * 5484 * Getter for "Properties" property of a configured network. 5485 */ 5486 dbus_bool_t wpas_dbus_getter_network_properties( 5487 const struct wpa_dbus_property_desc *property_desc, 5488 DBusMessageIter *iter, DBusError *error, void *user_data) 5489 { 5490 struct network_handler_args *net = user_data; 5491 DBusMessageIter variant_iter, dict_iter; 5492 char **iterator; 5493 char **props = wpa_config_get_all(net->ssid, 1); 5494 dbus_bool_t success = FALSE; 5495 5496 if (!props) { 5497 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 5498 return FALSE; 5499 } 5500 5501 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}", 5502 &variant_iter) || 5503 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) { 5504 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 5505 goto out; 5506 } 5507 5508 iterator = props; 5509 while (*iterator) { 5510 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator, 5511 *(iterator + 1))) { 5512 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 5513 "no memory"); 5514 goto out; 5515 } 5516 iterator += 2; 5517 } 5518 5519 5520 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || 5521 !dbus_message_iter_close_container(iter, &variant_iter)) { 5522 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 5523 goto out; 5524 } 5525 5526 success = TRUE; 5527 5528 out: 5529 iterator = props; 5530 while (*iterator) { 5531 os_free(*iterator); 5532 iterator++; 5533 } 5534 os_free(props); 5535 return success; 5536 } 5537 5538 5539 /** 5540 * wpas_dbus_setter_network_properties - Set options for a configured network 5541 * @iter: Pointer to incoming dbus message iter 5542 * @error: Location to store error on failure 5543 * @user_data: Function specific data 5544 * Returns: TRUE on success, FALSE on failure 5545 * 5546 * Setter for "Properties" property of a configured network. 5547 */ 5548 dbus_bool_t wpas_dbus_setter_network_properties( 5549 const struct wpa_dbus_property_desc *property_desc, 5550 DBusMessageIter *iter, DBusError *error, void *user_data) 5551 { 5552 struct network_handler_args *net = user_data; 5553 struct wpa_ssid *ssid = net->ssid; 5554 DBusMessageIter variant_iter; 5555 5556 dbus_message_iter_recurse(iter, &variant_iter); 5557 return set_network_properties(net->wpa_s, ssid, &variant_iter, error); 5558 } 5559 5560 5561 #ifdef CONFIG_AP 5562 5563 DBusMessage * wpas_dbus_handler_subscribe_preq( 5564 DBusMessage *message, struct wpa_supplicant *wpa_s) 5565 { 5566 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 5567 char *name; 5568 5569 if (wpa_s->preq_notify_peer != NULL) { 5570 if (os_strcmp(dbus_message_get_sender(message), 5571 wpa_s->preq_notify_peer) == 0) 5572 return NULL; 5573 5574 return dbus_message_new_error(message, 5575 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE, 5576 "Another application is already subscribed"); 5577 } 5578 5579 name = os_strdup(dbus_message_get_sender(message)); 5580 if (!name) 5581 return wpas_dbus_error_no_memory(message); 5582 5583 wpa_s->preq_notify_peer = name; 5584 5585 /* Subscribe to clean up if application closes socket */ 5586 wpas_dbus_subscribe_noc(priv); 5587 5588 /* 5589 * Double-check it's still alive to make sure that we didn't 5590 * miss the NameOwnerChanged signal, e.g. while strdup'ing. 5591 */ 5592 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) { 5593 /* 5594 * Application no longer exists, clean up. 5595 * The return value is irrelevant now. 5596 * 5597 * Need to check if the NameOwnerChanged handling 5598 * already cleaned up because we have processed 5599 * DBus messages while checking if the name still 5600 * has an owner. 5601 */ 5602 if (!wpa_s->preq_notify_peer) 5603 return NULL; 5604 os_free(wpa_s->preq_notify_peer); 5605 wpa_s->preq_notify_peer = NULL; 5606 wpas_dbus_unsubscribe_noc(priv); 5607 } 5608 5609 return NULL; 5610 } 5611 5612 5613 DBusMessage * wpas_dbus_handler_unsubscribe_preq( 5614 DBusMessage *message, struct wpa_supplicant *wpa_s) 5615 { 5616 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 5617 5618 if (!wpa_s->preq_notify_peer) 5619 return dbus_message_new_error(message, 5620 WPAS_DBUS_ERROR_NO_SUBSCRIPTION, 5621 "Not subscribed"); 5622 5623 if (os_strcmp(wpa_s->preq_notify_peer, 5624 dbus_message_get_sender(message))) 5625 return dbus_message_new_error(message, 5626 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM, 5627 "Can't unsubscribe others"); 5628 5629 os_free(wpa_s->preq_notify_peer); 5630 wpa_s->preq_notify_peer = NULL; 5631 wpas_dbus_unsubscribe_noc(priv); 5632 return NULL; 5633 } 5634 5635 5636 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s, 5637 const u8 *addr, const u8 *dst, const u8 *bssid, 5638 const u8 *ie, size_t ie_len, u32 ssi_signal) 5639 { 5640 DBusMessage *msg; 5641 DBusMessageIter iter, dict_iter; 5642 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 5643 5644 /* Do nothing if the control interface is not turned on */ 5645 if (priv == NULL || !wpa_s->dbus_new_path) 5646 return; 5647 5648 if (wpa_s->preq_notify_peer == NULL) 5649 return; 5650 5651 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 5652 WPAS_DBUS_NEW_IFACE_INTERFACE, 5653 "ProbeRequest"); 5654 if (msg == NULL) 5655 return; 5656 5657 dbus_message_set_destination(msg, wpa_s->preq_notify_peer); 5658 5659 dbus_message_iter_init_append(msg, &iter); 5660 5661 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 5662 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr", 5663 (const char *) addr, 5664 ETH_ALEN)) || 5665 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst", 5666 (const char *) dst, 5667 ETH_ALEN)) || 5668 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid", 5669 (const char *) bssid, 5670 ETH_ALEN)) || 5671 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies", 5672 (const char *) ie, 5673 ie_len)) || 5674 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal", 5675 ssi_signal)) || 5676 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 5677 goto fail; 5678 5679 dbus_connection_send(priv->con, msg, NULL); 5680 goto out; 5681 fail: 5682 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 5683 out: 5684 dbus_message_unref(msg); 5685 } 5686 5687 #endif /* CONFIG_AP */ 5688 5689 5690 DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message, 5691 struct wpa_supplicant *wpa_s) 5692 { 5693 u8 *ielems; 5694 int len; 5695 struct ieee802_11_elems elems; 5696 dbus_int32_t frame_id; 5697 DBusMessageIter iter, array; 5698 5699 dbus_message_iter_init(message, &iter); 5700 dbus_message_iter_get_basic(&iter, &frame_id); 5701 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) { 5702 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5703 "Invalid ID"); 5704 } 5705 5706 dbus_message_iter_next(&iter); 5707 dbus_message_iter_recurse(&iter, &array); 5708 dbus_message_iter_get_fixed_array(&array, &ielems, &len); 5709 if (!ielems || len == 0) { 5710 return dbus_message_new_error( 5711 message, DBUS_ERROR_INVALID_ARGS, "Invalid value"); 5712 } 5713 5714 if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) { 5715 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5716 "Parse error"); 5717 } 5718 5719 wpa_s = wpas_vendor_elem(wpa_s, frame_id); 5720 if (!wpa_s->vendor_elem[frame_id]) { 5721 wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len); 5722 wpas_vendor_elem_update(wpa_s); 5723 return NULL; 5724 } 5725 5726 if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) { 5727 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5728 "Resize error"); 5729 } 5730 5731 wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len); 5732 wpas_vendor_elem_update(wpa_s); 5733 return NULL; 5734 } 5735 5736 5737 DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message, 5738 struct wpa_supplicant *wpa_s) 5739 { 5740 DBusMessage *reply; 5741 DBusMessageIter iter, array_iter; 5742 dbus_int32_t frame_id; 5743 const u8 *elem; 5744 size_t elem_len; 5745 5746 dbus_message_iter_init(message, &iter); 5747 dbus_message_iter_get_basic(&iter, &frame_id); 5748 5749 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) { 5750 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5751 "Invalid ID"); 5752 } 5753 5754 wpa_s = wpas_vendor_elem(wpa_s, frame_id); 5755 if (!wpa_s->vendor_elem[frame_id]) { 5756 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5757 "ID value does not exist"); 5758 } 5759 5760 reply = dbus_message_new_method_return(message); 5761 if (!reply) 5762 return wpas_dbus_error_no_memory(message); 5763 5764 dbus_message_iter_init_append(reply, &iter); 5765 5766 elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]); 5767 elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]); 5768 5769 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 5770 DBUS_TYPE_BYTE_AS_STRING, 5771 &array_iter) || 5772 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE, 5773 &elem, elem_len) || 5774 !dbus_message_iter_close_container(&iter, &array_iter)) { 5775 dbus_message_unref(reply); 5776 reply = wpas_dbus_error_no_memory(message); 5777 } 5778 5779 return reply; 5780 } 5781 5782 5783 DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message, 5784 struct wpa_supplicant *wpa_s) 5785 { 5786 u8 *ielems; 5787 int len; 5788 struct ieee802_11_elems elems; 5789 DBusMessageIter iter, array; 5790 dbus_int32_t frame_id; 5791 5792 dbus_message_iter_init(message, &iter); 5793 dbus_message_iter_get_basic(&iter, &frame_id); 5794 if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) { 5795 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5796 "Invalid ID"); 5797 } 5798 5799 dbus_message_iter_next(&iter); 5800 dbus_message_iter_recurse(&iter, &array); 5801 dbus_message_iter_get_fixed_array(&array, &ielems, &len); 5802 if (!ielems || len == 0) { 5803 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5804 "Invalid value"); 5805 } 5806 5807 wpa_s = wpas_vendor_elem(wpa_s, frame_id); 5808 5809 if (len == 1 && *ielems == '*') { 5810 wpabuf_free(wpa_s->vendor_elem[frame_id]); 5811 wpa_s->vendor_elem[frame_id] = NULL; 5812 wpas_vendor_elem_update(wpa_s); 5813 return NULL; 5814 } 5815 5816 if (!wpa_s->vendor_elem[frame_id]) { 5817 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5818 "ID value does not exist"); 5819 } 5820 5821 if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) { 5822 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5823 "Parse error"); 5824 } 5825 5826 if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0) 5827 return NULL; 5828 5829 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 5830 "Not found"); 5831 } 5832 5833 5834 #ifdef CONFIG_MESH 5835 5836 /** 5837 * wpas_dbus_getter_mesh_peers - Get connected mesh peers 5838 * @iter: Pointer to incoming dbus message iter 5839 * @error: Location to store error on failure 5840 * @user_data: Function specific data 5841 * Returns: TRUE on success, FALSE on failure 5842 * 5843 * Getter for "MeshPeers" property. 5844 */ 5845 dbus_bool_t wpas_dbus_getter_mesh_peers( 5846 const struct wpa_dbus_property_desc *property_desc, 5847 DBusMessageIter *iter, DBusError *error, void *user_data) 5848 { 5849 struct wpa_supplicant *wpa_s = user_data; 5850 struct hostapd_data *hapd; 5851 struct sta_info *sta; 5852 DBusMessageIter variant_iter, array_iter; 5853 int i; 5854 DBusMessageIter inner_array_iter; 5855 5856 if (!wpa_s->ifmsh) 5857 return FALSE; 5858 hapd = wpa_s->ifmsh->bss[0]; 5859 5860 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 5861 DBUS_TYPE_ARRAY_AS_STRING 5862 DBUS_TYPE_ARRAY_AS_STRING 5863 DBUS_TYPE_BYTE_AS_STRING, 5864 &variant_iter) || 5865 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 5866 DBUS_TYPE_ARRAY_AS_STRING 5867 DBUS_TYPE_BYTE_AS_STRING, 5868 &array_iter)) 5869 return FALSE; 5870 5871 for (sta = hapd->sta_list; sta; sta = sta->next) { 5872 if (!dbus_message_iter_open_container( 5873 &array_iter, DBUS_TYPE_ARRAY, 5874 DBUS_TYPE_BYTE_AS_STRING, 5875 &inner_array_iter)) 5876 return FALSE; 5877 5878 for (i = 0; i < ETH_ALEN; i++) { 5879 if (!dbus_message_iter_append_basic(&inner_array_iter, 5880 DBUS_TYPE_BYTE, 5881 &(sta->addr[i]))) 5882 return FALSE; 5883 } 5884 5885 if (!dbus_message_iter_close_container( 5886 &array_iter, &inner_array_iter)) 5887 return FALSE; 5888 } 5889 5890 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) || 5891 !dbus_message_iter_close_container(iter, &variant_iter)) 5892 return FALSE; 5893 5894 return TRUE; 5895 } 5896 5897 5898 /** 5899 * wpas_dbus_getter_mesh_group - Get mesh group 5900 * @iter: Pointer to incoming dbus message iter 5901 * @error: Location to store error on failure 5902 * @user_data: Function specific data 5903 * Returns: TRUE on success, FALSE on failure 5904 * 5905 * Getter for "MeshGroup" property. 5906 */ 5907 dbus_bool_t wpas_dbus_getter_mesh_group( 5908 const struct wpa_dbus_property_desc *property_desc, 5909 DBusMessageIter *iter, DBusError *error, void *user_data) 5910 { 5911 struct wpa_supplicant *wpa_s = user_data; 5912 struct wpa_ssid *ssid = wpa_s->current_ssid; 5913 5914 if (!wpa_s->ifmsh || !ssid) 5915 return FALSE; 5916 5917 if (!wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 5918 (char *) ssid->ssid, 5919 ssid->ssid_len, error)) { 5920 dbus_set_error(error, DBUS_ERROR_FAILED, 5921 "%s: error constructing reply", __func__); 5922 return FALSE; 5923 } 5924 5925 return TRUE; 5926 } 5927 5928 #endif /* CONFIG_MESH */ 5929