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