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