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