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