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