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