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