dbus_new_handlers.c revision 01904cfafd75a70b9f29c0220b90bdef45595491
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#ifdef CONFIG_TDLS 2001 2002static DBusMessage * get_peer_hwaddr_helper(DBusMessage *message, 2003 const char *func_name, 2004 u8 *peer_address) 2005{ 2006 const char *peer_string; 2007 2008 if (!dbus_message_get_args(message, NULL, 2009 DBUS_TYPE_STRING, &peer_string, 2010 DBUS_TYPE_INVALID)) 2011 return wpas_dbus_error_invalid_args(message, NULL); 2012 2013 if (hwaddr_aton(peer_string, peer_address)) { 2014 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'", 2015 func_name, peer_string); 2016 return wpas_dbus_error_invalid_args( 2017 message, "Invalid hardware address format"); 2018 } 2019 2020 return NULL; 2021} 2022 2023 2024/* 2025 * wpas_dbus_handler_tdls_discover - Discover TDLS peer 2026 * @message: Pointer to incoming dbus message 2027 * @wpa_s: wpa_supplicant structure for a network interface 2028 * Returns: NULL indicating success or DBus error message on failure 2029 * 2030 * Handler function for "TDLSDiscover" method call of network interface. 2031 */ 2032DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message, 2033 struct wpa_supplicant *wpa_s) 2034{ 2035 u8 peer[ETH_ALEN]; 2036 DBusMessage *error_reply; 2037 int ret; 2038 2039 error_reply = get_peer_hwaddr_helper(message, __func__, peer); 2040 if (error_reply) 2041 return error_reply; 2042 2043 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer)); 2044 2045 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2046 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 2047 else 2048 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 2049 2050 if (ret) { 2051 return wpas_dbus_error_unknown_error( 2052 message, "error performing TDLS discovery"); 2053 } 2054 2055 return NULL; 2056} 2057 2058 2059/* 2060 * wpas_dbus_handler_tdls_setup - Setup TDLS session 2061 * @message: Pointer to incoming dbus message 2062 * @wpa_s: wpa_supplicant structure for a network interface 2063 * Returns: NULL indicating success or DBus error message on failure 2064 * 2065 * Handler function for "TDLSSetup" method call of network interface. 2066 */ 2067DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message, 2068 struct wpa_supplicant *wpa_s) 2069{ 2070 u8 peer[ETH_ALEN]; 2071 DBusMessage *error_reply; 2072 int ret; 2073 2074 error_reply = get_peer_hwaddr_helper(message, __func__, peer); 2075 if (error_reply) 2076 return error_reply; 2077 2078 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer)); 2079 2080 wpa_tdls_remove(wpa_s->wpa, peer); 2081 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2082 ret = wpa_tdls_start(wpa_s->wpa, peer); 2083 else 2084 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 2085 2086 if (ret) { 2087 return wpas_dbus_error_unknown_error( 2088 message, "error performing TDLS setup"); 2089 } 2090 2091 return NULL; 2092} 2093 2094 2095/* 2096 * wpas_dbus_handler_tdls_status - Return TDLS session status 2097 * @message: Pointer to incoming dbus message 2098 * @wpa_s: wpa_supplicant structure for a network interface 2099 * Returns: A string representing the state of the link to this TDLS peer 2100 * 2101 * Handler function for "TDLSStatus" method call of network interface. 2102 */ 2103DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message, 2104 struct wpa_supplicant *wpa_s) 2105{ 2106 u8 peer[ETH_ALEN]; 2107 DBusMessage *reply; 2108 const char *tdls_status; 2109 2110 reply = get_peer_hwaddr_helper(message, __func__, peer); 2111 if (reply) 2112 return reply; 2113 2114 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer)); 2115 2116 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer); 2117 2118 reply = dbus_message_new_method_return(message); 2119 dbus_message_append_args(reply, DBUS_TYPE_STRING, 2120 &tdls_status, DBUS_TYPE_INVALID); 2121 return reply; 2122} 2123 2124 2125/* 2126 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session 2127 * @message: Pointer to incoming dbus message 2128 * @wpa_s: wpa_supplicant structure for a network interface 2129 * Returns: NULL indicating success or DBus error message on failure 2130 * 2131 * Handler function for "TDLSTeardown" method call of network interface. 2132 */ 2133DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message, 2134 struct wpa_supplicant *wpa_s) 2135{ 2136 u8 peer[ETH_ALEN]; 2137 DBusMessage *error_reply; 2138 int ret; 2139 2140 error_reply = get_peer_hwaddr_helper(message, __func__, peer); 2141 if (error_reply) 2142 return error_reply; 2143 2144 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer)); 2145 2146 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2147 ret = wpa_tdls_teardown_link( 2148 wpa_s->wpa, peer, 2149 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 2150 else 2151 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 2152 2153 if (ret) { 2154 return wpas_dbus_error_unknown_error( 2155 message, "error performing TDLS teardown"); 2156 } 2157 2158 return NULL; 2159} 2160 2161#endif /* CONFIG_TDLS */ 2162 2163 2164/** 2165 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path 2166 * @message: Pointer to incoming dbus message 2167 * @wpa_s: %wpa_supplicant data structure 2168 * Returns: A dbus message containing an error on failure or NULL on success 2169 * 2170 * Sets the PKCS #11 engine and module path. 2171 */ 2172DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path( 2173 DBusMessage *message, struct wpa_supplicant *wpa_s) 2174{ 2175 DBusMessageIter iter; 2176 char *value = NULL; 2177 char *pkcs11_engine_path = NULL; 2178 char *pkcs11_module_path = NULL; 2179 2180 dbus_message_iter_init(message, &iter); 2181 dbus_message_iter_get_basic(&iter, &value); 2182 if (value == NULL) { 2183 return dbus_message_new_error( 2184 message, DBUS_ERROR_INVALID_ARGS, 2185 "Invalid pkcs11_engine_path argument"); 2186 } 2187 /* Empty path defaults to NULL */ 2188 if (os_strlen(value)) 2189 pkcs11_engine_path = value; 2190 2191 dbus_message_iter_next(&iter); 2192 dbus_message_iter_get_basic(&iter, &value); 2193 if (value == NULL) { 2194 os_free(pkcs11_engine_path); 2195 return dbus_message_new_error( 2196 message, DBUS_ERROR_INVALID_ARGS, 2197 "Invalid pkcs11_module_path argument"); 2198 } 2199 /* Empty path defaults to NULL */ 2200 if (os_strlen(value)) 2201 pkcs11_module_path = value; 2202 2203 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path, 2204 pkcs11_module_path)) 2205 return dbus_message_new_error( 2206 message, DBUS_ERROR_FAILED, 2207 "Reinit of the EAPOL state machine with the new PKCS " 2208 "#11 engine and module path failed."); 2209 2210 wpa_dbus_mark_property_changed( 2211 wpa_s->global->dbus, wpa_s->dbus_new_path, 2212 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath"); 2213 wpa_dbus_mark_property_changed( 2214 wpa_s->global->dbus, wpa_s->dbus_new_path, 2215 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath"); 2216 2217 return NULL; 2218} 2219 2220 2221/** 2222 * wpas_dbus_getter_capabilities - Return interface capabilities 2223 * @iter: Pointer to incoming dbus message iter 2224 * @error: Location to store error on failure 2225 * @user_data: Function specific data 2226 * Returns: TRUE on success, FALSE on failure 2227 * 2228 * Getter for "Capabilities" property of an interface. 2229 */ 2230dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter, 2231 DBusError *error, void *user_data) 2232{ 2233 struct wpa_supplicant *wpa_s = user_data; 2234 struct wpa_driver_capa capa; 2235 int res; 2236 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array, 2237 variant_iter; 2238 const char *scans[] = { "active", "passive", "ssid" }; 2239 2240 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 2241 "a{sv}", &variant_iter)) 2242 goto nomem; 2243 2244 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 2245 goto nomem; 2246 2247 res = wpa_drv_get_capa(wpa_s, &capa); 2248 2249 /***** pairwise cipher */ 2250 if (res < 0) { 2251 const char *args[] = {"ccmp", "tkip", "none"}; 2252 if (!wpa_dbus_dict_append_string_array( 2253 &iter_dict, "Pairwise", args, 2254 ARRAY_SIZE(args))) 2255 goto nomem; 2256 } else { 2257 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise", 2258 &iter_dict_entry, 2259 &iter_dict_val, 2260 &iter_array)) 2261 goto nomem; 2262 2263 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2264 if (!wpa_dbus_dict_string_array_add_element( 2265 &iter_array, "ccmp")) 2266 goto nomem; 2267 } 2268 2269 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) { 2270 if (!wpa_dbus_dict_string_array_add_element( 2271 &iter_array, "gcmp")) 2272 goto nomem; 2273 } 2274 2275 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2276 if (!wpa_dbus_dict_string_array_add_element( 2277 &iter_array, "tkip")) 2278 goto nomem; 2279 } 2280 2281 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2282 if (!wpa_dbus_dict_string_array_add_element( 2283 &iter_array, "none")) 2284 goto nomem; 2285 } 2286 2287 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2288 &iter_dict_entry, 2289 &iter_dict_val, 2290 &iter_array)) 2291 goto nomem; 2292 } 2293 2294 /***** group cipher */ 2295 if (res < 0) { 2296 const char *args[] = { 2297 "ccmp", "tkip", "wep104", "wep40" 2298 }; 2299 if (!wpa_dbus_dict_append_string_array( 2300 &iter_dict, "Group", args, 2301 ARRAY_SIZE(args))) 2302 goto nomem; 2303 } else { 2304 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group", 2305 &iter_dict_entry, 2306 &iter_dict_val, 2307 &iter_array)) 2308 goto nomem; 2309 2310 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2311 if (!wpa_dbus_dict_string_array_add_element( 2312 &iter_array, "ccmp")) 2313 goto nomem; 2314 } 2315 2316 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) { 2317 if (!wpa_dbus_dict_string_array_add_element( 2318 &iter_array, "gcmp")) 2319 goto nomem; 2320 } 2321 2322 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2323 if (!wpa_dbus_dict_string_array_add_element( 2324 &iter_array, "tkip")) 2325 goto nomem; 2326 } 2327 2328 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { 2329 if (!wpa_dbus_dict_string_array_add_element( 2330 &iter_array, "wep104")) 2331 goto nomem; 2332 } 2333 2334 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { 2335 if (!wpa_dbus_dict_string_array_add_element( 2336 &iter_array, "wep40")) 2337 goto nomem; 2338 } 2339 2340 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2341 &iter_dict_entry, 2342 &iter_dict_val, 2343 &iter_array)) 2344 goto nomem; 2345 } 2346 2347 /***** key management */ 2348 if (res < 0) { 2349 const char *args[] = { 2350 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none", 2351#ifdef CONFIG_WPS 2352 "wps", 2353#endif /* CONFIG_WPS */ 2354 "none" 2355 }; 2356 if (!wpa_dbus_dict_append_string_array( 2357 &iter_dict, "KeyMgmt", args, 2358 ARRAY_SIZE(args))) 2359 goto nomem; 2360 } else { 2361 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt", 2362 &iter_dict_entry, 2363 &iter_dict_val, 2364 &iter_array)) 2365 goto nomem; 2366 2367 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 2368 "none")) 2369 goto nomem; 2370 2371 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 2372 "ieee8021x")) 2373 goto nomem; 2374 2375 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2376 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 2377 if (!wpa_dbus_dict_string_array_add_element( 2378 &iter_array, "wpa-eap")) 2379 goto nomem; 2380 2381 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) 2382 if (!wpa_dbus_dict_string_array_add_element( 2383 &iter_array, "wpa-ft-eap")) 2384 goto nomem; 2385 2386/* TODO: Ensure that driver actually supports sha256 encryption. */ 2387#ifdef CONFIG_IEEE80211W 2388 if (!wpa_dbus_dict_string_array_add_element( 2389 &iter_array, "wpa-eap-sha256")) 2390 goto nomem; 2391#endif /* CONFIG_IEEE80211W */ 2392 } 2393 2394 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 2395 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2396 if (!wpa_dbus_dict_string_array_add_element( 2397 &iter_array, "wpa-psk")) 2398 goto nomem; 2399 2400 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) 2401 if (!wpa_dbus_dict_string_array_add_element( 2402 &iter_array, "wpa-ft-psk")) 2403 goto nomem; 2404 2405/* TODO: Ensure that driver actually supports sha256 encryption. */ 2406#ifdef CONFIG_IEEE80211W 2407 if (!wpa_dbus_dict_string_array_add_element( 2408 &iter_array, "wpa-psk-sha256")) 2409 goto nomem; 2410#endif /* CONFIG_IEEE80211W */ 2411 } 2412 2413 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2414 if (!wpa_dbus_dict_string_array_add_element( 2415 &iter_array, "wpa-none")) 2416 goto nomem; 2417 } 2418 2419 2420#ifdef CONFIG_WPS 2421 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 2422 "wps")) 2423 goto nomem; 2424#endif /* CONFIG_WPS */ 2425 2426 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2427 &iter_dict_entry, 2428 &iter_dict_val, 2429 &iter_array)) 2430 goto nomem; 2431 } 2432 2433 /***** WPA protocol */ 2434 if (res < 0) { 2435 const char *args[] = { "rsn", "wpa" }; 2436 if (!wpa_dbus_dict_append_string_array( 2437 &iter_dict, "Protocol", args, 2438 ARRAY_SIZE(args))) 2439 goto nomem; 2440 } else { 2441 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol", 2442 &iter_dict_entry, 2443 &iter_dict_val, 2444 &iter_array)) 2445 goto nomem; 2446 2447 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 2448 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2449 if (!wpa_dbus_dict_string_array_add_element( 2450 &iter_array, "rsn")) 2451 goto nomem; 2452 } 2453 2454 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2455 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 2456 if (!wpa_dbus_dict_string_array_add_element( 2457 &iter_array, "wpa")) 2458 goto nomem; 2459 } 2460 2461 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2462 &iter_dict_entry, 2463 &iter_dict_val, 2464 &iter_array)) 2465 goto nomem; 2466 } 2467 2468 /***** auth alg */ 2469 if (res < 0) { 2470 const char *args[] = { "open", "shared", "leap" }; 2471 if (!wpa_dbus_dict_append_string_array( 2472 &iter_dict, "AuthAlg", args, 2473 ARRAY_SIZE(args))) 2474 goto nomem; 2475 } else { 2476 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg", 2477 &iter_dict_entry, 2478 &iter_dict_val, 2479 &iter_array)) 2480 goto nomem; 2481 2482 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { 2483 if (!wpa_dbus_dict_string_array_add_element( 2484 &iter_array, "open")) 2485 goto nomem; 2486 } 2487 2488 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { 2489 if (!wpa_dbus_dict_string_array_add_element( 2490 &iter_array, "shared")) 2491 goto nomem; 2492 } 2493 2494 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { 2495 if (!wpa_dbus_dict_string_array_add_element( 2496 &iter_array, "leap")) 2497 goto nomem; 2498 } 2499 2500 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2501 &iter_dict_entry, 2502 &iter_dict_val, 2503 &iter_array)) 2504 goto nomem; 2505 } 2506 2507 /***** Scan */ 2508 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans, 2509 ARRAY_SIZE(scans))) 2510 goto nomem; 2511 2512 /***** Modes */ 2513 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes", 2514 &iter_dict_entry, 2515 &iter_dict_val, 2516 &iter_array)) 2517 goto nomem; 2518 2519 if (!wpa_dbus_dict_string_array_add_element( 2520 &iter_array, "infrastructure")) 2521 goto nomem; 2522 2523 if (!wpa_dbus_dict_string_array_add_element( 2524 &iter_array, "ad-hoc")) 2525 goto nomem; 2526 2527 if (res >= 0) { 2528 if (capa.flags & (WPA_DRIVER_FLAGS_AP)) { 2529 if (!wpa_dbus_dict_string_array_add_element( 2530 &iter_array, "ap")) 2531 goto nomem; 2532 } 2533 2534 if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) { 2535 if (!wpa_dbus_dict_string_array_add_element( 2536 &iter_array, "p2p")) 2537 goto nomem; 2538 } 2539 } 2540 2541 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2542 &iter_dict_entry, 2543 &iter_dict_val, 2544 &iter_array)) 2545 goto nomem; 2546 /***** Modes end */ 2547 2548 if (res >= 0) { 2549 dbus_int32_t max_scan_ssid = capa.max_scan_ssids; 2550 2551 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID", 2552 max_scan_ssid)) 2553 goto nomem; 2554 } 2555 2556 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) 2557 goto nomem; 2558 if (!dbus_message_iter_close_container(iter, &variant_iter)) 2559 goto nomem; 2560 2561 return TRUE; 2562 2563nomem: 2564 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2565 return FALSE; 2566} 2567 2568 2569/** 2570 * wpas_dbus_getter_state - Get interface state 2571 * @iter: Pointer to incoming dbus message iter 2572 * @error: Location to store error on failure 2573 * @user_data: Function specific data 2574 * Returns: TRUE on success, FALSE on failure 2575 * 2576 * Getter for "State" property. 2577 */ 2578dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error, 2579 void *user_data) 2580{ 2581 struct wpa_supplicant *wpa_s = user_data; 2582 const char *str_state; 2583 char *state_ls, *tmp; 2584 dbus_bool_t success = FALSE; 2585 2586 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 2587 2588 /* make state string lowercase to fit new DBus API convention 2589 */ 2590 state_ls = tmp = os_strdup(str_state); 2591 if (!tmp) { 2592 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2593 return FALSE; 2594 } 2595 while (*tmp) { 2596 *tmp = tolower(*tmp); 2597 tmp++; 2598 } 2599 2600 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2601 &state_ls, error); 2602 2603 os_free(state_ls); 2604 2605 return success; 2606} 2607 2608 2609/** 2610 * wpas_dbus_new_iface_get_scanning - Get interface scanning state 2611 * @iter: Pointer to incoming dbus message iter 2612 * @error: Location to store error on failure 2613 * @user_data: Function specific data 2614 * Returns: TRUE on success, FALSE on failure 2615 * 2616 * Getter for "scanning" property. 2617 */ 2618dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error, 2619 void *user_data) 2620{ 2621 struct wpa_supplicant *wpa_s = user_data; 2622 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 2623 2624 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 2625 &scanning, error); 2626} 2627 2628 2629/** 2630 * wpas_dbus_getter_ap_scan - Control roaming mode 2631 * @iter: Pointer to incoming dbus message iter 2632 * @error: Location to store error on failure 2633 * @user_data: Function specific data 2634 * Returns: TRUE on success, FALSE on failure 2635 * 2636 * Getter function for "ApScan" property. 2637 */ 2638dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error, 2639 void *user_data) 2640{ 2641 struct wpa_supplicant *wpa_s = user_data; 2642 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan; 2643 2644 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2645 &ap_scan, error); 2646} 2647 2648 2649/** 2650 * wpas_dbus_setter_ap_scan - Control roaming mode 2651 * @iter: Pointer to incoming dbus message iter 2652 * @error: Location to store error on failure 2653 * @user_data: Function specific data 2654 * Returns: TRUE on success, FALSE on failure 2655 * 2656 * Setter function for "ApScan" property. 2657 */ 2658dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error, 2659 void *user_data) 2660{ 2661 struct wpa_supplicant *wpa_s = user_data; 2662 dbus_uint32_t ap_scan; 2663 2664 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2665 &ap_scan)) 2666 return FALSE; 2667 2668 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 2669 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2670 "ap_scan must be 0, 1, or 2"); 2671 return FALSE; 2672 } 2673 return TRUE; 2674} 2675 2676 2677/** 2678 * wpas_dbus_getter_fast_reauth - Control fast 2679 * reauthentication (TLS session resumption) 2680 * @iter: Pointer to incoming dbus message iter 2681 * @error: Location to store error on failure 2682 * @user_data: Function specific data 2683 * Returns: TRUE on success, FALSE on failure 2684 * 2685 * Getter function for "FastReauth" property. 2686 */ 2687dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter, 2688 DBusError *error, 2689 void *user_data) 2690{ 2691 struct wpa_supplicant *wpa_s = user_data; 2692 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE; 2693 2694 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 2695 &fast_reauth, error); 2696} 2697 2698 2699/** 2700 * wpas_dbus_setter_fast_reauth - Control fast 2701 * reauthentication (TLS session resumption) 2702 * @iter: Pointer to incoming dbus message iter 2703 * @error: Location to store error on failure 2704 * @user_data: Function specific data 2705 * Returns: TRUE on success, FALSE on failure 2706 * 2707 * Setter function for "FastReauth" property. 2708 */ 2709dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter, 2710 DBusError *error, 2711 void *user_data) 2712{ 2713 struct wpa_supplicant *wpa_s = user_data; 2714 dbus_bool_t fast_reauth; 2715 2716 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 2717 &fast_reauth)) 2718 return FALSE; 2719 2720 wpa_s->conf->fast_reauth = fast_reauth; 2721 return TRUE; 2722} 2723 2724 2725/** 2726 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect 2727 * @iter: Pointer to incoming dbus message iter 2728 * @error: Location to store error on failure 2729 * @user_data: Function specific data 2730 * Returns: TRUE on success, FALSE on failure 2731 * 2732 * Getter for "DisconnectReason" property. The reason is negative if it is 2733 * locally generated. 2734 */ 2735dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter, 2736 DBusError *error, 2737 void *user_data) 2738{ 2739 struct wpa_supplicant *wpa_s = user_data; 2740 dbus_int32_t reason = wpa_s->disconnect_reason; 2741 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 2742 &reason, error); 2743} 2744 2745 2746/** 2747 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age 2748 * @iter: Pointer to incoming dbus message iter 2749 * @error: Location to store error on failure 2750 * @user_data: Function specific data 2751 * Returns: TRUE on success, FALSE on failure 2752 * 2753 * Getter function for "BSSExpireAge" property. 2754 */ 2755dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter, 2756 DBusError *error, 2757 void *user_data) 2758{ 2759 struct wpa_supplicant *wpa_s = user_data; 2760 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age; 2761 2762 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2763 &expire_age, error); 2764} 2765 2766 2767/** 2768 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age 2769 * @iter: Pointer to incoming dbus message iter 2770 * @error: Location to store error on failure 2771 * @user_data: Function specific data 2772 * Returns: TRUE on success, FALSE on failure 2773 * 2774 * Setter function for "BSSExpireAge" property. 2775 */ 2776dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter, 2777 DBusError *error, 2778 void *user_data) 2779{ 2780 struct wpa_supplicant *wpa_s = user_data; 2781 dbus_uint32_t expire_age; 2782 2783 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2784 &expire_age)) 2785 return FALSE; 2786 2787 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) { 2788 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2789 "BSSExpireAge must be >= 10"); 2790 return FALSE; 2791 } 2792 return TRUE; 2793} 2794 2795 2796/** 2797 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count 2798 * @iter: Pointer to incoming dbus message iter 2799 * @error: Location to store error on failure 2800 * @user_data: Function specific data 2801 * Returns: TRUE on success, FALSE on failure 2802 * 2803 * Getter function for "BSSExpireCount" property. 2804 */ 2805dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter, 2806 DBusError *error, 2807 void *user_data) 2808{ 2809 struct wpa_supplicant *wpa_s = user_data; 2810 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count; 2811 2812 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2813 &expire_count, error); 2814} 2815 2816 2817/** 2818 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count 2819 * @iter: Pointer to incoming dbus message iter 2820 * @error: Location to store error on failure 2821 * @user_data: Function specific data 2822 * Returns: TRUE on success, FALSE on failure 2823 * 2824 * Setter function for "BSSExpireCount" property. 2825 */ 2826dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter, 2827 DBusError *error, 2828 void *user_data) 2829{ 2830 struct wpa_supplicant *wpa_s = user_data; 2831 dbus_uint32_t expire_count; 2832 2833 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2834 &expire_count)) 2835 return FALSE; 2836 2837 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) { 2838 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2839 "BSSExpireCount must be > 0"); 2840 return FALSE; 2841 } 2842 return TRUE; 2843} 2844 2845 2846/** 2847 * wpas_dbus_getter_country - Control country code 2848 * @iter: Pointer to incoming dbus message iter 2849 * @error: Location to store error on failure 2850 * @user_data: Function specific data 2851 * Returns: TRUE on success, FALSE on failure 2852 * 2853 * Getter function for "Country" property. 2854 */ 2855dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error, 2856 void *user_data) 2857{ 2858 struct wpa_supplicant *wpa_s = user_data; 2859 char country[3]; 2860 char *str = country; 2861 2862 country[0] = wpa_s->conf->country[0]; 2863 country[1] = wpa_s->conf->country[1]; 2864 country[2] = '\0'; 2865 2866 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2867 &str, error); 2868} 2869 2870 2871/** 2872 * wpas_dbus_setter_country - Control country code 2873 * @iter: Pointer to incoming dbus message iter 2874 * @error: Location to store error on failure 2875 * @user_data: Function specific data 2876 * Returns: TRUE on success, FALSE on failure 2877 * 2878 * Setter function for "Country" property. 2879 */ 2880dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error, 2881 void *user_data) 2882{ 2883 struct wpa_supplicant *wpa_s = user_data; 2884 const char *country; 2885 2886 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, 2887 &country)) 2888 return FALSE; 2889 2890 if (!country[0] || !country[1]) { 2891 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2892 "invalid country code"); 2893 return FALSE; 2894 } 2895 2896 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) { 2897 wpa_printf(MSG_DEBUG, "Failed to set country"); 2898 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2899 "failed to set country code"); 2900 return FALSE; 2901 } 2902 2903 wpa_s->conf->country[0] = country[0]; 2904 wpa_s->conf->country[1] = country[1]; 2905 return TRUE; 2906} 2907 2908 2909/** 2910 * wpas_dbus_getter_scan_interval - Get scan interval 2911 * @iter: Pointer to incoming dbus message iter 2912 * @error: Location to store error on failure 2913 * @user_data: Function specific data 2914 * Returns: TRUE on success, FALSE on failure 2915 * 2916 * Getter function for "ScanInterval" property. 2917 */ 2918dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter, 2919 DBusError *error, 2920 void *user_data) 2921{ 2922 struct wpa_supplicant *wpa_s = user_data; 2923 dbus_int32_t scan_interval = wpa_s->scan_interval; 2924 2925 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 2926 &scan_interval, error); 2927} 2928 2929 2930/** 2931 * wpas_dbus_setter_scan_interval - Control scan interval 2932 * @iter: Pointer to incoming dbus message iter 2933 * @error: Location to store error on failure 2934 * @user_data: Function specific data 2935 * Returns: TRUE on success, FALSE on failure 2936 * 2937 * Setter function for "ScanInterval" property. 2938 */ 2939dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter, 2940 DBusError *error, 2941 void *user_data) 2942{ 2943 struct wpa_supplicant *wpa_s = user_data; 2944 dbus_int32_t scan_interval; 2945 2946 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32, 2947 &scan_interval)) 2948 return FALSE; 2949 2950 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) { 2951 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2952 "scan_interval must be >= 0"); 2953 return FALSE; 2954 } 2955 return TRUE; 2956} 2957 2958 2959/** 2960 * wpas_dbus_getter_ifname - Get interface name 2961 * @iter: Pointer to incoming dbus message iter 2962 * @error: Location to store error on failure 2963 * @user_data: Function specific data 2964 * Returns: TRUE on success, FALSE on failure 2965 * 2966 * Getter for "Ifname" property. 2967 */ 2968dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error, 2969 void *user_data) 2970{ 2971 struct wpa_supplicant *wpa_s = user_data; 2972 const char *ifname = wpa_s->ifname; 2973 2974 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2975 &ifname, error); 2976} 2977 2978 2979/** 2980 * wpas_dbus_getter_driver - Get interface name 2981 * @iter: Pointer to incoming dbus message iter 2982 * @error: Location to store error on failure 2983 * @user_data: Function specific data 2984 * Returns: TRUE on success, FALSE on failure 2985 * 2986 * Getter for "Driver" property. 2987 */ 2988dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error, 2989 void *user_data) 2990{ 2991 struct wpa_supplicant *wpa_s = user_data; 2992 const char *driver; 2993 2994 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) { 2995 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: " 2996 "wpa_s has no driver set"); 2997 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set", 2998 __func__); 2999 return FALSE; 3000 } 3001 3002 driver = wpa_s->driver->name; 3003 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3004 &driver, error); 3005} 3006 3007 3008/** 3009 * wpas_dbus_getter_current_bss - Get current bss object path 3010 * @iter: Pointer to incoming dbus message iter 3011 * @error: Location to store error on failure 3012 * @user_data: Function specific data 3013 * Returns: TRUE on success, FALSE on failure 3014 * 3015 * Getter for "CurrentBSS" property. 3016 */ 3017dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter, 3018 DBusError *error, 3019 void *user_data) 3020{ 3021 struct wpa_supplicant *wpa_s = user_data; 3022 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf; 3023 3024 if (wpa_s->current_bss) 3025 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3026 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 3027 wpa_s->dbus_new_path, wpa_s->current_bss->id); 3028 else 3029 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 3030 3031 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 3032 &bss_obj_path, error); 3033} 3034 3035 3036/** 3037 * wpas_dbus_getter_current_network - Get current network object path 3038 * @iter: Pointer to incoming dbus message iter 3039 * @error: Location to store error on failure 3040 * @user_data: Function specific data 3041 * Returns: TRUE on success, FALSE on failure 3042 * 3043 * Getter for "CurrentNetwork" property. 3044 */ 3045dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter, 3046 DBusError *error, 3047 void *user_data) 3048{ 3049 struct wpa_supplicant *wpa_s = user_data; 3050 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf; 3051 3052 if (wpa_s->current_ssid) 3053 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3054 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 3055 wpa_s->dbus_new_path, wpa_s->current_ssid->id); 3056 else 3057 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 3058 3059 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 3060 &net_obj_path, error); 3061} 3062 3063 3064/** 3065 * wpas_dbus_getter_current_auth_mode - Get current authentication type 3066 * @iter: Pointer to incoming dbus message iter 3067 * @error: Location to store error on failure 3068 * @user_data: Function specific data 3069 * Returns: TRUE on success, FALSE on failure 3070 * 3071 * Getter for "CurrentAuthMode" property. 3072 */ 3073dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter, 3074 DBusError *error, 3075 void *user_data) 3076{ 3077 struct wpa_supplicant *wpa_s = user_data; 3078 const char *eap_mode; 3079 const char *auth_mode; 3080 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX]; 3081 3082 if (wpa_s->wpa_state != WPA_COMPLETED) { 3083 auth_mode = "INACTIVE"; 3084 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || 3085 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 3086 eap_mode = wpa_supplicant_get_eap_mode(wpa_s); 3087 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX, 3088 "EAP-%s", eap_mode); 3089 auth_mode = eap_mode_buf; 3090 3091 } else { 3092 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt, 3093 wpa_s->current_ssid->proto); 3094 } 3095 3096 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3097 &auth_mode, error); 3098} 3099 3100 3101/** 3102 * wpas_dbus_getter_bridge_ifname - Get interface name 3103 * @iter: Pointer to incoming dbus message iter 3104 * @error: Location to store error on failure 3105 * @user_data: Function specific data 3106 * Returns: TRUE on success, FALSE on failure 3107 * 3108 * Getter for "BridgeIfname" property. 3109 */ 3110dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter, 3111 DBusError *error, 3112 void *user_data) 3113{ 3114 struct wpa_supplicant *wpa_s = user_data; 3115 const char *bridge_ifname = wpa_s->bridge_ifname; 3116 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3117 &bridge_ifname, error); 3118} 3119 3120 3121/** 3122 * wpas_dbus_getter_bsss - Get array of BSSs objects 3123 * @iter: Pointer to incoming dbus message iter 3124 * @error: Location to store error on failure 3125 * @user_data: Function specific data 3126 * Returns: TRUE on success, FALSE on failure 3127 * 3128 * Getter for "BSSs" property. 3129 */ 3130dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error, 3131 void *user_data) 3132{ 3133 struct wpa_supplicant *wpa_s = user_data; 3134 struct wpa_bss *bss; 3135 char **paths; 3136 unsigned int i = 0; 3137 dbus_bool_t success = FALSE; 3138 3139 paths = os_calloc(wpa_s->num_bss, sizeof(char *)); 3140 if (!paths) { 3141 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3142 return FALSE; 3143 } 3144 3145 /* Loop through scan results and append each result's object path */ 3146 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 3147 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 3148 if (paths[i] == NULL) { 3149 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 3150 "no memory"); 3151 goto out; 3152 } 3153 /* Construct the object path for this BSS. */ 3154 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 3155 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 3156 wpa_s->dbus_new_path, bss->id); 3157 } 3158 3159 success = wpas_dbus_simple_array_property_getter(iter, 3160 DBUS_TYPE_OBJECT_PATH, 3161 paths, wpa_s->num_bss, 3162 error); 3163 3164out: 3165 while (i) 3166 os_free(paths[--i]); 3167 os_free(paths); 3168 return success; 3169} 3170 3171 3172/** 3173 * wpas_dbus_getter_networks - Get array of networks objects 3174 * @iter: Pointer to incoming dbus message iter 3175 * @error: Location to store error on failure 3176 * @user_data: Function specific data 3177 * Returns: TRUE on success, FALSE on failure 3178 * 3179 * Getter for "Networks" property. 3180 */ 3181dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error, 3182 void *user_data) 3183{ 3184 struct wpa_supplicant *wpa_s = user_data; 3185 struct wpa_ssid *ssid; 3186 char **paths; 3187 unsigned int i = 0, num = 0; 3188 dbus_bool_t success = FALSE; 3189 3190 if (wpa_s->conf == NULL) { 3191 wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting " 3192 "networks list.", __func__); 3193 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error " 3194 "occurred getting the networks list", __func__); 3195 return FALSE; 3196 } 3197 3198 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 3199 if (!network_is_persistent_group(ssid)) 3200 num++; 3201 3202 paths = os_calloc(num, sizeof(char *)); 3203 if (!paths) { 3204 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3205 return FALSE; 3206 } 3207 3208 /* Loop through configured networks and append object path of each */ 3209 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 3210 if (network_is_persistent_group(ssid)) 3211 continue; 3212 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 3213 if (paths[i] == NULL) { 3214 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3215 goto out; 3216 } 3217 3218 /* Construct the object path for this network. */ 3219 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 3220 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 3221 wpa_s->dbus_new_path, ssid->id); 3222 } 3223 3224 success = wpas_dbus_simple_array_property_getter(iter, 3225 DBUS_TYPE_OBJECT_PATH, 3226 paths, num, error); 3227 3228out: 3229 while (i) 3230 os_free(paths[--i]); 3231 os_free(paths); 3232 return success; 3233} 3234 3235 3236/** 3237 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path 3238 * @iter: Pointer to incoming dbus message iter 3239 * @error: Location to store error on failure 3240 * @user_data: Function specific data 3241 * Returns: A dbus message containing the PKCS #11 engine path 3242 * 3243 * Getter for "PKCS11EnginePath" property. 3244 */ 3245dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter, 3246 DBusError *error, 3247 void *user_data) 3248{ 3249 struct wpa_supplicant *wpa_s = user_data; 3250 const char *pkcs11_engine_path; 3251 3252 if (wpa_s->conf == NULL) { 3253 wpa_printf(MSG_ERROR, 3254 "wpas_dbus_getter_pkcs11_engine_path[dbus]: An " 3255 "error occurred getting the PKCS #11 engine path."); 3256 dbus_set_error_const( 3257 error, DBUS_ERROR_FAILED, 3258 "An error occured getting the PKCS #11 engine path."); 3259 return FALSE; 3260 } 3261 3262 if (wpa_s->conf->pkcs11_engine_path == NULL) 3263 pkcs11_engine_path = ""; 3264 else 3265 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; 3266 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3267 &pkcs11_engine_path, error); 3268} 3269 3270 3271/** 3272 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path 3273 * @iter: Pointer to incoming dbus message iter 3274 * @error: Location to store error on failure 3275 * @user_data: Function specific data 3276 * Returns: A dbus message containing the PKCS #11 module path 3277 * 3278 * Getter for "PKCS11ModulePath" property. 3279 */ 3280dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter, 3281 DBusError *error, 3282 void *user_data) 3283{ 3284 struct wpa_supplicant *wpa_s = user_data; 3285 const char *pkcs11_module_path; 3286 3287 if (wpa_s->conf == NULL) { 3288 wpa_printf(MSG_ERROR, 3289 "wpas_dbus_getter_pkcs11_module_path[dbus]: An " 3290 "error occurred getting the PKCS #11 module path."); 3291 dbus_set_error_const( 3292 error, DBUS_ERROR_FAILED, 3293 "An error occured getting the PKCS #11 module path."); 3294 return FALSE; 3295 } 3296 3297 if (wpa_s->conf->pkcs11_module_path == NULL) 3298 pkcs11_module_path = ""; 3299 else 3300 pkcs11_module_path = wpa_s->conf->pkcs11_module_path; 3301 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3302 &pkcs11_module_path, error); 3303} 3304 3305 3306/** 3307 * wpas_dbus_getter_blobs - Get all blobs defined for this interface 3308 * @iter: Pointer to incoming dbus message iter 3309 * @error: Location to store error on failure 3310 * @user_data: Function specific data 3311 * Returns: TRUE on success, FALSE on failure 3312 * 3313 * Getter for "Blobs" property. 3314 */ 3315dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error, 3316 void *user_data) 3317{ 3318 struct wpa_supplicant *wpa_s = user_data; 3319 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter; 3320 struct wpa_config_blob *blob; 3321 3322 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3323 "a{say}", &variant_iter) || 3324 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 3325 "{say}", &dict_iter)) { 3326 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3327 return FALSE; 3328 } 3329 3330 blob = wpa_s->conf->blobs; 3331 while (blob) { 3332 if (!dbus_message_iter_open_container(&dict_iter, 3333 DBUS_TYPE_DICT_ENTRY, 3334 NULL, &entry_iter) || 3335 !dbus_message_iter_append_basic(&entry_iter, 3336 DBUS_TYPE_STRING, 3337 &(blob->name)) || 3338 !dbus_message_iter_open_container(&entry_iter, 3339 DBUS_TYPE_ARRAY, 3340 DBUS_TYPE_BYTE_AS_STRING, 3341 &array_iter) || 3342 !dbus_message_iter_append_fixed_array(&array_iter, 3343 DBUS_TYPE_BYTE, 3344 &(blob->data), 3345 blob->len) || 3346 !dbus_message_iter_close_container(&entry_iter, 3347 &array_iter) || 3348 !dbus_message_iter_close_container(&dict_iter, 3349 &entry_iter)) { 3350 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 3351 "no memory"); 3352 return FALSE; 3353 } 3354 3355 blob = blob->next; 3356 } 3357 3358 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) || 3359 !dbus_message_iter_close_container(iter, &variant_iter)) { 3360 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3361 return FALSE; 3362 } 3363 3364 return TRUE; 3365} 3366 3367 3368static struct wpa_bss * get_bss_helper(struct bss_handler_args *args, 3369 DBusError *error, const char *func_name) 3370{ 3371 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id); 3372 3373 if (!res) { 3374 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found", 3375 func_name, args->id); 3376 dbus_set_error(error, DBUS_ERROR_FAILED, 3377 "%s: BSS %d not found", 3378 func_name, args->id); 3379 } 3380 3381 return res; 3382} 3383 3384 3385/** 3386 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS 3387 * @iter: Pointer to incoming dbus message iter 3388 * @error: Location to store error on failure 3389 * @user_data: Function specific data 3390 * Returns: TRUE on success, FALSE on failure 3391 * 3392 * Getter for "BSSID" property. 3393 */ 3394dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error, 3395 void *user_data) 3396{ 3397 struct bss_handler_args *args = user_data; 3398 struct wpa_bss *res; 3399 3400 res = get_bss_helper(args, error, __func__); 3401 if (!res) 3402 return FALSE; 3403 3404 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3405 res->bssid, ETH_ALEN, 3406 error); 3407} 3408 3409 3410/** 3411 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS 3412 * @iter: Pointer to incoming dbus message iter 3413 * @error: Location to store error on failure 3414 * @user_data: Function specific data 3415 * Returns: TRUE on success, FALSE on failure 3416 * 3417 * Getter for "SSID" property. 3418 */ 3419dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error, 3420 void *user_data) 3421{ 3422 struct bss_handler_args *args = user_data; 3423 struct wpa_bss *res; 3424 3425 res = get_bss_helper(args, error, __func__); 3426 if (!res) 3427 return FALSE; 3428 3429 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3430 res->ssid, res->ssid_len, 3431 error); 3432} 3433 3434 3435/** 3436 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS 3437 * @iter: Pointer to incoming dbus message iter 3438 * @error: Location to store error on failure 3439 * @user_data: Function specific data 3440 * Returns: TRUE on success, FALSE on failure 3441 * 3442 * Getter for "Privacy" property. 3443 */ 3444dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter, 3445 DBusError *error, void *user_data) 3446{ 3447 struct bss_handler_args *args = user_data; 3448 struct wpa_bss *res; 3449 dbus_bool_t privacy; 3450 3451 res = get_bss_helper(args, error, __func__); 3452 if (!res) 3453 return FALSE; 3454 3455 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE; 3456 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3457 &privacy, error); 3458} 3459 3460 3461/** 3462 * wpas_dbus_getter_bss_mode - Return the mode of a BSS 3463 * @iter: Pointer to incoming dbus message iter 3464 * @error: Location to store error on failure 3465 * @user_data: Function specific data 3466 * Returns: TRUE on success, FALSE on failure 3467 * 3468 * Getter for "Mode" property. 3469 */ 3470dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error, 3471 void *user_data) 3472{ 3473 struct bss_handler_args *args = user_data; 3474 struct wpa_bss *res; 3475 const char *mode; 3476 3477 res = get_bss_helper(args, error, __func__); 3478 if (!res) 3479 return FALSE; 3480 3481 if (res->caps & IEEE80211_CAP_IBSS) 3482 mode = "ad-hoc"; 3483 else 3484 mode = "infrastructure"; 3485 3486 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3487 &mode, error); 3488} 3489 3490 3491/** 3492 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS 3493 * @iter: Pointer to incoming dbus message iter 3494 * @error: Location to store error on failure 3495 * @user_data: Function specific data 3496 * Returns: TRUE on success, FALSE on failure 3497 * 3498 * Getter for "Level" property. 3499 */ 3500dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter, 3501 DBusError *error, void *user_data) 3502{ 3503 struct bss_handler_args *args = user_data; 3504 struct wpa_bss *res; 3505 s16 level; 3506 3507 res = get_bss_helper(args, error, __func__); 3508 if (!res) 3509 return FALSE; 3510 3511 level = (s16) res->level; 3512 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16, 3513 &level, error); 3514} 3515 3516 3517/** 3518 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS 3519 * @iter: Pointer to incoming dbus message iter 3520 * @error: Location to store error on failure 3521 * @user_data: Function specific data 3522 * Returns: TRUE on success, FALSE on failure 3523 * 3524 * Getter for "Frequency" property. 3525 */ 3526dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter, 3527 DBusError *error, void *user_data) 3528{ 3529 struct bss_handler_args *args = user_data; 3530 struct wpa_bss *res; 3531 u16 freq; 3532 3533 res = get_bss_helper(args, error, __func__); 3534 if (!res) 3535 return FALSE; 3536 3537 freq = (u16) res->freq; 3538 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 3539 &freq, error); 3540} 3541 3542 3543static int cmp_u8s_desc(const void *a, const void *b) 3544{ 3545 return (*(u8 *) b - *(u8 *) a); 3546} 3547 3548 3549/** 3550 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS 3551 * @iter: Pointer to incoming dbus message iter 3552 * @error: Location to store error on failure 3553 * @user_data: Function specific data 3554 * Returns: TRUE on success, FALSE on failure 3555 * 3556 * Getter for "Rates" property. 3557 */ 3558dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter, 3559 DBusError *error, void *user_data) 3560{ 3561 struct bss_handler_args *args = user_data; 3562 struct wpa_bss *res; 3563 u8 *ie_rates = NULL; 3564 u32 *real_rates; 3565 int rates_num, i; 3566 dbus_bool_t success = FALSE; 3567 3568 res = get_bss_helper(args, error, __func__); 3569 if (!res) 3570 return FALSE; 3571 3572 rates_num = wpa_bss_get_bit_rates(res, &ie_rates); 3573 if (rates_num < 0) 3574 return FALSE; 3575 3576 qsort(ie_rates, rates_num, 1, cmp_u8s_desc); 3577 3578 real_rates = os_malloc(sizeof(u32) * rates_num); 3579 if (!real_rates) { 3580 os_free(ie_rates); 3581 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3582 return FALSE; 3583 } 3584 3585 for (i = 0; i < rates_num; i++) 3586 real_rates[i] = ie_rates[i] * 500000; 3587 3588 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32, 3589 real_rates, rates_num, 3590 error); 3591 3592 os_free(ie_rates); 3593 os_free(real_rates); 3594 return success; 3595} 3596 3597 3598static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, 3599 struct wpa_ie_data *ie_data, 3600 DBusError *error) 3601{ 3602 DBusMessageIter iter_dict, variant_iter; 3603 const char *group; 3604 const char *pairwise[3]; /* max 3 pairwise ciphers is supported */ 3605 const char *key_mgmt[7]; /* max 7 key managements may be supported */ 3606 int n; 3607 3608 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3609 "a{sv}", &variant_iter)) 3610 goto nomem; 3611 3612 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 3613 goto nomem; 3614 3615 /* KeyMgmt */ 3616 n = 0; 3617 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK) 3618 key_mgmt[n++] = "wpa-psk"; 3619 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK) 3620 key_mgmt[n++] = "wpa-ft-psk"; 3621 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 3622 key_mgmt[n++] = "wpa-psk-sha256"; 3623 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X) 3624 key_mgmt[n++] = "wpa-eap"; 3625 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 3626 key_mgmt[n++] = "wpa-ft-eap"; 3627 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 3628 key_mgmt[n++] = "wpa-eap-sha256"; 3629 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE) 3630 key_mgmt[n++] = "wpa-none"; 3631 3632 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt", 3633 key_mgmt, n)) 3634 goto nomem; 3635 3636 /* Group */ 3637 switch (ie_data->group_cipher) { 3638 case WPA_CIPHER_WEP40: 3639 group = "wep40"; 3640 break; 3641 case WPA_CIPHER_TKIP: 3642 group = "tkip"; 3643 break; 3644 case WPA_CIPHER_CCMP: 3645 group = "ccmp"; 3646 break; 3647 case WPA_CIPHER_GCMP: 3648 group = "gcmp"; 3649 break; 3650 case WPA_CIPHER_WEP104: 3651 group = "wep104"; 3652 break; 3653 default: 3654 group = ""; 3655 break; 3656 } 3657 3658 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group)) 3659 goto nomem; 3660 3661 /* Pairwise */ 3662 n = 0; 3663 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP) 3664 pairwise[n++] = "tkip"; 3665 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP) 3666 pairwise[n++] = "ccmp"; 3667 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP) 3668 pairwise[n++] = "gcmp"; 3669 3670 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise", 3671 pairwise, n)) 3672 goto nomem; 3673 3674 /* Management group (RSN only) */ 3675 if (ie_data->proto == WPA_PROTO_RSN) { 3676 switch (ie_data->mgmt_group_cipher) { 3677#ifdef CONFIG_IEEE80211W 3678 case WPA_CIPHER_AES_128_CMAC: 3679 group = "aes128cmac"; 3680 break; 3681#endif /* CONFIG_IEEE80211W */ 3682 default: 3683 group = ""; 3684 break; 3685 } 3686 3687 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup", 3688 group)) 3689 goto nomem; 3690 } 3691 3692 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) 3693 goto nomem; 3694 if (!dbus_message_iter_close_container(iter, &variant_iter)) 3695 goto nomem; 3696 3697 return TRUE; 3698 3699nomem: 3700 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3701 return FALSE; 3702} 3703 3704 3705/** 3706 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS 3707 * @iter: Pointer to incoming dbus message iter 3708 * @error: Location to store error on failure 3709 * @user_data: Function specific data 3710 * Returns: TRUE on success, FALSE on failure 3711 * 3712 * Getter for "WPA" property. 3713 */ 3714dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error, 3715 void *user_data) 3716{ 3717 struct bss_handler_args *args = user_data; 3718 struct wpa_bss *res; 3719 struct wpa_ie_data wpa_data; 3720 const u8 *ie; 3721 3722 res = get_bss_helper(args, error, __func__); 3723 if (!res) 3724 return FALSE; 3725 3726 os_memset(&wpa_data, 0, sizeof(wpa_data)); 3727 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); 3728 if (ie) { 3729 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { 3730 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3731 "failed to parse WPA IE"); 3732 return FALSE; 3733 } 3734 } 3735 3736 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error); 3737} 3738 3739 3740/** 3741 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS 3742 * @iter: Pointer to incoming dbus message iter 3743 * @error: Location to store error on failure 3744 * @user_data: Function specific data 3745 * Returns: TRUE on success, FALSE on failure 3746 * 3747 * Getter for "RSN" property. 3748 */ 3749dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error, 3750 void *user_data) 3751{ 3752 struct bss_handler_args *args = user_data; 3753 struct wpa_bss *res; 3754 struct wpa_ie_data wpa_data; 3755 const u8 *ie; 3756 3757 res = get_bss_helper(args, error, __func__); 3758 if (!res) 3759 return FALSE; 3760 3761 os_memset(&wpa_data, 0, sizeof(wpa_data)); 3762 ie = wpa_bss_get_ie(res, WLAN_EID_RSN); 3763 if (ie) { 3764 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { 3765 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3766 "failed to parse RSN IE"); 3767 return FALSE; 3768 } 3769 } 3770 3771 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error); 3772} 3773 3774 3775/** 3776 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS 3777 * @iter: Pointer to incoming dbus message iter 3778 * @error: Location to store error on failure 3779 * @user_data: Function specific data 3780 * Returns: TRUE on success, FALSE on failure 3781 * 3782 * Getter for "WPS" property. 3783 */ 3784dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error, 3785 void *user_data) 3786{ 3787 struct bss_handler_args *args = user_data; 3788 struct wpa_bss *res; 3789#ifdef CONFIG_WPS 3790 struct wpabuf *wps_ie; 3791#endif /* CONFIG_WPS */ 3792 DBusMessageIter iter_dict, variant_iter; 3793 const char *type = ""; 3794 3795 res = get_bss_helper(args, error, __func__); 3796 if (!res) 3797 return FALSE; 3798 3799 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3800 "a{sv}", &variant_iter)) 3801 goto nomem; 3802 3803 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 3804 goto nomem; 3805 3806#ifdef CONFIG_WPS 3807 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE); 3808 if (wps_ie) { 3809 if (wps_is_selected_pbc_registrar(wps_ie)) 3810 type = "pbc"; 3811 else if (wps_is_selected_pin_registrar(wps_ie)) 3812 type = "pin"; 3813 } 3814#endif /* CONFIG_WPS */ 3815 3816 if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type)) 3817 goto nomem; 3818 3819 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) 3820 goto nomem; 3821 if (!dbus_message_iter_close_container(iter, &variant_iter)) 3822 goto nomem; 3823 3824 return TRUE; 3825 3826nomem: 3827 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3828 return FALSE; 3829} 3830 3831 3832/** 3833 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS 3834 * @iter: Pointer to incoming dbus message iter 3835 * @error: Location to store error on failure 3836 * @user_data: Function specific data 3837 * Returns: TRUE on success, FALSE on failure 3838 * 3839 * Getter for "IEs" property. 3840 */ 3841dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error, 3842 void *user_data) 3843{ 3844 struct bss_handler_args *args = user_data; 3845 struct wpa_bss *res; 3846 3847 res = get_bss_helper(args, error, __func__); 3848 if (!res) 3849 return FALSE; 3850 3851 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3852 res + 1, res->ie_len, 3853 error); 3854} 3855 3856 3857/** 3858 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled 3859 * @iter: Pointer to incoming dbus message iter 3860 * @error: Location to store error on failure 3861 * @user_data: Function specific data 3862 * Returns: TRUE on success, FALSE on failure 3863 * 3864 * Getter for "enabled" property of a configured network. 3865 */ 3866dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error, 3867 void *user_data) 3868{ 3869 struct network_handler_args *net = user_data; 3870 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE; 3871 3872 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3873 &enabled, error); 3874} 3875 3876 3877/** 3878 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled 3879 * @iter: Pointer to incoming dbus message iter 3880 * @error: Location to store error on failure 3881 * @user_data: Function specific data 3882 * Returns: TRUE on success, FALSE on failure 3883 * 3884 * Setter for "Enabled" property of a configured network. 3885 */ 3886dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error, 3887 void *user_data) 3888{ 3889 struct network_handler_args *net = user_data; 3890 struct wpa_supplicant *wpa_s; 3891 struct wpa_ssid *ssid; 3892 dbus_bool_t enable; 3893 3894 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 3895 &enable)) 3896 return FALSE; 3897 3898 wpa_s = net->wpa_s; 3899 ssid = net->ssid; 3900 3901 if (enable) 3902 wpa_supplicant_enable_network(wpa_s, ssid); 3903 else 3904 wpa_supplicant_disable_network(wpa_s, ssid); 3905 3906 return TRUE; 3907} 3908 3909 3910/** 3911 * wpas_dbus_getter_network_properties - Get options for a configured network 3912 * @iter: Pointer to incoming dbus message iter 3913 * @error: Location to store error on failure 3914 * @user_data: Function specific data 3915 * Returns: TRUE on success, FALSE on failure 3916 * 3917 * Getter for "Properties" property of a configured network. 3918 */ 3919dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter, 3920 DBusError *error, 3921 void *user_data) 3922{ 3923 struct network_handler_args *net = user_data; 3924 DBusMessageIter variant_iter, dict_iter; 3925 char **iterator; 3926 char **props = wpa_config_get_all(net->ssid, 1); 3927 dbus_bool_t success = FALSE; 3928 3929 if (!props) { 3930 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3931 return FALSE; 3932 } 3933 3934 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}", 3935 &variant_iter) || 3936 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) { 3937 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3938 goto out; 3939 } 3940 3941 iterator = props; 3942 while (*iterator) { 3943 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator, 3944 *(iterator + 1))) { 3945 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 3946 "no memory"); 3947 goto out; 3948 } 3949 iterator += 2; 3950 } 3951 3952 3953 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || 3954 !dbus_message_iter_close_container(iter, &variant_iter)) { 3955 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3956 goto out; 3957 } 3958 3959 success = TRUE; 3960 3961out: 3962 iterator = props; 3963 while (*iterator) { 3964 os_free(*iterator); 3965 iterator++; 3966 } 3967 os_free(props); 3968 return success; 3969} 3970 3971 3972/** 3973 * wpas_dbus_setter_network_properties - Set options for a configured network 3974 * @iter: Pointer to incoming dbus message iter 3975 * @error: Location to store error on failure 3976 * @user_data: Function specific data 3977 * Returns: TRUE on success, FALSE on failure 3978 * 3979 * Setter for "Properties" property of a configured network. 3980 */ 3981dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter, 3982 DBusError *error, 3983 void *user_data) 3984{ 3985 struct network_handler_args *net = user_data; 3986 struct wpa_ssid *ssid = net->ssid; 3987 DBusMessageIter variant_iter; 3988 3989 dbus_message_iter_recurse(iter, &variant_iter); 3990 return set_network_properties(net->wpa_s, ssid, &variant_iter, error); 3991} 3992 3993 3994#ifdef CONFIG_AP 3995 3996DBusMessage * wpas_dbus_handler_subscribe_preq( 3997 DBusMessage *message, struct wpa_supplicant *wpa_s) 3998{ 3999 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 4000 char *name; 4001 4002 if (wpa_s->preq_notify_peer != NULL) { 4003 if (os_strcmp(dbus_message_get_sender(message), 4004 wpa_s->preq_notify_peer) == 0) 4005 return NULL; 4006 4007 return dbus_message_new_error(message, 4008 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE, 4009 "Another application is already subscribed"); 4010 } 4011 4012 name = os_strdup(dbus_message_get_sender(message)); 4013 if (!name) 4014 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 4015 "out of memory"); 4016 4017 wpa_s->preq_notify_peer = name; 4018 4019 /* Subscribe to clean up if application closes socket */ 4020 wpas_dbus_subscribe_noc(priv); 4021 4022 /* 4023 * Double-check it's still alive to make sure that we didn't 4024 * miss the NameOwnerChanged signal, e.g. while strdup'ing. 4025 */ 4026 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) { 4027 /* 4028 * Application no longer exists, clean up. 4029 * The return value is irrelevant now. 4030 * 4031 * Need to check if the NameOwnerChanged handling 4032 * already cleaned up because we have processed 4033 * DBus messages while checking if the name still 4034 * has an owner. 4035 */ 4036 if (!wpa_s->preq_notify_peer) 4037 return NULL; 4038 os_free(wpa_s->preq_notify_peer); 4039 wpa_s->preq_notify_peer = NULL; 4040 wpas_dbus_unsubscribe_noc(priv); 4041 } 4042 4043 return NULL; 4044} 4045 4046 4047DBusMessage * wpas_dbus_handler_unsubscribe_preq( 4048 DBusMessage *message, struct wpa_supplicant *wpa_s) 4049{ 4050 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 4051 4052 if (!wpa_s->preq_notify_peer) 4053 return dbus_message_new_error(message, 4054 WPAS_DBUS_ERROR_NO_SUBSCRIPTION, 4055 "Not subscribed"); 4056 4057 if (os_strcmp(wpa_s->preq_notify_peer, 4058 dbus_message_get_sender(message))) 4059 return dbus_message_new_error(message, 4060 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM, 4061 "Can't unsubscribe others"); 4062 4063 os_free(wpa_s->preq_notify_peer); 4064 wpa_s->preq_notify_peer = NULL; 4065 wpas_dbus_unsubscribe_noc(priv); 4066 return NULL; 4067} 4068 4069 4070void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s, 4071 const u8 *addr, const u8 *dst, const u8 *bssid, 4072 const u8 *ie, size_t ie_len, u32 ssi_signal) 4073{ 4074 DBusMessage *msg; 4075 DBusMessageIter iter, dict_iter; 4076 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 4077 4078 /* Do nothing if the control interface is not turned on */ 4079 if (priv == NULL) 4080 return; 4081 4082 if (wpa_s->preq_notify_peer == NULL) 4083 return; 4084 4085 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 4086 WPAS_DBUS_NEW_IFACE_INTERFACE, 4087 "ProbeRequest"); 4088 if (msg == NULL) 4089 return; 4090 4091 dbus_message_set_destination(msg, wpa_s->preq_notify_peer); 4092 4093 dbus_message_iter_init_append(msg, &iter); 4094 4095 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) 4096 goto fail; 4097 if (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr", 4098 (const char *) addr, 4099 ETH_ALEN)) 4100 goto fail; 4101 if (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst", 4102 (const char *) dst, 4103 ETH_ALEN)) 4104 goto fail; 4105 if (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid", 4106 (const char *) bssid, 4107 ETH_ALEN)) 4108 goto fail; 4109 if (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies", 4110 (const char *) ie, 4111 ie_len)) 4112 goto fail; 4113 if (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal", 4114 ssi_signal)) 4115 goto fail; 4116 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) 4117 goto fail; 4118 4119 dbus_connection_send(priv->con, msg, NULL); 4120 goto out; 4121fail: 4122 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 4123out: 4124 dbus_message_unref(msg); 4125} 4126 4127#endif /* CONFIG_AP */ 4128