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