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