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