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