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