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