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