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