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