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