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