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