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