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