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