1 /* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc. 4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa (at) gmail.com> 5 * Copyright (c) 2009-2015, Jouni Malinen <j (at) w1.fi> 6 * 7 * This software may be distributed under the terms of the BSD license. 8 * See README for more details. 9 */ 10 11 #include "includes.h" 12 13 #include "common.h" 14 #include "common/ieee802_11_defs.h" 15 #include "eap_peer/eap_methods.h" 16 #include "eapol_supp/eapol_supp_sm.h" 17 #include "rsn_supp/wpa.h" 18 #include "../config.h" 19 #include "../wpa_supplicant_i.h" 20 #include "../driver_i.h" 21 #include "../notify.h" 22 #include "../bss.h" 23 #include "../scan.h" 24 #include "../autoscan.h" 25 #include "dbus_new_helpers.h" 26 #include "dbus_new.h" 27 #include "dbus_new_handlers.h" 28 #include "dbus_dict_helpers.h" 29 #include "dbus_common_i.h" 30 #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 if (wpa_supplicant_trigger_scan(wpa_s, 1345 ¶ms)) { 1346 reply = wpas_dbus_error_scan_error( 1347 message, 1348 "Scan request rejected"); 1349 } 1350 } else { 1351 wpa_s->scan_req = MANUAL_SCAN_REQ; 1352 wpa_supplicant_req_scan(wpa_s, 0, 0); 1353 } 1354 } 1355 } else if (os_strcmp(type, "active") == 0) { 1356 if (!params.num_ssids) { 1357 /* Add wildcard ssid */ 1358 params.num_ssids++; 1359 } 1360 #ifdef CONFIG_AUTOSCAN 1361 autoscan_deinit(wpa_s); 1362 #endif /* CONFIG_AUTOSCAN */ 1363 if (wpa_s->sched_scanning) { 1364 wpa_printf(MSG_DEBUG, 1365 "%s[dbus]: Stop ongoing sched_scan to allow requested scan to proceed", 1366 __func__); 1367 wpa_supplicant_cancel_sched_scan(wpa_s); 1368 } 1369 1370 if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) { 1371 reply = wpas_dbus_error_scan_error( 1372 message, "Scan request rejected"); 1373 } 1374 } else { 1375 wpa_printf(MSG_DEBUG, "%s[dbus]: Unknown scan type: %s", 1376 __func__, type); 1377 reply = wpas_dbus_error_invalid_args(message, 1378 "Wrong scan type"); 1379 goto out; 1380 } 1381 1382 if (!allow_roam) 1383 wpa_s->scan_res_handler = scan_only_handler; 1384 1385 out: 1386 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++) 1387 os_free((u8 *) params.ssids[i].ssid); 1388 os_free((u8 *) params.extra_ies); 1389 os_free(params.freqs); 1390 return reply; 1391 } 1392 1393 1394 /** 1395 * wpas_dbus_handler_signal_poll - Request immediate signal properties 1396 * @message: Pointer to incoming dbus message 1397 * @wpa_s: wpa_supplicant structure for a network interface 1398 * Returns: NULL indicating success or DBus error message on failure 1399 * 1400 * Handler function for "SignalPoll" method call of a network device. Requests 1401 * that wpa_supplicant read signal properties like RSSI, noise, and link 1402 * speed and return them. 1403 */ 1404 DBusMessage * wpas_dbus_handler_signal_poll(DBusMessage *message, 1405 struct wpa_supplicant *wpa_s) 1406 { 1407 struct wpa_signal_info si; 1408 DBusMessage *reply = NULL; 1409 DBusMessageIter iter, iter_dict, variant_iter; 1410 int ret; 1411 1412 ret = wpa_drv_signal_poll(wpa_s, &si); 1413 if (ret) { 1414 return dbus_message_new_error(message, DBUS_ERROR_FAILED, 1415 "Failed to read signal"); 1416 } 1417 1418 reply = dbus_message_new_method_return(message); 1419 if (reply == NULL) 1420 goto nomem; 1421 1422 dbus_message_iter_init_append(reply, &iter); 1423 1424 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, 1425 "a{sv}", &variant_iter) || 1426 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict) || 1427 !wpa_dbus_dict_append_int32(&iter_dict, "rssi", 1428 si.current_signal) || 1429 !wpa_dbus_dict_append_int32(&iter_dict, "linkspeed", 1430 si.current_txrate / 1000) || 1431 !wpa_dbus_dict_append_int32(&iter_dict, "noise", 1432 si.current_noise) || 1433 !wpa_dbus_dict_append_uint32(&iter_dict, "frequency", 1434 si.frequency) || 1435 (si.chanwidth != CHAN_WIDTH_UNKNOWN && 1436 !wpa_dbus_dict_append_string( 1437 &iter_dict, "width", 1438 channel_width_to_string(si.chanwidth))) || 1439 (si.center_frq1 > 0 && si.center_frq2 > 0 && 1440 (!wpa_dbus_dict_append_int32(&iter_dict, "center-frq1", 1441 si.center_frq1) || 1442 !wpa_dbus_dict_append_int32(&iter_dict, "center-frq2", 1443 si.center_frq2))) || 1444 (si.avg_signal && 1445 !wpa_dbus_dict_append_int32(&iter_dict, "avg-rssi", 1446 si.avg_signal)) || 1447 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || 1448 !dbus_message_iter_close_container(&iter, &variant_iter)) 1449 goto nomem; 1450 1451 return reply; 1452 1453 nomem: 1454 if (reply) 1455 dbus_message_unref(reply); 1456 return wpas_dbus_error_no_memory(message); 1457 } 1458 1459 1460 /* 1461 * wpas_dbus_handler_disconnect - Terminate the current connection 1462 * @message: Pointer to incoming dbus message 1463 * @wpa_s: wpa_supplicant structure for a network interface 1464 * Returns: NotConnected DBus error message if already not connected 1465 * or NULL otherwise. 1466 * 1467 * Handler function for "Disconnect" method call of network interface. 1468 */ 1469 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message, 1470 struct wpa_supplicant *wpa_s) 1471 { 1472 if (wpa_s->current_ssid != NULL) { 1473 wpa_s->disconnected = 1; 1474 wpa_supplicant_deauthenticate(wpa_s, 1475 WLAN_REASON_DEAUTH_LEAVING); 1476 1477 return NULL; 1478 } 1479 1480 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED, 1481 "This interface is not connected"); 1482 } 1483 1484 1485 /** 1486 * wpas_dbus_new_iface_add_network - Add a new configured network 1487 * @message: Pointer to incoming dbus message 1488 * @wpa_s: wpa_supplicant structure for a network interface 1489 * Returns: A dbus message containing the object path of the new network 1490 * 1491 * Handler function for "AddNetwork" method call of a network interface. 1492 */ 1493 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message, 1494 struct wpa_supplicant *wpa_s) 1495 { 1496 DBusMessage *reply = NULL; 1497 DBusMessageIter iter; 1498 struct wpa_ssid *ssid = NULL; 1499 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 1500 DBusError error; 1501 1502 dbus_message_iter_init(message, &iter); 1503 1504 if (wpa_s->dbus_new_path) 1505 ssid = wpa_config_add_network(wpa_s->conf); 1506 if (ssid == NULL) { 1507 wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.", 1508 __func__); 1509 reply = wpas_dbus_error_unknown_error( 1510 message, 1511 "wpa_supplicant could not add a network on this interface."); 1512 goto err; 1513 } 1514 wpas_notify_network_added(wpa_s, ssid); 1515 ssid->disabled = 1; 1516 wpa_config_set_network_defaults(ssid); 1517 1518 dbus_error_init(&error); 1519 if (!set_network_properties(wpa_s, ssid, &iter, &error)) { 1520 wpa_printf(MSG_DEBUG, 1521 "%s[dbus]: control interface couldn't set network properties", 1522 __func__); 1523 reply = wpas_dbus_reply_new_from_error(message, &error, 1524 DBUS_ERROR_INVALID_ARGS, 1525 "Failed to add network"); 1526 dbus_error_free(&error); 1527 goto err; 1528 } 1529 1530 /* Construct the object path for this network. */ 1531 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 1532 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 1533 wpa_s->dbus_new_path, ssid->id); 1534 1535 reply = dbus_message_new_method_return(message); 1536 if (reply == NULL) { 1537 reply = wpas_dbus_error_no_memory(message); 1538 goto err; 1539 } 1540 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, 1541 DBUS_TYPE_INVALID)) { 1542 dbus_message_unref(reply); 1543 reply = wpas_dbus_error_no_memory(message); 1544 goto err; 1545 } 1546 1547 return reply; 1548 1549 err: 1550 if (ssid) { 1551 wpas_notify_network_removed(wpa_s, ssid); 1552 wpa_config_remove_network(wpa_s->conf, ssid->id); 1553 } 1554 return reply; 1555 } 1556 1557 1558 /** 1559 * wpas_dbus_handler_reassociate - Reassociate 1560 * @message: Pointer to incoming dbus message 1561 * @wpa_s: wpa_supplicant structure for a network interface 1562 * Returns: InterfaceDisabled DBus error message if disabled 1563 * or NULL otherwise. 1564 * 1565 * Handler function for "Reassociate" method call of network interface. 1566 */ 1567 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message, 1568 struct wpa_supplicant *wpa_s) 1569 { 1570 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) { 1571 wpas_request_connection(wpa_s); 1572 return NULL; 1573 } 1574 1575 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_DISABLED, 1576 "This interface is disabled"); 1577 } 1578 1579 1580 /** 1581 * wpas_dbus_handler_reattach - Reattach to current AP 1582 * @message: Pointer to incoming dbus message 1583 * @wpa_s: wpa_supplicant structure for a network interface 1584 * Returns: NotConnected DBus error message if not connected 1585 * or NULL otherwise. 1586 * 1587 * Handler function for "Reattach" method call of network interface. 1588 */ 1589 DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message, 1590 struct wpa_supplicant *wpa_s) 1591 { 1592 if (wpa_s->current_ssid != NULL) { 1593 wpa_s->reattach = 1; 1594 wpas_request_connection(wpa_s); 1595 return NULL; 1596 } 1597 1598 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED, 1599 "This interface is not connected"); 1600 } 1601 1602 1603 /** 1604 * wpas_dbus_handler_reconnect - Reconnect if disconnected 1605 * @message: Pointer to incoming dbus message 1606 * @wpa_s: wpa_supplicant structure for a network interface 1607 * Returns: InterfaceDisabled DBus error message if disabled 1608 * or NULL otherwise. 1609 * 1610 * Handler function for "Reconnect" method call of network interface. 1611 */ 1612 DBusMessage * wpas_dbus_handler_reconnect(DBusMessage *message, 1613 struct wpa_supplicant *wpa_s) 1614 { 1615 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { 1616 return dbus_message_new_error(message, 1617 WPAS_DBUS_ERROR_IFACE_DISABLED, 1618 "This interface is disabled"); 1619 } 1620 1621 if (wpa_s->disconnected) 1622 wpas_request_connection(wpa_s); 1623 return NULL; 1624 } 1625 1626 1627 /** 1628 * wpas_dbus_handler_remove_network - Remove a configured network 1629 * @message: Pointer to incoming dbus message 1630 * @wpa_s: wpa_supplicant structure for a network interface 1631 * Returns: NULL on success or dbus error on failure 1632 * 1633 * Handler function for "RemoveNetwork" method call of a network interface. 1634 */ 1635 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message, 1636 struct wpa_supplicant *wpa_s) 1637 { 1638 DBusMessage *reply = NULL; 1639 const char *op; 1640 char *iface, *net_id; 1641 int id; 1642 struct wpa_ssid *ssid; 1643 int was_disabled; 1644 1645 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 1646 DBUS_TYPE_INVALID); 1647 1648 /* Extract the network ID and ensure the network */ 1649 /* is actually a child of this interface */ 1650 iface = wpas_dbus_new_decompose_object_path(op, 1651 WPAS_DBUS_NEW_NETWORKS_PART, 1652 &net_id); 1653 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path || 1654 os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 1655 reply = wpas_dbus_error_invalid_args(message, op); 1656 goto out; 1657 } 1658 1659 errno = 0; 1660 id = strtoul(net_id, NULL, 10); 1661 if (errno != 0) { 1662 reply = wpas_dbus_error_invalid_args(message, op); 1663 goto out; 1664 } 1665 1666 ssid = wpa_config_get_network(wpa_s->conf, id); 1667 if (ssid == NULL) { 1668 reply = wpas_dbus_error_network_unknown(message); 1669 goto out; 1670 } 1671 1672 was_disabled = ssid->disabled; 1673 1674 wpas_notify_network_removed(wpa_s, ssid); 1675 1676 if (ssid == wpa_s->current_ssid) 1677 wpa_supplicant_deauthenticate(wpa_s, 1678 WLAN_REASON_DEAUTH_LEAVING); 1679 else if (!was_disabled && wpa_s->sched_scanning) { 1680 wpa_printf(MSG_DEBUG, 1681 "Stop ongoing sched_scan to remove network from filters"); 1682 wpa_supplicant_cancel_sched_scan(wpa_s); 1683 wpa_supplicant_req_scan(wpa_s, 0, 0); 1684 } 1685 1686 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 1687 wpa_printf(MSG_ERROR, 1688 "%s[dbus]: error occurred when removing network %d", 1689 __func__, id); 1690 reply = wpas_dbus_error_unknown_error( 1691 message, 1692 "error removing the specified network on is interface."); 1693 goto out; 1694 } 1695 1696 out: 1697 os_free(iface); 1698 return reply; 1699 } 1700 1701 1702 static void remove_network(void *arg, struct wpa_ssid *ssid) 1703 { 1704 struct wpa_supplicant *wpa_s = arg; 1705 1706 wpas_notify_network_removed(wpa_s, ssid); 1707 1708 if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) { 1709 wpa_printf(MSG_ERROR, 1710 "%s[dbus]: error occurred when removing network %d", 1711 __func__, ssid->id); 1712 return; 1713 } 1714 1715 if (ssid == wpa_s->current_ssid) 1716 wpa_supplicant_deauthenticate(wpa_s, 1717 WLAN_REASON_DEAUTH_LEAVING); 1718 } 1719 1720 1721 /** 1722 * wpas_dbus_handler_remove_all_networks - Remove all configured networks 1723 * @message: Pointer to incoming dbus message 1724 * @wpa_s: wpa_supplicant structure for a network interface 1725 * Returns: NULL on success or dbus error on failure 1726 * 1727 * Handler function for "RemoveAllNetworks" method call of a network interface. 1728 */ 1729 DBusMessage * wpas_dbus_handler_remove_all_networks( 1730 DBusMessage *message, struct wpa_supplicant *wpa_s) 1731 { 1732 if (wpa_s->sched_scanning) 1733 wpa_supplicant_cancel_sched_scan(wpa_s); 1734 1735 /* NB: could check for failure and return an error */ 1736 wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s); 1737 return NULL; 1738 } 1739 1740 1741 /** 1742 * wpas_dbus_handler_select_network - Attempt association with a network 1743 * @message: Pointer to incoming dbus message 1744 * @wpa_s: wpa_supplicant structure for a network interface 1745 * Returns: NULL on success or dbus error on failure 1746 * 1747 * Handler function for "SelectNetwork" method call of network interface. 1748 */ 1749 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message, 1750 struct wpa_supplicant *wpa_s) 1751 { 1752 DBusMessage *reply = NULL; 1753 const char *op; 1754 char *iface, *net_id; 1755 int id; 1756 struct wpa_ssid *ssid; 1757 1758 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 1759 DBUS_TYPE_INVALID); 1760 1761 /* Extract the network ID and ensure the network */ 1762 /* is actually a child of this interface */ 1763 iface = wpas_dbus_new_decompose_object_path(op, 1764 WPAS_DBUS_NEW_NETWORKS_PART, 1765 &net_id); 1766 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path || 1767 os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 1768 reply = wpas_dbus_error_invalid_args(message, op); 1769 goto out; 1770 } 1771 1772 errno = 0; 1773 id = strtoul(net_id, NULL, 10); 1774 if (errno != 0) { 1775 reply = wpas_dbus_error_invalid_args(message, op); 1776 goto out; 1777 } 1778 1779 ssid = wpa_config_get_network(wpa_s->conf, id); 1780 if (ssid == NULL) { 1781 reply = wpas_dbus_error_network_unknown(message); 1782 goto out; 1783 } 1784 1785 /* Finally, associate with the network */ 1786 wpa_supplicant_select_network(wpa_s, ssid); 1787 1788 out: 1789 os_free(iface); 1790 return reply; 1791 } 1792 1793 1794 /** 1795 * wpas_dbus_handler_network_reply - Reply to a NetworkRequest signal 1796 * @message: Pointer to incoming dbus message 1797 * @wpa_s: wpa_supplicant structure for a network interface 1798 * Returns: NULL on success or dbus error on failure 1799 * 1800 * Handler function for "NetworkReply" method call of network interface. 1801 */ 1802 DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message, 1803 struct wpa_supplicant *wpa_s) 1804 { 1805 #ifdef IEEE8021X_EAPOL 1806 DBusMessage *reply = NULL; 1807 const char *op, *field, *value; 1808 char *iface, *net_id; 1809 int id; 1810 struct wpa_ssid *ssid; 1811 1812 if (!dbus_message_get_args(message, NULL, 1813 DBUS_TYPE_OBJECT_PATH, &op, 1814 DBUS_TYPE_STRING, &field, 1815 DBUS_TYPE_STRING, &value, 1816 DBUS_TYPE_INVALID)) 1817 return wpas_dbus_error_invalid_args(message, NULL); 1818 1819 /* Extract the network ID and ensure the network */ 1820 /* is actually a child of this interface */ 1821 iface = wpas_dbus_new_decompose_object_path(op, 1822 WPAS_DBUS_NEW_NETWORKS_PART, 1823 &net_id); 1824 if (iface == NULL || net_id == NULL || !wpa_s->dbus_new_path || 1825 os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 1826 reply = wpas_dbus_error_invalid_args(message, op); 1827 goto out; 1828 } 1829 1830 errno = 0; 1831 id = strtoul(net_id, NULL, 10); 1832 if (errno != 0) { 1833 reply = wpas_dbus_error_invalid_args(message, net_id); 1834 goto out; 1835 } 1836 1837 ssid = wpa_config_get_network(wpa_s->conf, id); 1838 if (ssid == NULL) { 1839 reply = wpas_dbus_error_network_unknown(message); 1840 goto out; 1841 } 1842 1843 if (wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, 1844 field, value) < 0) 1845 reply = wpas_dbus_error_invalid_args(message, field); 1846 else { 1847 /* Tell EAP to retry immediately */ 1848 eapol_sm_notify_ctrl_response(wpa_s->eapol); 1849 } 1850 1851 out: 1852 os_free(iface); 1853 return reply; 1854 #else /* IEEE8021X_EAPOL */ 1855 wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); 1856 return wpas_dbus_error_unknown_error(message, "802.1X not included"); 1857 #endif /* IEEE8021X_EAPOL */ 1858 } 1859 1860 1861 #ifndef CONFIG_NO_CONFIG_BLOBS 1862 1863 /** 1864 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates) 1865 * @message: Pointer to incoming dbus message 1866 * @wpa_s: %wpa_supplicant data structure 1867 * Returns: A dbus message containing an error on failure or NULL on success 1868 * 1869 * Asks wpa_supplicant to internally store a binary blobs. 1870 */ 1871 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message, 1872 struct wpa_supplicant *wpa_s) 1873 { 1874 DBusMessage *reply = NULL; 1875 DBusMessageIter iter, array_iter; 1876 1877 char *blob_name; 1878 u8 *blob_data; 1879 int blob_len; 1880 struct wpa_config_blob *blob = NULL; 1881 1882 dbus_message_iter_init(message, &iter); 1883 dbus_message_iter_get_basic(&iter, &blob_name); 1884 1885 if (wpa_config_get_blob(wpa_s->conf, blob_name)) { 1886 return dbus_message_new_error(message, 1887 WPAS_DBUS_ERROR_BLOB_EXISTS, 1888 NULL); 1889 } 1890 1891 dbus_message_iter_next(&iter); 1892 dbus_message_iter_recurse(&iter, &array_iter); 1893 1894 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len); 1895 1896 blob = os_zalloc(sizeof(*blob)); 1897 if (!blob) { 1898 reply = wpas_dbus_error_no_memory(message); 1899 goto err; 1900 } 1901 1902 blob->data = os_malloc(blob_len); 1903 blob->name = os_strdup(blob_name); 1904 if (!blob->data || !blob->name) { 1905 reply = wpas_dbus_error_no_memory(message); 1906 goto err; 1907 } 1908 os_memcpy(blob->data, blob_data, blob_len); 1909 blob->len = blob_len; 1910 1911 wpa_config_set_blob(wpa_s->conf, blob); 1912 wpas_notify_blob_added(wpa_s, blob->name); 1913 1914 return reply; 1915 1916 err: 1917 if (blob) { 1918 os_free(blob->name); 1919 os_free(blob->data); 1920 os_free(blob); 1921 } 1922 return reply; 1923 } 1924 1925 1926 /** 1927 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates) 1928 * @message: Pointer to incoming dbus message 1929 * @wpa_s: %wpa_supplicant data structure 1930 * Returns: A dbus message containing array of bytes (blob) 1931 * 1932 * Gets one wpa_supplicant's binary blobs. 1933 */ 1934 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message, 1935 struct wpa_supplicant *wpa_s) 1936 { 1937 DBusMessage *reply = NULL; 1938 DBusMessageIter iter, array_iter; 1939 1940 char *blob_name; 1941 const struct wpa_config_blob *blob; 1942 1943 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name, 1944 DBUS_TYPE_INVALID); 1945 1946 blob = wpa_config_get_blob(wpa_s->conf, blob_name); 1947 if (!blob) { 1948 return dbus_message_new_error(message, 1949 WPAS_DBUS_ERROR_BLOB_UNKNOWN, 1950 "Blob id not set"); 1951 } 1952 1953 reply = dbus_message_new_method_return(message); 1954 if (!reply) 1955 return wpas_dbus_error_no_memory(message); 1956 1957 dbus_message_iter_init_append(reply, &iter); 1958 1959 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 1960 DBUS_TYPE_BYTE_AS_STRING, 1961 &array_iter) || 1962 !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE, 1963 &(blob->data), blob->len) || 1964 !dbus_message_iter_close_container(&iter, &array_iter)) { 1965 dbus_message_unref(reply); 1966 reply = wpas_dbus_error_no_memory(message); 1967 } 1968 1969 return reply; 1970 } 1971 1972 1973 /** 1974 * wpas_remove_handler_remove_blob - Remove named binary blob 1975 * @message: Pointer to incoming dbus message 1976 * @wpa_s: %wpa_supplicant data structure 1977 * Returns: NULL on success or dbus error 1978 * 1979 * Asks wpa_supplicant to internally remove a binary blobs. 1980 */ 1981 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message, 1982 struct wpa_supplicant *wpa_s) 1983 { 1984 DBusMessage *reply = NULL; 1985 char *blob_name; 1986 1987 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name, 1988 DBUS_TYPE_INVALID); 1989 1990 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) { 1991 return dbus_message_new_error(message, 1992 WPAS_DBUS_ERROR_BLOB_UNKNOWN, 1993 "Blob id not set"); 1994 } 1995 wpas_notify_blob_removed(wpa_s, blob_name); 1996 1997 return reply; 1998 1999 } 2000 2001 #endif /* CONFIG_NO_CONFIG_BLOBS */ 2002 2003 2004 /* 2005 * wpas_dbus_handler_flush_bss - Flush the BSS cache 2006 * @message: Pointer to incoming dbus message 2007 * @wpa_s: wpa_supplicant structure for a network interface 2008 * Returns: NULL 2009 * 2010 * Handler function for "FlushBSS" method call of network interface. 2011 */ 2012 DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message, 2013 struct wpa_supplicant *wpa_s) 2014 { 2015 dbus_uint32_t age; 2016 2017 dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age, 2018 DBUS_TYPE_INVALID); 2019 2020 if (age == 0) 2021 wpa_bss_flush(wpa_s); 2022 else 2023 wpa_bss_flush_by_age(wpa_s, age); 2024 2025 return NULL; 2026 } 2027 2028 2029 #ifdef CONFIG_AUTOSCAN 2030 /** 2031 * wpas_dbus_handler_autoscan - Set autoscan parameters for the interface 2032 * @message: Pointer to incoming dbus message 2033 * @wpa_s: wpa_supplicant structure for a network interface 2034 * Returns: NULL 2035 * 2036 * Handler function for "AutoScan" method call of network interface. 2037 */ 2038 DBusMessage * wpas_dbus_handler_autoscan(DBusMessage *message, 2039 struct wpa_supplicant *wpa_s) 2040 { 2041 DBusMessage *reply = NULL; 2042 enum wpa_states state = wpa_s->wpa_state; 2043 char *arg; 2044 2045 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, 2046 DBUS_TYPE_INVALID); 2047 2048 if (arg != NULL && os_strlen(arg) > 0) { 2049 char *tmp; 2050 2051 tmp = os_strdup(arg); 2052 if (tmp == NULL) { 2053 reply = wpas_dbus_error_no_memory(message); 2054 } else { 2055 os_free(wpa_s->conf->autoscan); 2056 wpa_s->conf->autoscan = tmp; 2057 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) 2058 autoscan_init(wpa_s, 1); 2059 else if (state == WPA_SCANNING) 2060 wpa_supplicant_reinit_autoscan(wpa_s); 2061 } 2062 } else if (arg != NULL && os_strlen(arg) == 0) { 2063 os_free(wpa_s->conf->autoscan); 2064 wpa_s->conf->autoscan = NULL; 2065 autoscan_deinit(wpa_s); 2066 } else 2067 reply = dbus_message_new_error(message, 2068 DBUS_ERROR_INVALID_ARGS, 2069 NULL); 2070 2071 return reply; 2072 } 2073 #endif /* CONFIG_AUTOSCAN */ 2074 2075 2076 /* 2077 * wpas_dbus_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff 2078 * @message: Pointer to incoming dbus message 2079 * @wpa_s: wpa_supplicant structure for a network interface 2080 * Returns: NULL 2081 * 2082 * Handler function for "EAPLogoff" method call of network interface. 2083 */ 2084 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message, 2085 struct wpa_supplicant *wpa_s) 2086 { 2087 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 2088 return NULL; 2089 } 2090 2091 2092 /* 2093 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon 2094 * @message: Pointer to incoming dbus message 2095 * @wpa_s: wpa_supplicant structure for a network interface 2096 * Returns: NULL 2097 * 2098 * Handler function for "EAPLogin" method call of network interface. 2099 */ 2100 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message, 2101 struct wpa_supplicant *wpa_s) 2102 { 2103 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 2104 return NULL; 2105 } 2106 2107 2108 #ifdef CONFIG_TDLS 2109 2110 static int get_peer_hwaddr_helper(DBusMessage *message, const char *func_name, 2111 u8 *peer_address, DBusMessage **error) 2112 { 2113 const char *peer_string; 2114 2115 *error = NULL; 2116 2117 if (!dbus_message_get_args(message, NULL, 2118 DBUS_TYPE_STRING, &peer_string, 2119 DBUS_TYPE_INVALID)) { 2120 *error = wpas_dbus_error_invalid_args(message, NULL); 2121 return -1; 2122 } 2123 2124 if (hwaddr_aton(peer_string, peer_address)) { 2125 wpa_printf(MSG_DEBUG, "%s: invalid address '%s'", 2126 func_name, peer_string); 2127 *error = wpas_dbus_error_invalid_args( 2128 message, "Invalid hardware address format"); 2129 return -1; 2130 } 2131 2132 return 0; 2133 } 2134 2135 2136 /* 2137 * wpas_dbus_handler_tdls_discover - Discover TDLS peer 2138 * @message: Pointer to incoming dbus message 2139 * @wpa_s: wpa_supplicant structure for a network interface 2140 * Returns: NULL indicating success or DBus error message on failure 2141 * 2142 * Handler function for "TDLSDiscover" method call of network interface. 2143 */ 2144 DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message, 2145 struct wpa_supplicant *wpa_s) 2146 { 2147 u8 peer[ETH_ALEN]; 2148 DBusMessage *error_reply; 2149 int ret; 2150 2151 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0) 2152 return error_reply; 2153 2154 wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer)); 2155 2156 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2157 ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); 2158 else 2159 ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); 2160 2161 if (ret) { 2162 return wpas_dbus_error_unknown_error( 2163 message, "error performing TDLS discovery"); 2164 } 2165 2166 return NULL; 2167 } 2168 2169 2170 /* 2171 * wpas_dbus_handler_tdls_setup - Setup TDLS session 2172 * @message: Pointer to incoming dbus message 2173 * @wpa_s: wpa_supplicant structure for a network interface 2174 * Returns: NULL indicating success or DBus error message on failure 2175 * 2176 * Handler function for "TDLSSetup" method call of network interface. 2177 */ 2178 DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message, 2179 struct wpa_supplicant *wpa_s) 2180 { 2181 u8 peer[ETH_ALEN]; 2182 DBusMessage *error_reply; 2183 int ret; 2184 2185 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0) 2186 return error_reply; 2187 2188 wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer)); 2189 2190 wpa_tdls_remove(wpa_s->wpa, peer); 2191 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2192 ret = wpa_tdls_start(wpa_s->wpa, peer); 2193 else 2194 ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); 2195 2196 if (ret) { 2197 return wpas_dbus_error_unknown_error( 2198 message, "error performing TDLS setup"); 2199 } 2200 2201 return NULL; 2202 } 2203 2204 2205 /* 2206 * wpas_dbus_handler_tdls_status - Return TDLS session status 2207 * @message: Pointer to incoming dbus message 2208 * @wpa_s: wpa_supplicant structure for a network interface 2209 * Returns: A string representing the state of the link to this TDLS peer 2210 * 2211 * Handler function for "TDLSStatus" method call of network interface. 2212 */ 2213 DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message, 2214 struct wpa_supplicant *wpa_s) 2215 { 2216 u8 peer[ETH_ALEN]; 2217 DBusMessage *reply; 2218 const char *tdls_status; 2219 2220 if (get_peer_hwaddr_helper(message, __func__, peer, &reply) < 0) 2221 return reply; 2222 2223 wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer)); 2224 2225 tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer); 2226 2227 reply = dbus_message_new_method_return(message); 2228 dbus_message_append_args(reply, DBUS_TYPE_STRING, 2229 &tdls_status, DBUS_TYPE_INVALID); 2230 return reply; 2231 } 2232 2233 2234 /* 2235 * wpas_dbus_handler_tdls_teardown - Teardown TDLS session 2236 * @message: Pointer to incoming dbus message 2237 * @wpa_s: wpa_supplicant structure for a network interface 2238 * Returns: NULL indicating success or DBus error message on failure 2239 * 2240 * Handler function for "TDLSTeardown" method call of network interface. 2241 */ 2242 DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message, 2243 struct wpa_supplicant *wpa_s) 2244 { 2245 u8 peer[ETH_ALEN]; 2246 DBusMessage *error_reply; 2247 int ret; 2248 2249 if (get_peer_hwaddr_helper(message, __func__, peer, &error_reply) < 0) 2250 return error_reply; 2251 2252 wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer)); 2253 2254 if (wpa_tdls_is_external_setup(wpa_s->wpa)) 2255 ret = wpa_tdls_teardown_link( 2256 wpa_s->wpa, peer, 2257 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); 2258 else 2259 ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); 2260 2261 if (ret) { 2262 return wpas_dbus_error_unknown_error( 2263 message, "error performing TDLS teardown"); 2264 } 2265 2266 return NULL; 2267 } 2268 2269 #endif /* CONFIG_TDLS */ 2270 2271 2272 /** 2273 * wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path 2274 * @message: Pointer to incoming dbus message 2275 * @wpa_s: %wpa_supplicant data structure 2276 * Returns: A dbus message containing an error on failure or NULL on success 2277 * 2278 * Sets the PKCS #11 engine and module path. 2279 */ 2280 DBusMessage * wpas_dbus_handler_set_pkcs11_engine_and_module_path( 2281 DBusMessage *message, struct wpa_supplicant *wpa_s) 2282 { 2283 DBusMessageIter iter; 2284 char *value = NULL; 2285 char *pkcs11_engine_path = NULL; 2286 char *pkcs11_module_path = NULL; 2287 2288 dbus_message_iter_init(message, &iter); 2289 dbus_message_iter_get_basic(&iter, &value); 2290 if (value == NULL) { 2291 return dbus_message_new_error( 2292 message, DBUS_ERROR_INVALID_ARGS, 2293 "Invalid pkcs11_engine_path argument"); 2294 } 2295 /* Empty path defaults to NULL */ 2296 if (os_strlen(value)) 2297 pkcs11_engine_path = value; 2298 2299 dbus_message_iter_next(&iter); 2300 dbus_message_iter_get_basic(&iter, &value); 2301 if (value == NULL) { 2302 os_free(pkcs11_engine_path); 2303 return dbus_message_new_error( 2304 message, DBUS_ERROR_INVALID_ARGS, 2305 "Invalid pkcs11_module_path argument"); 2306 } 2307 /* Empty path defaults to NULL */ 2308 if (os_strlen(value)) 2309 pkcs11_module_path = value; 2310 2311 if (wpas_set_pkcs11_engine_and_module_path(wpa_s, pkcs11_engine_path, 2312 pkcs11_module_path)) 2313 return dbus_message_new_error( 2314 message, DBUS_ERROR_FAILED, 2315 "Reinit of the EAPOL state machine with the new PKCS #11 engine and module path failed."); 2316 2317 if (wpa_s->dbus_new_path) { 2318 wpa_dbus_mark_property_changed( 2319 wpa_s->global->dbus, wpa_s->dbus_new_path, 2320 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11EnginePath"); 2321 wpa_dbus_mark_property_changed( 2322 wpa_s->global->dbus, wpa_s->dbus_new_path, 2323 WPAS_DBUS_NEW_IFACE_INTERFACE, "PKCS11ModulePath"); 2324 } 2325 2326 return NULL; 2327 } 2328 2329 2330 /** 2331 * wpas_dbus_getter_capabilities - Return interface capabilities 2332 * @iter: Pointer to incoming dbus message iter 2333 * @error: Location to store error on failure 2334 * @user_data: Function specific data 2335 * Returns: TRUE on success, FALSE on failure 2336 * 2337 * Getter for "Capabilities" property of an interface. 2338 */ 2339 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter, 2340 DBusError *error, void *user_data) 2341 { 2342 struct wpa_supplicant *wpa_s = user_data; 2343 struct wpa_driver_capa capa; 2344 int res; 2345 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array, 2346 variant_iter; 2347 const char *scans[] = { "active", "passive", "ssid" }; 2348 2349 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 2350 "a{sv}", &variant_iter) || 2351 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 2352 goto nomem; 2353 2354 res = wpa_drv_get_capa(wpa_s, &capa); 2355 2356 /***** pairwise cipher */ 2357 if (res < 0) { 2358 const char *args[] = {"ccmp", "tkip", "none"}; 2359 2360 if (!wpa_dbus_dict_append_string_array( 2361 &iter_dict, "Pairwise", args, 2362 ARRAY_SIZE(args))) 2363 goto nomem; 2364 } else { 2365 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise", 2366 &iter_dict_entry, 2367 &iter_dict_val, 2368 &iter_array) || 2369 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) && 2370 !wpa_dbus_dict_string_array_add_element( 2371 &iter_array, "ccmp-256")) || 2372 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) && 2373 !wpa_dbus_dict_string_array_add_element( 2374 &iter_array, "gcmp-256")) || 2375 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) && 2376 !wpa_dbus_dict_string_array_add_element( 2377 &iter_array, "ccmp")) || 2378 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) && 2379 !wpa_dbus_dict_string_array_add_element( 2380 &iter_array, "gcmp")) || 2381 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && 2382 !wpa_dbus_dict_string_array_add_element( 2383 &iter_array, "tkip")) || 2384 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) && 2385 !wpa_dbus_dict_string_array_add_element( 2386 &iter_array, "none")) || 2387 !wpa_dbus_dict_end_string_array(&iter_dict, 2388 &iter_dict_entry, 2389 &iter_dict_val, 2390 &iter_array)) 2391 goto nomem; 2392 } 2393 2394 /***** group cipher */ 2395 if (res < 0) { 2396 const char *args[] = { 2397 "ccmp", "tkip", "wep104", "wep40" 2398 }; 2399 2400 if (!wpa_dbus_dict_append_string_array( 2401 &iter_dict, "Group", args, 2402 ARRAY_SIZE(args))) 2403 goto nomem; 2404 } else { 2405 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group", 2406 &iter_dict_entry, 2407 &iter_dict_val, 2408 &iter_array) || 2409 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) && 2410 !wpa_dbus_dict_string_array_add_element( 2411 &iter_array, "ccmp-256")) || 2412 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) && 2413 !wpa_dbus_dict_string_array_add_element( 2414 &iter_array, "gcmp-256")) || 2415 ((capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) && 2416 !wpa_dbus_dict_string_array_add_element( 2417 &iter_array, "ccmp")) || 2418 ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) && 2419 !wpa_dbus_dict_string_array_add_element( 2420 &iter_array, "gcmp")) || 2421 ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && 2422 !wpa_dbus_dict_string_array_add_element( 2423 &iter_array, "tkip")) || 2424 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) && 2425 !wpa_dbus_dict_string_array_add_element( 2426 &iter_array, "wep104")) || 2427 ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) && 2428 !wpa_dbus_dict_string_array_add_element( 2429 &iter_array, "wep40")) || 2430 !wpa_dbus_dict_end_string_array(&iter_dict, 2431 &iter_dict_entry, 2432 &iter_dict_val, 2433 &iter_array)) 2434 goto nomem; 2435 } 2436 2437 /***** key management */ 2438 if (res < 0) { 2439 const char *args[] = { 2440 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none", 2441 #ifdef CONFIG_WPS 2442 "wps", 2443 #endif /* CONFIG_WPS */ 2444 "none" 2445 }; 2446 if (!wpa_dbus_dict_append_string_array( 2447 &iter_dict, "KeyMgmt", args, 2448 ARRAY_SIZE(args))) 2449 goto nomem; 2450 } else { 2451 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt", 2452 &iter_dict_entry, 2453 &iter_dict_val, 2454 &iter_array) || 2455 !wpa_dbus_dict_string_array_add_element(&iter_array, 2456 "none") || 2457 !wpa_dbus_dict_string_array_add_element(&iter_array, 2458 "ieee8021x")) 2459 goto nomem; 2460 2461 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2462 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 2463 if (!wpa_dbus_dict_string_array_add_element( 2464 &iter_array, "wpa-eap") || 2465 ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) && 2466 !wpa_dbus_dict_string_array_add_element( 2467 &iter_array, "wpa-ft-eap"))) 2468 goto nomem; 2469 2470 /* TODO: Ensure that driver actually supports sha256 encryption. */ 2471 #ifdef CONFIG_IEEE80211W 2472 if (!wpa_dbus_dict_string_array_add_element( 2473 &iter_array, "wpa-eap-sha256")) 2474 goto nomem; 2475 #endif /* CONFIG_IEEE80211W */ 2476 } 2477 2478 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 2479 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2480 if (!wpa_dbus_dict_string_array_add_element( 2481 &iter_array, "wpa-psk") || 2482 ((capa.key_mgmt & 2483 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) && 2484 !wpa_dbus_dict_string_array_add_element( 2485 &iter_array, "wpa-ft-psk"))) 2486 goto nomem; 2487 2488 /* TODO: Ensure that driver actually supports sha256 encryption. */ 2489 #ifdef CONFIG_IEEE80211W 2490 if (!wpa_dbus_dict_string_array_add_element( 2491 &iter_array, "wpa-psk-sha256")) 2492 goto nomem; 2493 #endif /* CONFIG_IEEE80211W */ 2494 } 2495 2496 if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) && 2497 !wpa_dbus_dict_string_array_add_element(&iter_array, 2498 "wpa-none")) 2499 goto nomem; 2500 2501 2502 #ifdef CONFIG_WPS 2503 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 2504 "wps")) 2505 goto nomem; 2506 #endif /* CONFIG_WPS */ 2507 2508 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2509 &iter_dict_entry, 2510 &iter_dict_val, 2511 &iter_array)) 2512 goto nomem; 2513 } 2514 2515 /***** WPA protocol */ 2516 if (res < 0) { 2517 const char *args[] = { "rsn", "wpa" }; 2518 2519 if (!wpa_dbus_dict_append_string_array( 2520 &iter_dict, "Protocol", args, 2521 ARRAY_SIZE(args))) 2522 goto nomem; 2523 } else { 2524 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol", 2525 &iter_dict_entry, 2526 &iter_dict_val, 2527 &iter_array) || 2528 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 2529 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) && 2530 !wpa_dbus_dict_string_array_add_element( 2531 &iter_array, "rsn")) || 2532 ((capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2533 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) && 2534 !wpa_dbus_dict_string_array_add_element( 2535 &iter_array, "wpa")) || 2536 !wpa_dbus_dict_end_string_array(&iter_dict, 2537 &iter_dict_entry, 2538 &iter_dict_val, 2539 &iter_array)) 2540 goto nomem; 2541 } 2542 2543 /***** auth alg */ 2544 if (res < 0) { 2545 const char *args[] = { "open", "shared", "leap" }; 2546 2547 if (!wpa_dbus_dict_append_string_array( 2548 &iter_dict, "AuthAlg", args, 2549 ARRAY_SIZE(args))) 2550 goto nomem; 2551 } else { 2552 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg", 2553 &iter_dict_entry, 2554 &iter_dict_val, 2555 &iter_array)) 2556 goto nomem; 2557 2558 if (((capa.auth & WPA_DRIVER_AUTH_OPEN) && 2559 !wpa_dbus_dict_string_array_add_element( 2560 &iter_array, "open")) || 2561 ((capa.auth & WPA_DRIVER_AUTH_SHARED) && 2562 !wpa_dbus_dict_string_array_add_element( 2563 &iter_array, "shared")) || 2564 ((capa.auth & WPA_DRIVER_AUTH_LEAP) && 2565 !wpa_dbus_dict_string_array_add_element( 2566 &iter_array, "leap")) || 2567 !wpa_dbus_dict_end_string_array(&iter_dict, 2568 &iter_dict_entry, 2569 &iter_dict_val, 2570 &iter_array)) 2571 goto nomem; 2572 } 2573 2574 /***** Scan */ 2575 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans, 2576 ARRAY_SIZE(scans))) 2577 goto nomem; 2578 2579 /***** Modes */ 2580 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes", 2581 &iter_dict_entry, 2582 &iter_dict_val, 2583 &iter_array) || 2584 !wpa_dbus_dict_string_array_add_element( 2585 &iter_array, "infrastructure") || 2586 !wpa_dbus_dict_string_array_add_element( 2587 &iter_array, "ad-hoc") || 2588 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) && 2589 !wpa_dbus_dict_string_array_add_element( 2590 &iter_array, "ap")) || 2591 (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) && 2592 !wpa_dbus_dict_string_array_add_element( 2593 &iter_array, "p2p")) || 2594 !wpa_dbus_dict_end_string_array(&iter_dict, 2595 &iter_dict_entry, 2596 &iter_dict_val, 2597 &iter_array)) 2598 goto nomem; 2599 /***** Modes end */ 2600 2601 if (res >= 0) { 2602 dbus_int32_t max_scan_ssid = capa.max_scan_ssids; 2603 2604 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID", 2605 max_scan_ssid)) 2606 goto nomem; 2607 } 2608 2609 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || 2610 !dbus_message_iter_close_container(iter, &variant_iter)) 2611 goto nomem; 2612 2613 return TRUE; 2614 2615 nomem: 2616 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2617 return FALSE; 2618 } 2619 2620 2621 /** 2622 * wpas_dbus_getter_state - Get interface state 2623 * @iter: Pointer to incoming dbus message iter 2624 * @error: Location to store error on failure 2625 * @user_data: Function specific data 2626 * Returns: TRUE on success, FALSE on failure 2627 * 2628 * Getter for "State" property. 2629 */ 2630 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error, 2631 void *user_data) 2632 { 2633 struct wpa_supplicant *wpa_s = user_data; 2634 const char *str_state; 2635 char *state_ls, *tmp; 2636 dbus_bool_t success = FALSE; 2637 2638 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 2639 2640 /* make state string lowercase to fit new DBus API convention 2641 */ 2642 state_ls = tmp = os_strdup(str_state); 2643 if (!tmp) { 2644 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2645 return FALSE; 2646 } 2647 while (*tmp) { 2648 *tmp = tolower(*tmp); 2649 tmp++; 2650 } 2651 2652 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2653 &state_ls, error); 2654 2655 os_free(state_ls); 2656 2657 return success; 2658 } 2659 2660 2661 /** 2662 * wpas_dbus_new_iface_get_scanning - Get interface scanning state 2663 * @iter: Pointer to incoming dbus message iter 2664 * @error: Location to store error on failure 2665 * @user_data: Function specific data 2666 * Returns: TRUE on success, FALSE on failure 2667 * 2668 * Getter for "scanning" property. 2669 */ 2670 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error, 2671 void *user_data) 2672 { 2673 struct wpa_supplicant *wpa_s = user_data; 2674 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 2675 2676 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 2677 &scanning, error); 2678 } 2679 2680 2681 /** 2682 * wpas_dbus_getter_ap_scan - Control roaming mode 2683 * @iter: Pointer to incoming dbus message iter 2684 * @error: Location to store error on failure 2685 * @user_data: Function specific data 2686 * Returns: TRUE on success, FALSE on failure 2687 * 2688 * Getter function for "ApScan" property. 2689 */ 2690 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error, 2691 void *user_data) 2692 { 2693 struct wpa_supplicant *wpa_s = user_data; 2694 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan; 2695 2696 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2697 &ap_scan, error); 2698 } 2699 2700 2701 /** 2702 * wpas_dbus_setter_ap_scan - Control roaming mode 2703 * @iter: Pointer to incoming dbus message iter 2704 * @error: Location to store error on failure 2705 * @user_data: Function specific data 2706 * Returns: TRUE on success, FALSE on failure 2707 * 2708 * Setter function for "ApScan" property. 2709 */ 2710 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error, 2711 void *user_data) 2712 { 2713 struct wpa_supplicant *wpa_s = user_data; 2714 dbus_uint32_t ap_scan; 2715 2716 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2717 &ap_scan)) 2718 return FALSE; 2719 2720 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 2721 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2722 "ap_scan must be 0, 1, or 2"); 2723 return FALSE; 2724 } 2725 return TRUE; 2726 } 2727 2728 2729 /** 2730 * wpas_dbus_getter_fast_reauth - Control fast 2731 * reauthentication (TLS session resumption) 2732 * @iter: Pointer to incoming dbus message iter 2733 * @error: Location to store error on failure 2734 * @user_data: Function specific data 2735 * Returns: TRUE on success, FALSE on failure 2736 * 2737 * Getter function for "FastReauth" property. 2738 */ 2739 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter, 2740 DBusError *error, 2741 void *user_data) 2742 { 2743 struct wpa_supplicant *wpa_s = user_data; 2744 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE; 2745 2746 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 2747 &fast_reauth, error); 2748 } 2749 2750 2751 /** 2752 * wpas_dbus_setter_fast_reauth - Control fast 2753 * reauthentication (TLS session resumption) 2754 * @iter: Pointer to incoming dbus message iter 2755 * @error: Location to store error on failure 2756 * @user_data: Function specific data 2757 * Returns: TRUE on success, FALSE on failure 2758 * 2759 * Setter function for "FastReauth" property. 2760 */ 2761 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter, 2762 DBusError *error, 2763 void *user_data) 2764 { 2765 struct wpa_supplicant *wpa_s = user_data; 2766 dbus_bool_t fast_reauth; 2767 2768 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 2769 &fast_reauth)) 2770 return FALSE; 2771 2772 wpa_s->conf->fast_reauth = fast_reauth; 2773 return TRUE; 2774 } 2775 2776 2777 /** 2778 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect 2779 * @iter: Pointer to incoming dbus message iter 2780 * @error: Location to store error on failure 2781 * @user_data: Function specific data 2782 * Returns: TRUE on success, FALSE on failure 2783 * 2784 * Getter for "DisconnectReason" property. The reason is negative if it is 2785 * locally generated. 2786 */ 2787 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter, 2788 DBusError *error, 2789 void *user_data) 2790 { 2791 struct wpa_supplicant *wpa_s = user_data; 2792 dbus_int32_t reason = wpa_s->disconnect_reason; 2793 2794 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 2795 &reason, error); 2796 } 2797 2798 2799 /** 2800 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age 2801 * @iter: Pointer to incoming dbus message iter 2802 * @error: Location to store error on failure 2803 * @user_data: Function specific data 2804 * Returns: TRUE on success, FALSE on failure 2805 * 2806 * Getter function for "BSSExpireAge" property. 2807 */ 2808 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter, 2809 DBusError *error, 2810 void *user_data) 2811 { 2812 struct wpa_supplicant *wpa_s = user_data; 2813 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age; 2814 2815 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2816 &expire_age, error); 2817 } 2818 2819 2820 /** 2821 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age 2822 * @iter: Pointer to incoming dbus message iter 2823 * @error: Location to store error on failure 2824 * @user_data: Function specific data 2825 * Returns: TRUE on success, FALSE on failure 2826 * 2827 * Setter function for "BSSExpireAge" property. 2828 */ 2829 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter, 2830 DBusError *error, 2831 void *user_data) 2832 { 2833 struct wpa_supplicant *wpa_s = user_data; 2834 dbus_uint32_t expire_age; 2835 2836 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2837 &expire_age)) 2838 return FALSE; 2839 2840 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) { 2841 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2842 "BSSExpireAge must be >= 10"); 2843 return FALSE; 2844 } 2845 return TRUE; 2846 } 2847 2848 2849 /** 2850 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count 2851 * @iter: Pointer to incoming dbus message iter 2852 * @error: Location to store error on failure 2853 * @user_data: Function specific data 2854 * Returns: TRUE on success, FALSE on failure 2855 * 2856 * Getter function for "BSSExpireCount" property. 2857 */ 2858 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter, 2859 DBusError *error, 2860 void *user_data) 2861 { 2862 struct wpa_supplicant *wpa_s = user_data; 2863 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count; 2864 2865 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2866 &expire_count, error); 2867 } 2868 2869 2870 /** 2871 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count 2872 * @iter: Pointer to incoming dbus message iter 2873 * @error: Location to store error on failure 2874 * @user_data: Function specific data 2875 * Returns: TRUE on success, FALSE on failure 2876 * 2877 * Setter function for "BSSExpireCount" property. 2878 */ 2879 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter, 2880 DBusError *error, 2881 void *user_data) 2882 { 2883 struct wpa_supplicant *wpa_s = user_data; 2884 dbus_uint32_t expire_count; 2885 2886 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2887 &expire_count)) 2888 return FALSE; 2889 2890 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) { 2891 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2892 "BSSExpireCount must be > 0"); 2893 return FALSE; 2894 } 2895 return TRUE; 2896 } 2897 2898 2899 /** 2900 * wpas_dbus_getter_country - Control country code 2901 * @iter: Pointer to incoming dbus message iter 2902 * @error: Location to store error on failure 2903 * @user_data: Function specific data 2904 * Returns: TRUE on success, FALSE on failure 2905 * 2906 * Getter function for "Country" property. 2907 */ 2908 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error, 2909 void *user_data) 2910 { 2911 struct wpa_supplicant *wpa_s = user_data; 2912 char country[3]; 2913 char *str = country; 2914 2915 country[0] = wpa_s->conf->country[0]; 2916 country[1] = wpa_s->conf->country[1]; 2917 country[2] = '\0'; 2918 2919 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2920 &str, error); 2921 } 2922 2923 2924 /** 2925 * wpas_dbus_setter_country - Control country code 2926 * @iter: Pointer to incoming dbus message iter 2927 * @error: Location to store error on failure 2928 * @user_data: Function specific data 2929 * Returns: TRUE on success, FALSE on failure 2930 * 2931 * Setter function for "Country" property. 2932 */ 2933 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error, 2934 void *user_data) 2935 { 2936 struct wpa_supplicant *wpa_s = user_data; 2937 const char *country; 2938 2939 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, 2940 &country)) 2941 return FALSE; 2942 2943 if (!country[0] || !country[1]) { 2944 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2945 "invalid country code"); 2946 return FALSE; 2947 } 2948 2949 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) { 2950 wpa_printf(MSG_DEBUG, "Failed to set country"); 2951 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2952 "failed to set country code"); 2953 return FALSE; 2954 } 2955 2956 wpa_s->conf->country[0] = country[0]; 2957 wpa_s->conf->country[1] = country[1]; 2958 return TRUE; 2959 } 2960 2961 2962 /** 2963 * wpas_dbus_getter_scan_interval - Get scan interval 2964 * @iter: Pointer to incoming dbus message iter 2965 * @error: Location to store error on failure 2966 * @user_data: Function specific data 2967 * Returns: TRUE on success, FALSE on failure 2968 * 2969 * Getter function for "ScanInterval" property. 2970 */ 2971 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter, 2972 DBusError *error, 2973 void *user_data) 2974 { 2975 struct wpa_supplicant *wpa_s = user_data; 2976 dbus_int32_t scan_interval = wpa_s->scan_interval; 2977 2978 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 2979 &scan_interval, error); 2980 } 2981 2982 2983 /** 2984 * wpas_dbus_setter_scan_interval - Control scan interval 2985 * @iter: Pointer to incoming dbus message iter 2986 * @error: Location to store error on failure 2987 * @user_data: Function specific data 2988 * Returns: TRUE on success, FALSE on failure 2989 * 2990 * Setter function for "ScanInterval" property. 2991 */ 2992 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter, 2993 DBusError *error, 2994 void *user_data) 2995 { 2996 struct wpa_supplicant *wpa_s = user_data; 2997 dbus_int32_t scan_interval; 2998 2999 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32, 3000 &scan_interval)) 3001 return FALSE; 3002 3003 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) { 3004 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3005 "scan_interval must be >= 0"); 3006 return FALSE; 3007 } 3008 return TRUE; 3009 } 3010 3011 3012 /** 3013 * wpas_dbus_getter_ifname - Get interface name 3014 * @iter: Pointer to incoming dbus message iter 3015 * @error: Location to store error on failure 3016 * @user_data: Function specific data 3017 * Returns: TRUE on success, FALSE on failure 3018 * 3019 * Getter for "Ifname" property. 3020 */ 3021 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error, 3022 void *user_data) 3023 { 3024 struct wpa_supplicant *wpa_s = user_data; 3025 const char *ifname = wpa_s->ifname; 3026 3027 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3028 &ifname, error); 3029 } 3030 3031 3032 /** 3033 * wpas_dbus_getter_driver - Get interface name 3034 * @iter: Pointer to incoming dbus message iter 3035 * @error: Location to store error on failure 3036 * @user_data: Function specific data 3037 * Returns: TRUE on success, FALSE on failure 3038 * 3039 * Getter for "Driver" property. 3040 */ 3041 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error, 3042 void *user_data) 3043 { 3044 struct wpa_supplicant *wpa_s = user_data; 3045 const char *driver; 3046 3047 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) { 3048 wpa_printf(MSG_DEBUG, "%s[dbus]: wpa_s has no driver set", 3049 __func__); 3050 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set", 3051 __func__); 3052 return FALSE; 3053 } 3054 3055 driver = wpa_s->driver->name; 3056 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3057 &driver, error); 3058 } 3059 3060 3061 /** 3062 * wpas_dbus_getter_current_bss - Get current bss object path 3063 * @iter: Pointer to incoming dbus message iter 3064 * @error: Location to store error on failure 3065 * @user_data: Function specific data 3066 * Returns: TRUE on success, FALSE on failure 3067 * 3068 * Getter for "CurrentBSS" property. 3069 */ 3070 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter, 3071 DBusError *error, 3072 void *user_data) 3073 { 3074 struct wpa_supplicant *wpa_s = user_data; 3075 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf; 3076 3077 if (wpa_s->current_bss && wpa_s->dbus_new_path) 3078 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3079 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 3080 wpa_s->dbus_new_path, wpa_s->current_bss->id); 3081 else 3082 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 3083 3084 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 3085 &bss_obj_path, error); 3086 } 3087 3088 3089 /** 3090 * wpas_dbus_getter_current_network - Get current network object path 3091 * @iter: Pointer to incoming dbus message iter 3092 * @error: Location to store error on failure 3093 * @user_data: Function specific data 3094 * Returns: TRUE on success, FALSE on failure 3095 * 3096 * Getter for "CurrentNetwork" property. 3097 */ 3098 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter, 3099 DBusError *error, 3100 void *user_data) 3101 { 3102 struct wpa_supplicant *wpa_s = user_data; 3103 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf; 3104 3105 if (wpa_s->current_ssid && wpa_s->dbus_new_path) 3106 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 3107 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 3108 wpa_s->dbus_new_path, wpa_s->current_ssid->id); 3109 else 3110 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 3111 3112 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 3113 &net_obj_path, error); 3114 } 3115 3116 3117 /** 3118 * wpas_dbus_getter_current_auth_mode - Get current authentication type 3119 * @iter: Pointer to incoming dbus message iter 3120 * @error: Location to store error on failure 3121 * @user_data: Function specific data 3122 * Returns: TRUE on success, FALSE on failure 3123 * 3124 * Getter for "CurrentAuthMode" property. 3125 */ 3126 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter, 3127 DBusError *error, 3128 void *user_data) 3129 { 3130 struct wpa_supplicant *wpa_s = user_data; 3131 const char *eap_mode; 3132 const char *auth_mode; 3133 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX]; 3134 3135 if (wpa_s->wpa_state != WPA_COMPLETED) { 3136 auth_mode = "INACTIVE"; 3137 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || 3138 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 3139 eap_mode = wpa_supplicant_get_eap_mode(wpa_s); 3140 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX, 3141 "EAP-%s", eap_mode); 3142 auth_mode = eap_mode_buf; 3143 3144 } else { 3145 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt, 3146 wpa_s->current_ssid->proto); 3147 } 3148 3149 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3150 &auth_mode, error); 3151 } 3152 3153 3154 /** 3155 * wpas_dbus_getter_bridge_ifname - Get interface name 3156 * @iter: Pointer to incoming dbus message iter 3157 * @error: Location to store error on failure 3158 * @user_data: Function specific data 3159 * Returns: TRUE on success, FALSE on failure 3160 * 3161 * Getter for "BridgeIfname" property. 3162 */ 3163 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter, 3164 DBusError *error, 3165 void *user_data) 3166 { 3167 struct wpa_supplicant *wpa_s = user_data; 3168 const char *bridge_ifname = wpa_s->bridge_ifname; 3169 3170 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3171 &bridge_ifname, error); 3172 } 3173 3174 3175 /** 3176 * wpas_dbus_getter_bsss - Get array of BSSs objects 3177 * @iter: Pointer to incoming dbus message iter 3178 * @error: Location to store error on failure 3179 * @user_data: Function specific data 3180 * Returns: TRUE on success, FALSE on failure 3181 * 3182 * Getter for "BSSs" property. 3183 */ 3184 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error, 3185 void *user_data) 3186 { 3187 struct wpa_supplicant *wpa_s = user_data; 3188 struct wpa_bss *bss; 3189 char **paths; 3190 unsigned int i = 0; 3191 dbus_bool_t success = FALSE; 3192 3193 if (!wpa_s->dbus_new_path) { 3194 dbus_set_error(error, DBUS_ERROR_FAILED, 3195 "%s: no D-Bus interface", __func__); 3196 return FALSE; 3197 } 3198 3199 paths = os_calloc(wpa_s->num_bss, sizeof(char *)); 3200 if (!paths) { 3201 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3202 return FALSE; 3203 } 3204 3205 /* Loop through scan results and append each result's object path */ 3206 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 3207 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 3208 if (paths[i] == NULL) { 3209 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 3210 "no memory"); 3211 goto out; 3212 } 3213 /* Construct the object path for this BSS. */ 3214 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 3215 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 3216 wpa_s->dbus_new_path, bss->id); 3217 } 3218 3219 success = wpas_dbus_simple_array_property_getter(iter, 3220 DBUS_TYPE_OBJECT_PATH, 3221 paths, wpa_s->num_bss, 3222 error); 3223 3224 out: 3225 while (i) 3226 os_free(paths[--i]); 3227 os_free(paths); 3228 return success; 3229 } 3230 3231 3232 /** 3233 * wpas_dbus_getter_networks - Get array of networks objects 3234 * @iter: Pointer to incoming dbus message iter 3235 * @error: Location to store error on failure 3236 * @user_data: Function specific data 3237 * Returns: TRUE on success, FALSE on failure 3238 * 3239 * Getter for "Networks" property. 3240 */ 3241 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error, 3242 void *user_data) 3243 { 3244 struct wpa_supplicant *wpa_s = user_data; 3245 struct wpa_ssid *ssid; 3246 char **paths; 3247 unsigned int i = 0, num = 0; 3248 dbus_bool_t success = FALSE; 3249 3250 if (!wpa_s->dbus_new_path) { 3251 dbus_set_error(error, DBUS_ERROR_FAILED, 3252 "%s: no D-Bus interface", __func__); 3253 return FALSE; 3254 } 3255 3256 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 3257 if (!network_is_persistent_group(ssid)) 3258 num++; 3259 3260 paths = os_calloc(num, sizeof(char *)); 3261 if (!paths) { 3262 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3263 return FALSE; 3264 } 3265 3266 /* Loop through configured networks and append object path of each */ 3267 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 3268 if (network_is_persistent_group(ssid)) 3269 continue; 3270 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 3271 if (paths[i] == NULL) { 3272 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, 3273 "no memory"); 3274 goto out; 3275 } 3276 3277 /* Construct the object path for this network. */ 3278 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 3279 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 3280 wpa_s->dbus_new_path, ssid->id); 3281 } 3282 3283 success = wpas_dbus_simple_array_property_getter(iter, 3284 DBUS_TYPE_OBJECT_PATH, 3285 paths, num, error); 3286 3287 out: 3288 while (i) 3289 os_free(paths[--i]); 3290 os_free(paths); 3291 return success; 3292 } 3293 3294 3295 /** 3296 * wpas_dbus_getter_pkcs11_engine_path - Get PKCS #11 engine path 3297 * @iter: Pointer to incoming dbus message iter 3298 * @error: Location to store error on failure 3299 * @user_data: Function specific data 3300 * Returns: A dbus message containing the PKCS #11 engine path 3301 * 3302 * Getter for "PKCS11EnginePath" property. 3303 */ 3304 dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter, 3305 DBusError *error, 3306 void *user_data) 3307 { 3308 struct wpa_supplicant *wpa_s = user_data; 3309 const char *pkcs11_engine_path; 3310 3311 if (wpa_s->conf->pkcs11_engine_path == NULL) 3312 pkcs11_engine_path = ""; 3313 else 3314 pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; 3315 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3316 &pkcs11_engine_path, error); 3317 } 3318 3319 3320 /** 3321 * wpas_dbus_getter_pkcs11_module_path - Get PKCS #11 module path 3322 * @iter: Pointer to incoming dbus message iter 3323 * @error: Location to store error on failure 3324 * @user_data: Function specific data 3325 * Returns: A dbus message containing the PKCS #11 module path 3326 * 3327 * Getter for "PKCS11ModulePath" property. 3328 */ 3329 dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter, 3330 DBusError *error, 3331 void *user_data) 3332 { 3333 struct wpa_supplicant *wpa_s = user_data; 3334 const char *pkcs11_module_path; 3335 3336 if (wpa_s->conf->pkcs11_module_path == NULL) 3337 pkcs11_module_path = ""; 3338 else 3339 pkcs11_module_path = wpa_s->conf->pkcs11_module_path; 3340 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3341 &pkcs11_module_path, error); 3342 } 3343 3344 3345 /** 3346 * wpas_dbus_getter_blobs - Get all blobs defined for this interface 3347 * @iter: Pointer to incoming dbus message iter 3348 * @error: Location to store error on failure 3349 * @user_data: Function specific data 3350 * Returns: TRUE on success, FALSE on failure 3351 * 3352 * Getter for "Blobs" property. 3353 */ 3354 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error, 3355 void *user_data) 3356 { 3357 struct wpa_supplicant *wpa_s = user_data; 3358 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter; 3359 struct wpa_config_blob *blob; 3360 3361 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3362 "a{say}", &variant_iter) || 3363 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 3364 "{say}", &dict_iter)) { 3365 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3366 return FALSE; 3367 } 3368 3369 blob = wpa_s->conf->blobs; 3370 while (blob) { 3371 if (!dbus_message_iter_open_container(&dict_iter, 3372 DBUS_TYPE_DICT_ENTRY, 3373 NULL, &entry_iter) || 3374 !dbus_message_iter_append_basic(&entry_iter, 3375 DBUS_TYPE_STRING, 3376 &(blob->name)) || 3377 !dbus_message_iter_open_container(&entry_iter, 3378 DBUS_TYPE_ARRAY, 3379 DBUS_TYPE_BYTE_AS_STRING, 3380 &array_iter) || 3381 !dbus_message_iter_append_fixed_array(&array_iter, 3382 DBUS_TYPE_BYTE, 3383 &(blob->data), 3384 blob->len) || 3385 !dbus_message_iter_close_container(&entry_iter, 3386 &array_iter) || 3387 !dbus_message_iter_close_container(&dict_iter, 3388 &entry_iter)) { 3389 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 3390 "no memory"); 3391 return FALSE; 3392 } 3393 3394 blob = blob->next; 3395 } 3396 3397 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) || 3398 !dbus_message_iter_close_container(iter, &variant_iter)) { 3399 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3400 return FALSE; 3401 } 3402 3403 return TRUE; 3404 } 3405 3406 3407 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args, 3408 DBusError *error, const char *func_name) 3409 { 3410 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id); 3411 3412 if (!res) { 3413 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found", 3414 func_name, args->id); 3415 dbus_set_error(error, DBUS_ERROR_FAILED, 3416 "%s: BSS %d not found", 3417 func_name, args->id); 3418 } 3419 3420 return res; 3421 } 3422 3423 3424 /** 3425 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS 3426 * @iter: Pointer to incoming dbus message iter 3427 * @error: Location to store error on failure 3428 * @user_data: Function specific data 3429 * Returns: TRUE on success, FALSE on failure 3430 * 3431 * Getter for "BSSID" property. 3432 */ 3433 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error, 3434 void *user_data) 3435 { 3436 struct bss_handler_args *args = user_data; 3437 struct wpa_bss *res; 3438 3439 res = get_bss_helper(args, error, __func__); 3440 if (!res) 3441 return FALSE; 3442 3443 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3444 res->bssid, ETH_ALEN, 3445 error); 3446 } 3447 3448 3449 /** 3450 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS 3451 * @iter: Pointer to incoming dbus message iter 3452 * @error: Location to store error on failure 3453 * @user_data: Function specific data 3454 * Returns: TRUE on success, FALSE on failure 3455 * 3456 * Getter for "SSID" property. 3457 */ 3458 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error, 3459 void *user_data) 3460 { 3461 struct bss_handler_args *args = user_data; 3462 struct wpa_bss *res; 3463 3464 res = get_bss_helper(args, error, __func__); 3465 if (!res) 3466 return FALSE; 3467 3468 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3469 res->ssid, res->ssid_len, 3470 error); 3471 } 3472 3473 3474 /** 3475 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS 3476 * @iter: Pointer to incoming dbus message iter 3477 * @error: Location to store error on failure 3478 * @user_data: Function specific data 3479 * Returns: TRUE on success, FALSE on failure 3480 * 3481 * Getter for "Privacy" property. 3482 */ 3483 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter, 3484 DBusError *error, void *user_data) 3485 { 3486 struct bss_handler_args *args = user_data; 3487 struct wpa_bss *res; 3488 dbus_bool_t privacy; 3489 3490 res = get_bss_helper(args, error, __func__); 3491 if (!res) 3492 return FALSE; 3493 3494 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE; 3495 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3496 &privacy, error); 3497 } 3498 3499 3500 /** 3501 * wpas_dbus_getter_bss_mode - Return the mode of a BSS 3502 * @iter: Pointer to incoming dbus message iter 3503 * @error: Location to store error on failure 3504 * @user_data: Function specific data 3505 * Returns: TRUE on success, FALSE on failure 3506 * 3507 * Getter for "Mode" property. 3508 */ 3509 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error, 3510 void *user_data) 3511 { 3512 struct bss_handler_args *args = user_data; 3513 struct wpa_bss *res; 3514 const char *mode; 3515 3516 res = get_bss_helper(args, error, __func__); 3517 if (!res) 3518 return FALSE; 3519 if (bss_is_dmg(res)) { 3520 switch (res->caps & IEEE80211_CAP_DMG_MASK) { 3521 case IEEE80211_CAP_DMG_PBSS: 3522 case IEEE80211_CAP_DMG_IBSS: 3523 mode = "ad-hoc"; 3524 break; 3525 case IEEE80211_CAP_DMG_AP: 3526 mode = "infrastructure"; 3527 break; 3528 } 3529 } else { 3530 if (res->caps & IEEE80211_CAP_IBSS) 3531 mode = "ad-hoc"; 3532 else 3533 mode = "infrastructure"; 3534 } 3535 3536 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3537 &mode, error); 3538 } 3539 3540 3541 /** 3542 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS 3543 * @iter: Pointer to incoming dbus message iter 3544 * @error: Location to store error on failure 3545 * @user_data: Function specific data 3546 * Returns: TRUE on success, FALSE on failure 3547 * 3548 * Getter for "Level" property. 3549 */ 3550 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter, 3551 DBusError *error, void *user_data) 3552 { 3553 struct bss_handler_args *args = user_data; 3554 struct wpa_bss *res; 3555 s16 level; 3556 3557 res = get_bss_helper(args, error, __func__); 3558 if (!res) 3559 return FALSE; 3560 3561 level = (s16) res->level; 3562 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16, 3563 &level, error); 3564 } 3565 3566 3567 /** 3568 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS 3569 * @iter: Pointer to incoming dbus message iter 3570 * @error: Location to store error on failure 3571 * @user_data: Function specific data 3572 * Returns: TRUE on success, FALSE on failure 3573 * 3574 * Getter for "Frequency" property. 3575 */ 3576 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter, 3577 DBusError *error, void *user_data) 3578 { 3579 struct bss_handler_args *args = user_data; 3580 struct wpa_bss *res; 3581 u16 freq; 3582 3583 res = get_bss_helper(args, error, __func__); 3584 if (!res) 3585 return FALSE; 3586 3587 freq = (u16) res->freq; 3588 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 3589 &freq, error); 3590 } 3591 3592 3593 static int cmp_u8s_desc(const void *a, const void *b) 3594 { 3595 return (*(u8 *) b - *(u8 *) a); 3596 } 3597 3598 3599 /** 3600 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS 3601 * @iter: Pointer to incoming dbus message iter 3602 * @error: Location to store error on failure 3603 * @user_data: Function specific data 3604 * Returns: TRUE on success, FALSE on failure 3605 * 3606 * Getter for "Rates" property. 3607 */ 3608 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter, 3609 DBusError *error, void *user_data) 3610 { 3611 struct bss_handler_args *args = user_data; 3612 struct wpa_bss *res; 3613 u8 *ie_rates = NULL; 3614 u32 *real_rates; 3615 int rates_num, i; 3616 dbus_bool_t success = FALSE; 3617 3618 res = get_bss_helper(args, error, __func__); 3619 if (!res) 3620 return FALSE; 3621 3622 rates_num = wpa_bss_get_bit_rates(res, &ie_rates); 3623 if (rates_num < 0) 3624 return FALSE; 3625 3626 qsort(ie_rates, rates_num, 1, cmp_u8s_desc); 3627 3628 real_rates = os_malloc(sizeof(u32) * rates_num); 3629 if (!real_rates) { 3630 os_free(ie_rates); 3631 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3632 return FALSE; 3633 } 3634 3635 for (i = 0; i < rates_num; i++) 3636 real_rates[i] = ie_rates[i] * 500000; 3637 3638 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32, 3639 real_rates, rates_num, 3640 error); 3641 3642 os_free(ie_rates); 3643 os_free(real_rates); 3644 return success; 3645 } 3646 3647 3648 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, 3649 struct wpa_ie_data *ie_data, 3650 DBusError *error) 3651 { 3652 DBusMessageIter iter_dict, variant_iter; 3653 const char *group; 3654 const char *pairwise[5]; /* max 5 pairwise ciphers is supported */ 3655 const char *key_mgmt[9]; /* max 9 key managements may be supported */ 3656 int n; 3657 3658 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3659 "a{sv}", &variant_iter)) 3660 goto nomem; 3661 3662 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 3663 goto nomem; 3664 3665 /* KeyMgmt */ 3666 n = 0; 3667 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK) 3668 key_mgmt[n++] = "wpa-psk"; 3669 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK) 3670 key_mgmt[n++] = "wpa-ft-psk"; 3671 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 3672 key_mgmt[n++] = "wpa-psk-sha256"; 3673 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X) 3674 key_mgmt[n++] = "wpa-eap"; 3675 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 3676 key_mgmt[n++] = "wpa-ft-eap"; 3677 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 3678 key_mgmt[n++] = "wpa-eap-sha256"; 3679 #ifdef CONFIG_SUITEB 3680 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) 3681 key_mgmt[n++] = "wpa-eap-suite-b"; 3682 #endif /* CONFIG_SUITEB */ 3683 #ifdef CONFIG_SUITEB192 3684 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 3685 key_mgmt[n++] = "wpa-eap-suite-b-192"; 3686 #endif /* CONFIG_SUITEB192 */ 3687 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE) 3688 key_mgmt[n++] = "wpa-none"; 3689 3690 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt", 3691 key_mgmt, n)) 3692 goto nomem; 3693 3694 /* Group */ 3695 switch (ie_data->group_cipher) { 3696 case WPA_CIPHER_WEP40: 3697 group = "wep40"; 3698 break; 3699 case WPA_CIPHER_TKIP: 3700 group = "tkip"; 3701 break; 3702 case WPA_CIPHER_CCMP: 3703 group = "ccmp"; 3704 break; 3705 case WPA_CIPHER_GCMP: 3706 group = "gcmp"; 3707 break; 3708 case WPA_CIPHER_WEP104: 3709 group = "wep104"; 3710 break; 3711 case WPA_CIPHER_CCMP_256: 3712 group = "ccmp-256"; 3713 break; 3714 case WPA_CIPHER_GCMP_256: 3715 group = "gcmp-256"; 3716 break; 3717 default: 3718 group = ""; 3719 break; 3720 } 3721 3722 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group)) 3723 goto nomem; 3724 3725 /* Pairwise */ 3726 n = 0; 3727 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP) 3728 pairwise[n++] = "tkip"; 3729 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP) 3730 pairwise[n++] = "ccmp"; 3731 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP) 3732 pairwise[n++] = "gcmp"; 3733 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256) 3734 pairwise[n++] = "ccmp-256"; 3735 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256) 3736 pairwise[n++] = "gcmp-256"; 3737 3738 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise", 3739 pairwise, n)) 3740 goto nomem; 3741 3742 /* Management group (RSN only) */ 3743 if (ie_data->proto == WPA_PROTO_RSN) { 3744 switch (ie_data->mgmt_group_cipher) { 3745 #ifdef CONFIG_IEEE80211W 3746 case WPA_CIPHER_AES_128_CMAC: 3747 group = "aes128cmac"; 3748 break; 3749 #endif /* CONFIG_IEEE80211W */ 3750 default: 3751 group = ""; 3752 break; 3753 } 3754 3755 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup", 3756 group)) 3757 goto nomem; 3758 } 3759 3760 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || 3761 !dbus_message_iter_close_container(iter, &variant_iter)) 3762 goto nomem; 3763 3764 return TRUE; 3765 3766 nomem: 3767 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3768 return FALSE; 3769 } 3770 3771 3772 /** 3773 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS 3774 * @iter: Pointer to incoming dbus message iter 3775 * @error: Location to store error on failure 3776 * @user_data: Function specific data 3777 * Returns: TRUE on success, FALSE on failure 3778 * 3779 * Getter for "WPA" property. 3780 */ 3781 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error, 3782 void *user_data) 3783 { 3784 struct bss_handler_args *args = user_data; 3785 struct wpa_bss *res; 3786 struct wpa_ie_data wpa_data; 3787 const u8 *ie; 3788 3789 res = get_bss_helper(args, error, __func__); 3790 if (!res) 3791 return FALSE; 3792 3793 os_memset(&wpa_data, 0, sizeof(wpa_data)); 3794 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); 3795 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { 3796 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3797 "failed to parse WPA IE"); 3798 return FALSE; 3799 } 3800 3801 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error); 3802 } 3803 3804 3805 /** 3806 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS 3807 * @iter: Pointer to incoming dbus message iter 3808 * @error: Location to store error on failure 3809 * @user_data: Function specific data 3810 * Returns: TRUE on success, FALSE on failure 3811 * 3812 * Getter for "RSN" property. 3813 */ 3814 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error, 3815 void *user_data) 3816 { 3817 struct bss_handler_args *args = user_data; 3818 struct wpa_bss *res; 3819 struct wpa_ie_data wpa_data; 3820 const u8 *ie; 3821 3822 res = get_bss_helper(args, error, __func__); 3823 if (!res) 3824 return FALSE; 3825 3826 os_memset(&wpa_data, 0, sizeof(wpa_data)); 3827 ie = wpa_bss_get_ie(res, WLAN_EID_RSN); 3828 if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { 3829 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3830 "failed to parse RSN IE"); 3831 return FALSE; 3832 } 3833 3834 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error); 3835 } 3836 3837 3838 /** 3839 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS 3840 * @iter: Pointer to incoming dbus message iter 3841 * @error: Location to store error on failure 3842 * @user_data: Function specific data 3843 * Returns: TRUE on success, FALSE on failure 3844 * 3845 * Getter for "WPS" property. 3846 */ 3847 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error, 3848 void *user_data) 3849 { 3850 struct bss_handler_args *args = user_data; 3851 struct wpa_bss *res; 3852 #ifdef CONFIG_WPS 3853 struct wpabuf *wps_ie; 3854 #endif /* CONFIG_WPS */ 3855 DBusMessageIter iter_dict, variant_iter; 3856 int wps_support = 0; 3857 const char *type = ""; 3858 3859 res = get_bss_helper(args, error, __func__); 3860 if (!res) 3861 return FALSE; 3862 3863 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3864 "a{sv}", &variant_iter) || 3865 !wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 3866 goto nomem; 3867 3868 #ifdef CONFIG_WPS 3869 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE); 3870 if (wps_ie) { 3871 wps_support = 1; 3872 if (wps_is_selected_pbc_registrar(wps_ie)) 3873 type = "pbc"; 3874 else if (wps_is_selected_pin_registrar(wps_ie)) 3875 type = "pin"; 3876 3877 wpabuf_free(wps_ie); 3878 } 3879 #endif /* CONFIG_WPS */ 3880 3881 if ((wps_support && !wpa_dbus_dict_append_string(&iter_dict, "Type", type)) || 3882 !wpa_dbus_dict_close_write(&variant_iter, &iter_dict) || 3883 !dbus_message_iter_close_container(iter, &variant_iter)) 3884 goto nomem; 3885 3886 return TRUE; 3887 3888 nomem: 3889 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3890 return FALSE; 3891 } 3892 3893 3894 /** 3895 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS 3896 * @iter: Pointer to incoming dbus message iter 3897 * @error: Location to store error on failure 3898 * @user_data: Function specific data 3899 * Returns: TRUE on success, FALSE on failure 3900 * 3901 * Getter for "IEs" property. 3902 */ 3903 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error, 3904 void *user_data) 3905 { 3906 struct bss_handler_args *args = user_data; 3907 struct wpa_bss *res; 3908 3909 res = get_bss_helper(args, error, __func__); 3910 if (!res) 3911 return FALSE; 3912 3913 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3914 res + 1, res->ie_len, 3915 error); 3916 } 3917 3918 3919 /** 3920 * wpas_dbus_getter_bss_age - Return time in seconds since BSS was last seen 3921 * @iter: Pointer to incoming dbus message iter 3922 * @error: Location to store error on failure 3923 * @user_data: Function specific data 3924 * Returns: TRUE on success, FALSE on failure 3925 * 3926 * Getter for BSS age 3927 */ 3928 dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error, 3929 void *user_data) 3930 { 3931 struct bss_handler_args *args = user_data; 3932 struct wpa_bss *res; 3933 struct os_reltime now, diff = { 0, 0 }; 3934 u32 age; 3935 3936 res = get_bss_helper(args, error, __func__); 3937 if (!res) 3938 return FALSE; 3939 3940 os_get_reltime(&now); 3941 os_reltime_sub(&now, &res->last_update, &diff); 3942 age = diff.sec > 0 ? diff.sec : 0; 3943 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, &age, 3944 error); 3945 } 3946 3947 3948 /** 3949 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled 3950 * @iter: Pointer to incoming dbus message iter 3951 * @error: Location to store error on failure 3952 * @user_data: Function specific data 3953 * Returns: TRUE on success, FALSE on failure 3954 * 3955 * Getter for "enabled" property of a configured network. 3956 */ 3957 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error, 3958 void *user_data) 3959 { 3960 struct network_handler_args *net = user_data; 3961 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE; 3962 3963 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3964 &enabled, error); 3965 } 3966 3967 3968 /** 3969 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled 3970 * @iter: Pointer to incoming dbus message iter 3971 * @error: Location to store error on failure 3972 * @user_data: Function specific data 3973 * Returns: TRUE on success, FALSE on failure 3974 * 3975 * Setter for "Enabled" property of a configured network. 3976 */ 3977 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error, 3978 void *user_data) 3979 { 3980 struct network_handler_args *net = user_data; 3981 struct wpa_supplicant *wpa_s; 3982 struct wpa_ssid *ssid; 3983 dbus_bool_t enable; 3984 3985 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 3986 &enable)) 3987 return FALSE; 3988 3989 wpa_s = net->wpa_s; 3990 ssid = net->ssid; 3991 3992 if (enable) 3993 wpa_supplicant_enable_network(wpa_s, ssid); 3994 else 3995 wpa_supplicant_disable_network(wpa_s, ssid); 3996 3997 return TRUE; 3998 } 3999 4000 4001 /** 4002 * wpas_dbus_getter_network_properties - Get options for a configured network 4003 * @iter: Pointer to incoming dbus message iter 4004 * @error: Location to store error on failure 4005 * @user_data: Function specific data 4006 * Returns: TRUE on success, FALSE on failure 4007 * 4008 * Getter for "Properties" property of a configured network. 4009 */ 4010 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter, 4011 DBusError *error, 4012 void *user_data) 4013 { 4014 struct network_handler_args *net = user_data; 4015 DBusMessageIter variant_iter, dict_iter; 4016 char **iterator; 4017 char **props = wpa_config_get_all(net->ssid, 1); 4018 dbus_bool_t success = FALSE; 4019 4020 if (!props) { 4021 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4022 return FALSE; 4023 } 4024 4025 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}", 4026 &variant_iter) || 4027 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) { 4028 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4029 goto out; 4030 } 4031 4032 iterator = props; 4033 while (*iterator) { 4034 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator, 4035 *(iterator + 1))) { 4036 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 4037 "no memory"); 4038 goto out; 4039 } 4040 iterator += 2; 4041 } 4042 4043 4044 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || 4045 !dbus_message_iter_close_container(iter, &variant_iter)) { 4046 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 4047 goto out; 4048 } 4049 4050 success = TRUE; 4051 4052 out: 4053 iterator = props; 4054 while (*iterator) { 4055 os_free(*iterator); 4056 iterator++; 4057 } 4058 os_free(props); 4059 return success; 4060 } 4061 4062 4063 /** 4064 * wpas_dbus_setter_network_properties - Set options for a configured network 4065 * @iter: Pointer to incoming dbus message iter 4066 * @error: Location to store error on failure 4067 * @user_data: Function specific data 4068 * Returns: TRUE on success, FALSE on failure 4069 * 4070 * Setter for "Properties" property of a configured network. 4071 */ 4072 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter, 4073 DBusError *error, 4074 void *user_data) 4075 { 4076 struct network_handler_args *net = user_data; 4077 struct wpa_ssid *ssid = net->ssid; 4078 DBusMessageIter variant_iter; 4079 4080 dbus_message_iter_recurse(iter, &variant_iter); 4081 return set_network_properties(net->wpa_s, ssid, &variant_iter, error); 4082 } 4083 4084 4085 #ifdef CONFIG_AP 4086 4087 DBusMessage * wpas_dbus_handler_subscribe_preq( 4088 DBusMessage *message, struct wpa_supplicant *wpa_s) 4089 { 4090 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 4091 char *name; 4092 4093 if (wpa_s->preq_notify_peer != NULL) { 4094 if (os_strcmp(dbus_message_get_sender(message), 4095 wpa_s->preq_notify_peer) == 0) 4096 return NULL; 4097 4098 return dbus_message_new_error(message, 4099 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE, 4100 "Another application is already subscribed"); 4101 } 4102 4103 name = os_strdup(dbus_message_get_sender(message)); 4104 if (!name) 4105 return wpas_dbus_error_no_memory(message); 4106 4107 wpa_s->preq_notify_peer = name; 4108 4109 /* Subscribe to clean up if application closes socket */ 4110 wpas_dbus_subscribe_noc(priv); 4111 4112 /* 4113 * Double-check it's still alive to make sure that we didn't 4114 * miss the NameOwnerChanged signal, e.g. while strdup'ing. 4115 */ 4116 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) { 4117 /* 4118 * Application no longer exists, clean up. 4119 * The return value is irrelevant now. 4120 * 4121 * Need to check if the NameOwnerChanged handling 4122 * already cleaned up because we have processed 4123 * DBus messages while checking if the name still 4124 * has an owner. 4125 */ 4126 if (!wpa_s->preq_notify_peer) 4127 return NULL; 4128 os_free(wpa_s->preq_notify_peer); 4129 wpa_s->preq_notify_peer = NULL; 4130 wpas_dbus_unsubscribe_noc(priv); 4131 } 4132 4133 return NULL; 4134 } 4135 4136 4137 DBusMessage * wpas_dbus_handler_unsubscribe_preq( 4138 DBusMessage *message, struct wpa_supplicant *wpa_s) 4139 { 4140 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 4141 4142 if (!wpa_s->preq_notify_peer) 4143 return dbus_message_new_error(message, 4144 WPAS_DBUS_ERROR_NO_SUBSCRIPTION, 4145 "Not subscribed"); 4146 4147 if (os_strcmp(wpa_s->preq_notify_peer, 4148 dbus_message_get_sender(message))) 4149 return dbus_message_new_error(message, 4150 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM, 4151 "Can't unsubscribe others"); 4152 4153 os_free(wpa_s->preq_notify_peer); 4154 wpa_s->preq_notify_peer = NULL; 4155 wpas_dbus_unsubscribe_noc(priv); 4156 return NULL; 4157 } 4158 4159 4160 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s, 4161 const u8 *addr, const u8 *dst, const u8 *bssid, 4162 const u8 *ie, size_t ie_len, u32 ssi_signal) 4163 { 4164 DBusMessage *msg; 4165 DBusMessageIter iter, dict_iter; 4166 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 4167 4168 /* Do nothing if the control interface is not turned on */ 4169 if (priv == NULL || !wpa_s->dbus_new_path) 4170 return; 4171 4172 if (wpa_s->preq_notify_peer == NULL) 4173 return; 4174 4175 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 4176 WPAS_DBUS_NEW_IFACE_INTERFACE, 4177 "ProbeRequest"); 4178 if (msg == NULL) 4179 return; 4180 4181 dbus_message_set_destination(msg, wpa_s->preq_notify_peer); 4182 4183 dbus_message_iter_init_append(msg, &iter); 4184 4185 if (!wpa_dbus_dict_open_write(&iter, &dict_iter) || 4186 (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr", 4187 (const char *) addr, 4188 ETH_ALEN)) || 4189 (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst", 4190 (const char *) dst, 4191 ETH_ALEN)) || 4192 (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid", 4193 (const char *) bssid, 4194 ETH_ALEN)) || 4195 (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies", 4196 (const char *) ie, 4197 ie_len)) || 4198 (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal", 4199 ssi_signal)) || 4200 !wpa_dbus_dict_close_write(&iter, &dict_iter)) 4201 goto fail; 4202 4203 dbus_connection_send(priv->con, msg, NULL); 4204 goto out; 4205 fail: 4206 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 4207 out: 4208 dbus_message_unref(msg); 4209 } 4210 4211 #endif /* CONFIG_AP */ 4212