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_handler_eap_logoff - IEEE 802.1X EAPOL state machine logoff 1943 * @message: Pointer to incoming dbus message 1944 * @wpa_s: wpa_supplicant structure for a network interface 1945 * Returns: NULL 1946 * 1947 * Handler function for "EAPLogoff" method call of network interface. 1948 */ 1949 DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message, 1950 struct wpa_supplicant *wpa_s) 1951 { 1952 eapol_sm_notify_logoff(wpa_s->eapol, TRUE); 1953 return NULL; 1954 } 1955 1956 1957 /* 1958 * wpas_dbus_handler_eap_logon - IEEE 802.1X EAPOL state machine logon 1959 * @message: Pointer to incoming dbus message 1960 * @wpa_s: wpa_supplicant structure for a network interface 1961 * Returns: NULL 1962 * 1963 * Handler function for "EAPLogin" method call of network interface. 1964 */ 1965 DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message, 1966 struct wpa_supplicant *wpa_s) 1967 { 1968 eapol_sm_notify_logoff(wpa_s->eapol, FALSE); 1969 return NULL; 1970 } 1971 1972 1973 /** 1974 * wpas_dbus_getter_capabilities - Return interface capabilities 1975 * @iter: Pointer to incoming dbus message iter 1976 * @error: Location to store error on failure 1977 * @user_data: Function specific data 1978 * Returns: TRUE on success, FALSE on failure 1979 * 1980 * Getter for "Capabilities" property of an interface. 1981 */ 1982 dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter, 1983 DBusError *error, void *user_data) 1984 { 1985 struct wpa_supplicant *wpa_s = user_data; 1986 struct wpa_driver_capa capa; 1987 int res; 1988 DBusMessageIter iter_dict, iter_dict_entry, iter_dict_val, iter_array, 1989 variant_iter; 1990 const char *scans[] = { "active", "passive", "ssid" }; 1991 1992 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 1993 "a{sv}", &variant_iter)) 1994 goto nomem; 1995 1996 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 1997 goto nomem; 1998 1999 res = wpa_drv_get_capa(wpa_s, &capa); 2000 2001 /***** pairwise cipher */ 2002 if (res < 0) { 2003 const char *args[] = {"ccmp", "tkip", "none"}; 2004 if (!wpa_dbus_dict_append_string_array( 2005 &iter_dict, "Pairwise", args, 2006 sizeof(args) / sizeof(char*))) 2007 goto nomem; 2008 } else { 2009 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise", 2010 &iter_dict_entry, 2011 &iter_dict_val, 2012 &iter_array)) 2013 goto nomem; 2014 2015 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2016 if (!wpa_dbus_dict_string_array_add_element( 2017 &iter_array, "ccmp")) 2018 goto nomem; 2019 } 2020 2021 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) { 2022 if (!wpa_dbus_dict_string_array_add_element( 2023 &iter_array, "gcmp")) 2024 goto nomem; 2025 } 2026 2027 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2028 if (!wpa_dbus_dict_string_array_add_element( 2029 &iter_array, "tkip")) 2030 goto nomem; 2031 } 2032 2033 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2034 if (!wpa_dbus_dict_string_array_add_element( 2035 &iter_array, "none")) 2036 goto nomem; 2037 } 2038 2039 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2040 &iter_dict_entry, 2041 &iter_dict_val, 2042 &iter_array)) 2043 goto nomem; 2044 } 2045 2046 /***** group cipher */ 2047 if (res < 0) { 2048 const char *args[] = { 2049 "ccmp", "tkip", "wep104", "wep40" 2050 }; 2051 if (!wpa_dbus_dict_append_string_array( 2052 &iter_dict, "Group", args, 2053 sizeof(args) / sizeof(char*))) 2054 goto nomem; 2055 } else { 2056 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group", 2057 &iter_dict_entry, 2058 &iter_dict_val, 2059 &iter_array)) 2060 goto nomem; 2061 2062 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 2063 if (!wpa_dbus_dict_string_array_add_element( 2064 &iter_array, "ccmp")) 2065 goto nomem; 2066 } 2067 2068 if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) { 2069 if (!wpa_dbus_dict_string_array_add_element( 2070 &iter_array, "gcmp")) 2071 goto nomem; 2072 } 2073 2074 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 2075 if (!wpa_dbus_dict_string_array_add_element( 2076 &iter_array, "tkip")) 2077 goto nomem; 2078 } 2079 2080 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { 2081 if (!wpa_dbus_dict_string_array_add_element( 2082 &iter_array, "wep104")) 2083 goto nomem; 2084 } 2085 2086 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { 2087 if (!wpa_dbus_dict_string_array_add_element( 2088 &iter_array, "wep40")) 2089 goto nomem; 2090 } 2091 2092 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2093 &iter_dict_entry, 2094 &iter_dict_val, 2095 &iter_array)) 2096 goto nomem; 2097 } 2098 2099 /***** key management */ 2100 if (res < 0) { 2101 const char *args[] = { 2102 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none", 2103 #ifdef CONFIG_WPS 2104 "wps", 2105 #endif /* CONFIG_WPS */ 2106 "none" 2107 }; 2108 if (!wpa_dbus_dict_append_string_array( 2109 &iter_dict, "KeyMgmt", args, 2110 sizeof(args) / sizeof(char*))) 2111 goto nomem; 2112 } else { 2113 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt", 2114 &iter_dict_entry, 2115 &iter_dict_val, 2116 &iter_array)) 2117 goto nomem; 2118 2119 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 2120 "none")) 2121 goto nomem; 2122 2123 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 2124 "ieee8021x")) 2125 goto nomem; 2126 2127 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2128 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 2129 if (!wpa_dbus_dict_string_array_add_element( 2130 &iter_array, "wpa-eap")) 2131 goto nomem; 2132 2133 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) 2134 if (!wpa_dbus_dict_string_array_add_element( 2135 &iter_array, "wpa-ft-eap")) 2136 goto nomem; 2137 2138 /* TODO: Ensure that driver actually supports sha256 encryption. */ 2139 #ifdef CONFIG_IEEE80211W 2140 if (!wpa_dbus_dict_string_array_add_element( 2141 &iter_array, "wpa-eap-sha256")) 2142 goto nomem; 2143 #endif /* CONFIG_IEEE80211W */ 2144 } 2145 2146 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 2147 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2148 if (!wpa_dbus_dict_string_array_add_element( 2149 &iter_array, "wpa-psk")) 2150 goto nomem; 2151 2152 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) 2153 if (!wpa_dbus_dict_string_array_add_element( 2154 &iter_array, "wpa-ft-psk")) 2155 goto nomem; 2156 2157 /* TODO: Ensure that driver actually supports sha256 encryption. */ 2158 #ifdef CONFIG_IEEE80211W 2159 if (!wpa_dbus_dict_string_array_add_element( 2160 &iter_array, "wpa-psk-sha256")) 2161 goto nomem; 2162 #endif /* CONFIG_IEEE80211W */ 2163 } 2164 2165 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 2166 if (!wpa_dbus_dict_string_array_add_element( 2167 &iter_array, "wpa-none")) 2168 goto nomem; 2169 } 2170 2171 2172 #ifdef CONFIG_WPS 2173 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 2174 "wps")) 2175 goto nomem; 2176 #endif /* CONFIG_WPS */ 2177 2178 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2179 &iter_dict_entry, 2180 &iter_dict_val, 2181 &iter_array)) 2182 goto nomem; 2183 } 2184 2185 /***** WPA protocol */ 2186 if (res < 0) { 2187 const char *args[] = { "rsn", "wpa" }; 2188 if (!wpa_dbus_dict_append_string_array( 2189 &iter_dict, "Protocol", args, 2190 sizeof(args) / sizeof(char*))) 2191 goto nomem; 2192 } else { 2193 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol", 2194 &iter_dict_entry, 2195 &iter_dict_val, 2196 &iter_array)) 2197 goto nomem; 2198 2199 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 2200 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 2201 if (!wpa_dbus_dict_string_array_add_element( 2202 &iter_array, "rsn")) 2203 goto nomem; 2204 } 2205 2206 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 2207 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 2208 if (!wpa_dbus_dict_string_array_add_element( 2209 &iter_array, "wpa")) 2210 goto nomem; 2211 } 2212 2213 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2214 &iter_dict_entry, 2215 &iter_dict_val, 2216 &iter_array)) 2217 goto nomem; 2218 } 2219 2220 /***** auth alg */ 2221 if (res < 0) { 2222 const char *args[] = { "open", "shared", "leap" }; 2223 if (!wpa_dbus_dict_append_string_array( 2224 &iter_dict, "AuthAlg", args, 2225 sizeof(args) / sizeof(char*))) 2226 goto nomem; 2227 } else { 2228 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg", 2229 &iter_dict_entry, 2230 &iter_dict_val, 2231 &iter_array)) 2232 goto nomem; 2233 2234 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { 2235 if (!wpa_dbus_dict_string_array_add_element( 2236 &iter_array, "open")) 2237 goto nomem; 2238 } 2239 2240 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { 2241 if (!wpa_dbus_dict_string_array_add_element( 2242 &iter_array, "shared")) 2243 goto nomem; 2244 } 2245 2246 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { 2247 if (!wpa_dbus_dict_string_array_add_element( 2248 &iter_array, "leap")) 2249 goto nomem; 2250 } 2251 2252 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2253 &iter_dict_entry, 2254 &iter_dict_val, 2255 &iter_array)) 2256 goto nomem; 2257 } 2258 2259 /***** Scan */ 2260 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans, 2261 sizeof(scans) / sizeof(char *))) 2262 goto nomem; 2263 2264 /***** Modes */ 2265 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Modes", 2266 &iter_dict_entry, 2267 &iter_dict_val, 2268 &iter_array)) 2269 goto nomem; 2270 2271 if (!wpa_dbus_dict_string_array_add_element( 2272 &iter_array, "infrastructure")) 2273 goto nomem; 2274 2275 if (!wpa_dbus_dict_string_array_add_element( 2276 &iter_array, "ad-hoc")) 2277 goto nomem; 2278 2279 if (res >= 0) { 2280 if (capa.flags & (WPA_DRIVER_FLAGS_AP)) { 2281 if (!wpa_dbus_dict_string_array_add_element( 2282 &iter_array, "ap")) 2283 goto nomem; 2284 } 2285 2286 if (capa.flags & (WPA_DRIVER_FLAGS_P2P_CAPABLE)) { 2287 if (!wpa_dbus_dict_string_array_add_element( 2288 &iter_array, "p2p")) 2289 goto nomem; 2290 } 2291 } 2292 2293 if (!wpa_dbus_dict_end_string_array(&iter_dict, 2294 &iter_dict_entry, 2295 &iter_dict_val, 2296 &iter_array)) 2297 goto nomem; 2298 /***** Modes end */ 2299 2300 if (res >= 0) { 2301 dbus_int32_t max_scan_ssid = capa.max_scan_ssids; 2302 2303 if (!wpa_dbus_dict_append_int32(&iter_dict, "MaxScanSSID", 2304 max_scan_ssid)) 2305 goto nomem; 2306 } 2307 2308 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) 2309 goto nomem; 2310 if (!dbus_message_iter_close_container(iter, &variant_iter)) 2311 goto nomem; 2312 2313 return TRUE; 2314 2315 nomem: 2316 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2317 return FALSE; 2318 } 2319 2320 2321 /** 2322 * wpas_dbus_getter_state - Get interface state 2323 * @iter: Pointer to incoming dbus message iter 2324 * @error: Location to store error on failure 2325 * @user_data: Function specific data 2326 * Returns: TRUE on success, FALSE on failure 2327 * 2328 * Getter for "State" property. 2329 */ 2330 dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error, 2331 void *user_data) 2332 { 2333 struct wpa_supplicant *wpa_s = user_data; 2334 const char *str_state; 2335 char *state_ls, *tmp; 2336 dbus_bool_t success = FALSE; 2337 2338 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 2339 2340 /* make state string lowercase to fit new DBus API convention 2341 */ 2342 state_ls = tmp = os_strdup(str_state); 2343 if (!tmp) { 2344 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2345 return FALSE; 2346 } 2347 while (*tmp) { 2348 *tmp = tolower(*tmp); 2349 tmp++; 2350 } 2351 2352 success = wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2353 &state_ls, error); 2354 2355 os_free(state_ls); 2356 2357 return success; 2358 } 2359 2360 2361 /** 2362 * wpas_dbus_new_iface_get_scanning - Get interface scanning state 2363 * @iter: Pointer to incoming dbus message iter 2364 * @error: Location to store error on failure 2365 * @user_data: Function specific data 2366 * Returns: TRUE on success, FALSE on failure 2367 * 2368 * Getter for "scanning" property. 2369 */ 2370 dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error, 2371 void *user_data) 2372 { 2373 struct wpa_supplicant *wpa_s = user_data; 2374 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 2375 2376 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 2377 &scanning, error); 2378 } 2379 2380 2381 /** 2382 * wpas_dbus_getter_ap_scan - Control roaming mode 2383 * @iter: Pointer to incoming dbus message iter 2384 * @error: Location to store error on failure 2385 * @user_data: Function specific data 2386 * Returns: TRUE on success, FALSE on failure 2387 * 2388 * Getter function for "ApScan" property. 2389 */ 2390 dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error, 2391 void *user_data) 2392 { 2393 struct wpa_supplicant *wpa_s = user_data; 2394 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan; 2395 2396 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2397 &ap_scan, error); 2398 } 2399 2400 2401 /** 2402 * wpas_dbus_setter_ap_scan - Control roaming mode 2403 * @iter: Pointer to incoming dbus message iter 2404 * @error: Location to store error on failure 2405 * @user_data: Function specific data 2406 * Returns: TRUE on success, FALSE on failure 2407 * 2408 * Setter function for "ApScan" property. 2409 */ 2410 dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error, 2411 void *user_data) 2412 { 2413 struct wpa_supplicant *wpa_s = user_data; 2414 dbus_uint32_t ap_scan; 2415 2416 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2417 &ap_scan)) 2418 return FALSE; 2419 2420 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 2421 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2422 "ap_scan must be 0, 1, or 2"); 2423 return FALSE; 2424 } 2425 return TRUE; 2426 } 2427 2428 2429 /** 2430 * wpas_dbus_getter_fast_reauth - Control fast 2431 * reauthentication (TLS session resumption) 2432 * @iter: Pointer to incoming dbus message iter 2433 * @error: Location to store error on failure 2434 * @user_data: Function specific data 2435 * Returns: TRUE on success, FALSE on failure 2436 * 2437 * Getter function for "FastReauth" property. 2438 */ 2439 dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter, 2440 DBusError *error, 2441 void *user_data) 2442 { 2443 struct wpa_supplicant *wpa_s = user_data; 2444 dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE; 2445 2446 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 2447 &fast_reauth, error); 2448 } 2449 2450 2451 /** 2452 * wpas_dbus_setter_fast_reauth - Control fast 2453 * reauthentication (TLS session resumption) 2454 * @iter: Pointer to incoming dbus message iter 2455 * @error: Location to store error on failure 2456 * @user_data: Function specific data 2457 * Returns: TRUE on success, FALSE on failure 2458 * 2459 * Setter function for "FastReauth" property. 2460 */ 2461 dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter, 2462 DBusError *error, 2463 void *user_data) 2464 { 2465 struct wpa_supplicant *wpa_s = user_data; 2466 dbus_bool_t fast_reauth; 2467 2468 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 2469 &fast_reauth)) 2470 return FALSE; 2471 2472 wpa_s->conf->fast_reauth = fast_reauth; 2473 return TRUE; 2474 } 2475 2476 2477 /** 2478 * wpas_dbus_getter_disconnect_reason - Get most recent reason for disconnect 2479 * @iter: Pointer to incoming dbus message iter 2480 * @error: Location to store error on failure 2481 * @user_data: Function specific data 2482 * Returns: TRUE on success, FALSE on failure 2483 * 2484 * Getter for "DisconnectReason" property. The reason is negative if it is 2485 * locally generated. 2486 */ 2487 dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter, 2488 DBusError *error, 2489 void *user_data) 2490 { 2491 struct wpa_supplicant *wpa_s = user_data; 2492 dbus_int32_t reason = wpa_s->disconnect_reason; 2493 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 2494 &reason, error); 2495 } 2496 2497 2498 /** 2499 * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age 2500 * @iter: Pointer to incoming dbus message iter 2501 * @error: Location to store error on failure 2502 * @user_data: Function specific data 2503 * Returns: TRUE on success, FALSE on failure 2504 * 2505 * Getter function for "BSSExpireAge" property. 2506 */ 2507 dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter, 2508 DBusError *error, 2509 void *user_data) 2510 { 2511 struct wpa_supplicant *wpa_s = user_data; 2512 dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age; 2513 2514 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2515 &expire_age, error); 2516 } 2517 2518 2519 /** 2520 * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age 2521 * @iter: Pointer to incoming dbus message iter 2522 * @error: Location to store error on failure 2523 * @user_data: Function specific data 2524 * Returns: TRUE on success, FALSE on failure 2525 * 2526 * Setter function for "BSSExpireAge" property. 2527 */ 2528 dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter, 2529 DBusError *error, 2530 void *user_data) 2531 { 2532 struct wpa_supplicant *wpa_s = user_data; 2533 dbus_uint32_t expire_age; 2534 2535 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2536 &expire_age)) 2537 return FALSE; 2538 2539 if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) { 2540 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2541 "BSSExpireAge must be >= 10"); 2542 return FALSE; 2543 } 2544 return TRUE; 2545 } 2546 2547 2548 /** 2549 * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count 2550 * @iter: Pointer to incoming dbus message iter 2551 * @error: Location to store error on failure 2552 * @user_data: Function specific data 2553 * Returns: TRUE on success, FALSE on failure 2554 * 2555 * Getter function for "BSSExpireCount" property. 2556 */ 2557 dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter, 2558 DBusError *error, 2559 void *user_data) 2560 { 2561 struct wpa_supplicant *wpa_s = user_data; 2562 dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count; 2563 2564 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32, 2565 &expire_count, error); 2566 } 2567 2568 2569 /** 2570 * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count 2571 * @iter: Pointer to incoming dbus message iter 2572 * @error: Location to store error on failure 2573 * @user_data: Function specific data 2574 * Returns: TRUE on success, FALSE on failure 2575 * 2576 * Setter function for "BSSExpireCount" property. 2577 */ 2578 dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter, 2579 DBusError *error, 2580 void *user_data) 2581 { 2582 struct wpa_supplicant *wpa_s = user_data; 2583 dbus_uint32_t expire_count; 2584 2585 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32, 2586 &expire_count)) 2587 return FALSE; 2588 2589 if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) { 2590 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2591 "BSSExpireCount must be > 0"); 2592 return FALSE; 2593 } 2594 return TRUE; 2595 } 2596 2597 2598 /** 2599 * wpas_dbus_getter_country - Control country code 2600 * @iter: Pointer to incoming dbus message iter 2601 * @error: Location to store error on failure 2602 * @user_data: Function specific data 2603 * Returns: TRUE on success, FALSE on failure 2604 * 2605 * Getter function for "Country" property. 2606 */ 2607 dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error, 2608 void *user_data) 2609 { 2610 struct wpa_supplicant *wpa_s = user_data; 2611 char country[3]; 2612 char *str = country; 2613 2614 country[0] = wpa_s->conf->country[0]; 2615 country[1] = wpa_s->conf->country[1]; 2616 country[2] = '\0'; 2617 2618 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2619 &str, error); 2620 } 2621 2622 2623 /** 2624 * wpas_dbus_setter_country - Control country code 2625 * @iter: Pointer to incoming dbus message iter 2626 * @error: Location to store error on failure 2627 * @user_data: Function specific data 2628 * Returns: TRUE on success, FALSE on failure 2629 * 2630 * Setter function for "Country" property. 2631 */ 2632 dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error, 2633 void *user_data) 2634 { 2635 struct wpa_supplicant *wpa_s = user_data; 2636 const char *country; 2637 2638 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, 2639 &country)) 2640 return FALSE; 2641 2642 if (!country[0] || !country[1]) { 2643 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2644 "invalid country code"); 2645 return FALSE; 2646 } 2647 2648 if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) { 2649 wpa_printf(MSG_DEBUG, "Failed to set country"); 2650 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2651 "failed to set country code"); 2652 return FALSE; 2653 } 2654 2655 wpa_s->conf->country[0] = country[0]; 2656 wpa_s->conf->country[1] = country[1]; 2657 return TRUE; 2658 } 2659 2660 2661 /** 2662 * wpas_dbus_getter_scan_interval - Get scan interval 2663 * @iter: Pointer to incoming dbus message iter 2664 * @error: Location to store error on failure 2665 * @user_data: Function specific data 2666 * Returns: TRUE on success, FALSE on failure 2667 * 2668 * Getter function for "ScanInterval" property. 2669 */ 2670 dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter, 2671 DBusError *error, 2672 void *user_data) 2673 { 2674 struct wpa_supplicant *wpa_s = user_data; 2675 dbus_int32_t scan_interval = wpa_s->scan_interval; 2676 2677 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32, 2678 &scan_interval, error); 2679 } 2680 2681 2682 /** 2683 * wpas_dbus_setter_scan_interval - Control scan interval 2684 * @iter: Pointer to incoming dbus message iter 2685 * @error: Location to store error on failure 2686 * @user_data: Function specific data 2687 * Returns: TRUE on success, FALSE on failure 2688 * 2689 * Setter function for "ScanInterval" property. 2690 */ 2691 dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter, 2692 DBusError *error, 2693 void *user_data) 2694 { 2695 struct wpa_supplicant *wpa_s = user_data; 2696 dbus_int32_t scan_interval; 2697 2698 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_INT32, 2699 &scan_interval)) 2700 return FALSE; 2701 2702 if (wpa_supplicant_set_scan_interval(wpa_s, scan_interval)) { 2703 dbus_set_error_const(error, DBUS_ERROR_FAILED, 2704 "scan_interval must be >= 0"); 2705 return FALSE; 2706 } 2707 return TRUE; 2708 } 2709 2710 2711 /** 2712 * wpas_dbus_getter_ifname - Get interface name 2713 * @iter: Pointer to incoming dbus message iter 2714 * @error: Location to store error on failure 2715 * @user_data: Function specific data 2716 * Returns: TRUE on success, FALSE on failure 2717 * 2718 * Getter for "Ifname" property. 2719 */ 2720 dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error, 2721 void *user_data) 2722 { 2723 struct wpa_supplicant *wpa_s = user_data; 2724 const char *ifname = wpa_s->ifname; 2725 2726 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2727 &ifname, error); 2728 } 2729 2730 2731 /** 2732 * wpas_dbus_getter_driver - Get interface name 2733 * @iter: Pointer to incoming dbus message iter 2734 * @error: Location to store error on failure 2735 * @user_data: Function specific data 2736 * Returns: TRUE on success, FALSE on failure 2737 * 2738 * Getter for "Driver" property. 2739 */ 2740 dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error, 2741 void *user_data) 2742 { 2743 struct wpa_supplicant *wpa_s = user_data; 2744 const char *driver; 2745 2746 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) { 2747 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: " 2748 "wpa_s has no driver set"); 2749 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: no driver set", 2750 __func__); 2751 return FALSE; 2752 } 2753 2754 driver = wpa_s->driver->name; 2755 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2756 &driver, error); 2757 } 2758 2759 2760 /** 2761 * wpas_dbus_getter_current_bss - Get current bss object path 2762 * @iter: Pointer to incoming dbus message iter 2763 * @error: Location to store error on failure 2764 * @user_data: Function specific data 2765 * Returns: TRUE on success, FALSE on failure 2766 * 2767 * Getter for "CurrentBSS" property. 2768 */ 2769 dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter, 2770 DBusError *error, 2771 void *user_data) 2772 { 2773 struct wpa_supplicant *wpa_s = user_data; 2774 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf; 2775 2776 if (wpa_s->current_bss) 2777 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2778 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2779 wpa_s->dbus_new_path, wpa_s->current_bss->id); 2780 else 2781 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 2782 2783 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 2784 &bss_obj_path, error); 2785 } 2786 2787 2788 /** 2789 * wpas_dbus_getter_current_network - Get current network object path 2790 * @iter: Pointer to incoming dbus message iter 2791 * @error: Location to store error on failure 2792 * @user_data: Function specific data 2793 * Returns: TRUE on success, FALSE on failure 2794 * 2795 * Getter for "CurrentNetwork" property. 2796 */ 2797 dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter, 2798 DBusError *error, 2799 void *user_data) 2800 { 2801 struct wpa_supplicant *wpa_s = user_data; 2802 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf; 2803 2804 if (wpa_s->current_ssid) 2805 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2806 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2807 wpa_s->dbus_new_path, wpa_s->current_ssid->id); 2808 else 2809 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 2810 2811 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_OBJECT_PATH, 2812 &net_obj_path, error); 2813 } 2814 2815 2816 /** 2817 * wpas_dbus_getter_current_auth_mode - Get current authentication type 2818 * @iter: Pointer to incoming dbus message iter 2819 * @error: Location to store error on failure 2820 * @user_data: Function specific data 2821 * Returns: TRUE on success, FALSE on failure 2822 * 2823 * Getter for "CurrentAuthMode" property. 2824 */ 2825 dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter, 2826 DBusError *error, 2827 void *user_data) 2828 { 2829 struct wpa_supplicant *wpa_s = user_data; 2830 const char *eap_mode; 2831 const char *auth_mode; 2832 char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX]; 2833 2834 if (wpa_s->wpa_state != WPA_COMPLETED) { 2835 auth_mode = "INACTIVE"; 2836 } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || 2837 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 2838 eap_mode = wpa_supplicant_get_eap_mode(wpa_s); 2839 os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX, 2840 "EAP-%s", eap_mode); 2841 auth_mode = eap_mode_buf; 2842 2843 } else { 2844 auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt, 2845 wpa_s->current_ssid->proto); 2846 } 2847 2848 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2849 &auth_mode, error); 2850 } 2851 2852 2853 /** 2854 * wpas_dbus_getter_bridge_ifname - Get interface name 2855 * @iter: Pointer to incoming dbus message iter 2856 * @error: Location to store error on failure 2857 * @user_data: Function specific data 2858 * Returns: TRUE on success, FALSE on failure 2859 * 2860 * Getter for "BridgeIfname" property. 2861 */ 2862 dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter, 2863 DBusError *error, 2864 void *user_data) 2865 { 2866 struct wpa_supplicant *wpa_s = user_data; 2867 const char *bridge_ifname = wpa_s->bridge_ifname; 2868 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 2869 &bridge_ifname, error); 2870 } 2871 2872 2873 /** 2874 * wpas_dbus_getter_bsss - Get array of BSSs objects 2875 * @iter: Pointer to incoming dbus message iter 2876 * @error: Location to store error on failure 2877 * @user_data: Function specific data 2878 * Returns: TRUE on success, FALSE on failure 2879 * 2880 * Getter for "BSSs" property. 2881 */ 2882 dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error, 2883 void *user_data) 2884 { 2885 struct wpa_supplicant *wpa_s = user_data; 2886 struct wpa_bss *bss; 2887 char **paths; 2888 unsigned int i = 0; 2889 dbus_bool_t success = FALSE; 2890 2891 paths = os_calloc(wpa_s->num_bss, sizeof(char *)); 2892 if (!paths) { 2893 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2894 return FALSE; 2895 } 2896 2897 /* Loop through scan results and append each result's object path */ 2898 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 2899 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 2900 if (paths[i] == NULL) { 2901 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 2902 "no memory"); 2903 goto out; 2904 } 2905 /* Construct the object path for this BSS. */ 2906 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 2907 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2908 wpa_s->dbus_new_path, bss->id); 2909 } 2910 2911 success = wpas_dbus_simple_array_property_getter(iter, 2912 DBUS_TYPE_OBJECT_PATH, 2913 paths, wpa_s->num_bss, 2914 error); 2915 2916 out: 2917 while (i) 2918 os_free(paths[--i]); 2919 os_free(paths); 2920 return success; 2921 } 2922 2923 2924 /** 2925 * wpas_dbus_getter_networks - Get array of networks objects 2926 * @iter: Pointer to incoming dbus message iter 2927 * @error: Location to store error on failure 2928 * @user_data: Function specific data 2929 * Returns: TRUE on success, FALSE on failure 2930 * 2931 * Getter for "Networks" property. 2932 */ 2933 dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error, 2934 void *user_data) 2935 { 2936 struct wpa_supplicant *wpa_s = user_data; 2937 struct wpa_ssid *ssid; 2938 char **paths; 2939 unsigned int i = 0, num = 0; 2940 dbus_bool_t success = FALSE; 2941 2942 if (wpa_s->conf == NULL) { 2943 wpa_printf(MSG_ERROR, "%s[dbus]: An error occurred getting " 2944 "networks list.", __func__); 2945 dbus_set_error(error, DBUS_ERROR_FAILED, "%s: an error " 2946 "occurred getting the networks list", __func__); 2947 return FALSE; 2948 } 2949 2950 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 2951 if (!network_is_persistent_group(ssid)) 2952 num++; 2953 2954 paths = os_calloc(num, sizeof(char *)); 2955 if (!paths) { 2956 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2957 return FALSE; 2958 } 2959 2960 /* Loop through configured networks and append object path of each */ 2961 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 2962 if (network_is_persistent_group(ssid)) 2963 continue; 2964 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 2965 if (paths[i] == NULL) { 2966 dbus_set_error(error, DBUS_ERROR_NO_MEMORY, "no memory"); 2967 goto out; 2968 } 2969 2970 /* Construct the object path for this network. */ 2971 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 2972 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 2973 wpa_s->dbus_new_path, ssid->id); 2974 } 2975 2976 success = wpas_dbus_simple_array_property_getter(iter, 2977 DBUS_TYPE_OBJECT_PATH, 2978 paths, num, error); 2979 2980 out: 2981 while (i) 2982 os_free(paths[--i]); 2983 os_free(paths); 2984 return success; 2985 } 2986 2987 2988 /** 2989 * wpas_dbus_getter_blobs - Get all blobs defined for this interface 2990 * @iter: Pointer to incoming dbus message iter 2991 * @error: Location to store error on failure 2992 * @user_data: Function specific data 2993 * Returns: TRUE on success, FALSE on failure 2994 * 2995 * Getter for "Blobs" property. 2996 */ 2997 dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error, 2998 void *user_data) 2999 { 3000 struct wpa_supplicant *wpa_s = user_data; 3001 DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter; 3002 struct wpa_config_blob *blob; 3003 3004 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3005 "a{say}", &variant_iter) || 3006 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 3007 "{say}", &dict_iter)) { 3008 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3009 return FALSE; 3010 } 3011 3012 blob = wpa_s->conf->blobs; 3013 while (blob) { 3014 if (!dbus_message_iter_open_container(&dict_iter, 3015 DBUS_TYPE_DICT_ENTRY, 3016 NULL, &entry_iter) || 3017 !dbus_message_iter_append_basic(&entry_iter, 3018 DBUS_TYPE_STRING, 3019 &(blob->name)) || 3020 !dbus_message_iter_open_container(&entry_iter, 3021 DBUS_TYPE_ARRAY, 3022 DBUS_TYPE_BYTE_AS_STRING, 3023 &array_iter) || 3024 !dbus_message_iter_append_fixed_array(&array_iter, 3025 DBUS_TYPE_BYTE, 3026 &(blob->data), 3027 blob->len) || 3028 !dbus_message_iter_close_container(&entry_iter, 3029 &array_iter) || 3030 !dbus_message_iter_close_container(&dict_iter, 3031 &entry_iter)) { 3032 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 3033 "no memory"); 3034 return FALSE; 3035 } 3036 3037 blob = blob->next; 3038 } 3039 3040 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) || 3041 !dbus_message_iter_close_container(iter, &variant_iter)) { 3042 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3043 return FALSE; 3044 } 3045 3046 return TRUE; 3047 } 3048 3049 3050 static struct wpa_bss * get_bss_helper(struct bss_handler_args *args, 3051 DBusError *error, const char *func_name) 3052 { 3053 struct wpa_bss *res = wpa_bss_get_id(args->wpa_s, args->id); 3054 3055 if (!res) { 3056 wpa_printf(MSG_ERROR, "%s[dbus]: no bss with id %d found", 3057 func_name, args->id); 3058 dbus_set_error(error, DBUS_ERROR_FAILED, 3059 "%s: BSS %d not found", 3060 func_name, args->id); 3061 } 3062 3063 return res; 3064 } 3065 3066 3067 /** 3068 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS 3069 * @iter: Pointer to incoming dbus message iter 3070 * @error: Location to store error on failure 3071 * @user_data: Function specific data 3072 * Returns: TRUE on success, FALSE on failure 3073 * 3074 * Getter for "BSSID" property. 3075 */ 3076 dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error, 3077 void *user_data) 3078 { 3079 struct bss_handler_args *args = user_data; 3080 struct wpa_bss *res; 3081 3082 res = get_bss_helper(args, error, __func__); 3083 if (!res) 3084 return FALSE; 3085 3086 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3087 res->bssid, ETH_ALEN, 3088 error); 3089 } 3090 3091 3092 /** 3093 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS 3094 * @iter: Pointer to incoming dbus message iter 3095 * @error: Location to store error on failure 3096 * @user_data: Function specific data 3097 * Returns: TRUE on success, FALSE on failure 3098 * 3099 * Getter for "SSID" property. 3100 */ 3101 dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error, 3102 void *user_data) 3103 { 3104 struct bss_handler_args *args = user_data; 3105 struct wpa_bss *res; 3106 3107 res = get_bss_helper(args, error, __func__); 3108 if (!res) 3109 return FALSE; 3110 3111 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3112 res->ssid, res->ssid_len, 3113 error); 3114 } 3115 3116 3117 /** 3118 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS 3119 * @iter: Pointer to incoming dbus message iter 3120 * @error: Location to store error on failure 3121 * @user_data: Function specific data 3122 * Returns: TRUE on success, FALSE on failure 3123 * 3124 * Getter for "Privacy" property. 3125 */ 3126 dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter, 3127 DBusError *error, void *user_data) 3128 { 3129 struct bss_handler_args *args = user_data; 3130 struct wpa_bss *res; 3131 dbus_bool_t privacy; 3132 3133 res = get_bss_helper(args, error, __func__); 3134 if (!res) 3135 return FALSE; 3136 3137 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE; 3138 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3139 &privacy, error); 3140 } 3141 3142 3143 /** 3144 * wpas_dbus_getter_bss_mode - Return the mode of a BSS 3145 * @iter: Pointer to incoming dbus message iter 3146 * @error: Location to store error on failure 3147 * @user_data: Function specific data 3148 * Returns: TRUE on success, FALSE on failure 3149 * 3150 * Getter for "Mode" property. 3151 */ 3152 dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error, 3153 void *user_data) 3154 { 3155 struct bss_handler_args *args = user_data; 3156 struct wpa_bss *res; 3157 const char *mode; 3158 3159 res = get_bss_helper(args, error, __func__); 3160 if (!res) 3161 return FALSE; 3162 3163 if (res->caps & IEEE80211_CAP_IBSS) 3164 mode = "ad-hoc"; 3165 else 3166 mode = "infrastructure"; 3167 3168 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, 3169 &mode, error); 3170 } 3171 3172 3173 /** 3174 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS 3175 * @iter: Pointer to incoming dbus message iter 3176 * @error: Location to store error on failure 3177 * @user_data: Function specific data 3178 * Returns: TRUE on success, FALSE on failure 3179 * 3180 * Getter for "Level" property. 3181 */ 3182 dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter, 3183 DBusError *error, void *user_data) 3184 { 3185 struct bss_handler_args *args = user_data; 3186 struct wpa_bss *res; 3187 s16 level; 3188 3189 res = get_bss_helper(args, error, __func__); 3190 if (!res) 3191 return FALSE; 3192 3193 level = (s16) res->level; 3194 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT16, 3195 &level, error); 3196 } 3197 3198 3199 /** 3200 * wpas_dbus_getter_bss_frequency - Return the frequency 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 "Frequency" property. 3207 */ 3208 dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter, 3209 DBusError *error, void *user_data) 3210 { 3211 struct bss_handler_args *args = user_data; 3212 struct wpa_bss *res; 3213 u16 freq; 3214 3215 res = get_bss_helper(args, error, __func__); 3216 if (!res) 3217 return FALSE; 3218 3219 freq = (u16) res->freq; 3220 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT16, 3221 &freq, error); 3222 } 3223 3224 3225 static int cmp_u8s_desc(const void *a, const void *b) 3226 { 3227 return (*(u8 *) b - *(u8 *) a); 3228 } 3229 3230 3231 /** 3232 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS 3233 * @iter: Pointer to incoming dbus message iter 3234 * @error: Location to store error on failure 3235 * @user_data: Function specific data 3236 * Returns: TRUE on success, FALSE on failure 3237 * 3238 * Getter for "Rates" property. 3239 */ 3240 dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter, 3241 DBusError *error, void *user_data) 3242 { 3243 struct bss_handler_args *args = user_data; 3244 struct wpa_bss *res; 3245 u8 *ie_rates = NULL; 3246 u32 *real_rates; 3247 int rates_num, i; 3248 dbus_bool_t success = FALSE; 3249 3250 res = get_bss_helper(args, error, __func__); 3251 if (!res) 3252 return FALSE; 3253 3254 rates_num = wpa_bss_get_bit_rates(res, &ie_rates); 3255 if (rates_num < 0) 3256 return FALSE; 3257 3258 qsort(ie_rates, rates_num, 1, cmp_u8s_desc); 3259 3260 real_rates = os_malloc(sizeof(u32) * rates_num); 3261 if (!real_rates) { 3262 os_free(ie_rates); 3263 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3264 return FALSE; 3265 } 3266 3267 for (i = 0; i < rates_num; i++) 3268 real_rates[i] = ie_rates[i] * 500000; 3269 3270 success = wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_UINT32, 3271 real_rates, rates_num, 3272 error); 3273 3274 os_free(ie_rates); 3275 os_free(real_rates); 3276 return success; 3277 } 3278 3279 3280 static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, 3281 struct wpa_ie_data *ie_data, 3282 DBusError *error) 3283 { 3284 DBusMessageIter iter_dict, variant_iter; 3285 const char *group; 3286 const char *pairwise[3]; /* max 3 pairwise ciphers is supported */ 3287 const char *key_mgmt[7]; /* max 7 key managements may be supported */ 3288 int n; 3289 3290 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3291 "a{sv}", &variant_iter)) 3292 goto nomem; 3293 3294 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 3295 goto nomem; 3296 3297 /* KeyMgmt */ 3298 n = 0; 3299 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK) 3300 key_mgmt[n++] = "wpa-psk"; 3301 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK) 3302 key_mgmt[n++] = "wpa-ft-psk"; 3303 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 3304 key_mgmt[n++] = "wpa-psk-sha256"; 3305 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X) 3306 key_mgmt[n++] = "wpa-eap"; 3307 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 3308 key_mgmt[n++] = "wpa-ft-eap"; 3309 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 3310 key_mgmt[n++] = "wpa-eap-sha256"; 3311 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE) 3312 key_mgmt[n++] = "wpa-none"; 3313 3314 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt", 3315 key_mgmt, n)) 3316 goto nomem; 3317 3318 /* Group */ 3319 switch (ie_data->group_cipher) { 3320 case WPA_CIPHER_WEP40: 3321 group = "wep40"; 3322 break; 3323 case WPA_CIPHER_TKIP: 3324 group = "tkip"; 3325 break; 3326 case WPA_CIPHER_CCMP: 3327 group = "ccmp"; 3328 break; 3329 case WPA_CIPHER_GCMP: 3330 group = "gcmp"; 3331 break; 3332 case WPA_CIPHER_WEP104: 3333 group = "wep104"; 3334 break; 3335 default: 3336 group = ""; 3337 break; 3338 } 3339 3340 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group)) 3341 goto nomem; 3342 3343 /* Pairwise */ 3344 n = 0; 3345 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP) 3346 pairwise[n++] = "tkip"; 3347 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP) 3348 pairwise[n++] = "ccmp"; 3349 if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP) 3350 pairwise[n++] = "gcmp"; 3351 3352 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise", 3353 pairwise, n)) 3354 goto nomem; 3355 3356 /* Management group (RSN only) */ 3357 if (ie_data->proto == WPA_PROTO_RSN) { 3358 switch (ie_data->mgmt_group_cipher) { 3359 #ifdef CONFIG_IEEE80211W 3360 case WPA_CIPHER_AES_128_CMAC: 3361 group = "aes128cmac"; 3362 break; 3363 #endif /* CONFIG_IEEE80211W */ 3364 default: 3365 group = ""; 3366 break; 3367 } 3368 3369 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup", 3370 group)) 3371 goto nomem; 3372 } 3373 3374 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) 3375 goto nomem; 3376 if (!dbus_message_iter_close_container(iter, &variant_iter)) 3377 goto nomem; 3378 3379 return TRUE; 3380 3381 nomem: 3382 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3383 return FALSE; 3384 } 3385 3386 3387 /** 3388 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS 3389 * @iter: Pointer to incoming dbus message iter 3390 * @error: Location to store error on failure 3391 * @user_data: Function specific data 3392 * Returns: TRUE on success, FALSE on failure 3393 * 3394 * Getter for "WPA" property. 3395 */ 3396 dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error, 3397 void *user_data) 3398 { 3399 struct bss_handler_args *args = user_data; 3400 struct wpa_bss *res; 3401 struct wpa_ie_data wpa_data; 3402 const u8 *ie; 3403 3404 res = get_bss_helper(args, error, __func__); 3405 if (!res) 3406 return FALSE; 3407 3408 os_memset(&wpa_data, 0, sizeof(wpa_data)); 3409 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); 3410 if (ie) { 3411 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { 3412 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3413 "failed to parse WPA IE"); 3414 return FALSE; 3415 } 3416 } 3417 3418 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error); 3419 } 3420 3421 3422 /** 3423 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS 3424 * @iter: Pointer to incoming dbus message iter 3425 * @error: Location to store error on failure 3426 * @user_data: Function specific data 3427 * Returns: TRUE on success, FALSE on failure 3428 * 3429 * Getter for "RSN" property. 3430 */ 3431 dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error, 3432 void *user_data) 3433 { 3434 struct bss_handler_args *args = user_data; 3435 struct wpa_bss *res; 3436 struct wpa_ie_data wpa_data; 3437 const u8 *ie; 3438 3439 res = get_bss_helper(args, error, __func__); 3440 if (!res) 3441 return FALSE; 3442 3443 os_memset(&wpa_data, 0, sizeof(wpa_data)); 3444 ie = wpa_bss_get_ie(res, WLAN_EID_RSN); 3445 if (ie) { 3446 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) { 3447 dbus_set_error_const(error, DBUS_ERROR_FAILED, 3448 "failed to parse RSN IE"); 3449 return FALSE; 3450 } 3451 } 3452 3453 return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error); 3454 } 3455 3456 3457 /** 3458 * wpas_dbus_getter_bss_wps - Return the WPS options of a BSS 3459 * @iter: Pointer to incoming dbus message iter 3460 * @error: Location to store error on failure 3461 * @user_data: Function specific data 3462 * Returns: TRUE on success, FALSE on failure 3463 * 3464 * Getter for "WPS" property. 3465 */ 3466 dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error, 3467 void *user_data) 3468 { 3469 struct bss_handler_args *args = user_data; 3470 struct wpa_bss *res; 3471 #ifdef CONFIG_WPS 3472 struct wpabuf *wps_ie; 3473 #endif /* CONFIG_WPS */ 3474 DBusMessageIter iter_dict, variant_iter; 3475 const char *type = ""; 3476 3477 res = get_bss_helper(args, error, __func__); 3478 if (!res) 3479 return FALSE; 3480 3481 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, 3482 "a{sv}", &variant_iter)) 3483 goto nomem; 3484 3485 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 3486 goto nomem; 3487 3488 #ifdef CONFIG_WPS 3489 wps_ie = wpa_bss_get_vendor_ie_multi(res, WPS_IE_VENDOR_TYPE); 3490 if (wps_ie) { 3491 if (wps_is_selected_pbc_registrar(wps_ie)) 3492 type = "pbc"; 3493 else if (wps_is_selected_pin_registrar(wps_ie)) 3494 type = "pin"; 3495 } 3496 #endif /* CONFIG_WPS */ 3497 3498 if (!wpa_dbus_dict_append_string(&iter_dict, "Type", type)) 3499 goto nomem; 3500 3501 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) 3502 goto nomem; 3503 if (!dbus_message_iter_close_container(iter, &variant_iter)) 3504 goto nomem; 3505 3506 return TRUE; 3507 3508 nomem: 3509 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3510 return FALSE; 3511 } 3512 3513 3514 /** 3515 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS 3516 * @iter: Pointer to incoming dbus message iter 3517 * @error: Location to store error on failure 3518 * @user_data: Function specific data 3519 * Returns: TRUE on success, FALSE on failure 3520 * 3521 * Getter for "IEs" property. 3522 */ 3523 dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error, 3524 void *user_data) 3525 { 3526 struct bss_handler_args *args = user_data; 3527 struct wpa_bss *res; 3528 3529 res = get_bss_helper(args, error, __func__); 3530 if (!res) 3531 return FALSE; 3532 3533 return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE, 3534 res + 1, res->ie_len, 3535 error); 3536 } 3537 3538 3539 /** 3540 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled 3541 * @iter: Pointer to incoming dbus message iter 3542 * @error: Location to store error on failure 3543 * @user_data: Function specific data 3544 * Returns: TRUE on success, FALSE on failure 3545 * 3546 * Getter for "enabled" property of a configured network. 3547 */ 3548 dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error, 3549 void *user_data) 3550 { 3551 struct network_handler_args *net = user_data; 3552 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE; 3553 3554 return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN, 3555 &enabled, error); 3556 } 3557 3558 3559 /** 3560 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled 3561 * @iter: Pointer to incoming dbus message iter 3562 * @error: Location to store error on failure 3563 * @user_data: Function specific data 3564 * Returns: TRUE on success, FALSE on failure 3565 * 3566 * Setter for "Enabled" property of a configured network. 3567 */ 3568 dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error, 3569 void *user_data) 3570 { 3571 struct network_handler_args *net = user_data; 3572 struct wpa_supplicant *wpa_s; 3573 struct wpa_ssid *ssid; 3574 dbus_bool_t enable; 3575 3576 if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_BOOLEAN, 3577 &enable)) 3578 return FALSE; 3579 3580 wpa_s = net->wpa_s; 3581 ssid = net->ssid; 3582 3583 if (enable) 3584 wpa_supplicant_enable_network(wpa_s, ssid); 3585 else 3586 wpa_supplicant_disable_network(wpa_s, ssid); 3587 3588 return TRUE; 3589 } 3590 3591 3592 /** 3593 * wpas_dbus_getter_network_properties - Get options for a configured network 3594 * @iter: Pointer to incoming dbus message iter 3595 * @error: Location to store error on failure 3596 * @user_data: Function specific data 3597 * Returns: TRUE on success, FALSE on failure 3598 * 3599 * Getter for "Properties" property of a configured network. 3600 */ 3601 dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter, 3602 DBusError *error, 3603 void *user_data) 3604 { 3605 struct network_handler_args *net = user_data; 3606 DBusMessageIter variant_iter, dict_iter; 3607 char **iterator; 3608 char **props = wpa_config_get_all(net->ssid, 1); 3609 dbus_bool_t success = FALSE; 3610 3611 if (!props) { 3612 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3613 return FALSE; 3614 } 3615 3616 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{sv}", 3617 &variant_iter) || 3618 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) { 3619 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3620 goto out; 3621 } 3622 3623 iterator = props; 3624 while (*iterator) { 3625 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator, 3626 *(iterator + 1))) { 3627 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 3628 "no memory"); 3629 goto out; 3630 } 3631 iterator += 2; 3632 } 3633 3634 3635 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || 3636 !dbus_message_iter_close_container(iter, &variant_iter)) { 3637 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, "no memory"); 3638 goto out; 3639 } 3640 3641 success = TRUE; 3642 3643 out: 3644 iterator = props; 3645 while (*iterator) { 3646 os_free(*iterator); 3647 iterator++; 3648 } 3649 os_free(props); 3650 return success; 3651 } 3652 3653 3654 /** 3655 * wpas_dbus_setter_network_properties - Set options for a configured network 3656 * @iter: Pointer to incoming dbus message iter 3657 * @error: Location to store error on failure 3658 * @user_data: Function specific data 3659 * Returns: TRUE on success, FALSE on failure 3660 * 3661 * Setter for "Properties" property of a configured network. 3662 */ 3663 dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter, 3664 DBusError *error, 3665 void *user_data) 3666 { 3667 struct network_handler_args *net = user_data; 3668 struct wpa_ssid *ssid = net->ssid; 3669 DBusMessageIter variant_iter; 3670 3671 dbus_message_iter_recurse(iter, &variant_iter); 3672 return set_network_properties(net->wpa_s, ssid, &variant_iter, error); 3673 } 3674 3675 3676 #ifdef CONFIG_AP 3677 3678 DBusMessage * wpas_dbus_handler_subscribe_preq( 3679 DBusMessage *message, struct wpa_supplicant *wpa_s) 3680 { 3681 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 3682 char *name; 3683 3684 if (wpa_s->preq_notify_peer != NULL) { 3685 if (os_strcmp(dbus_message_get_sender(message), 3686 wpa_s->preq_notify_peer) == 0) 3687 return NULL; 3688 3689 return dbus_message_new_error(message, 3690 WPAS_DBUS_ERROR_SUBSCRIPTION_IN_USE, 3691 "Another application is already subscribed"); 3692 } 3693 3694 name = os_strdup(dbus_message_get_sender(message)); 3695 if (!name) 3696 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 3697 "out of memory"); 3698 3699 wpa_s->preq_notify_peer = name; 3700 3701 /* Subscribe to clean up if application closes socket */ 3702 wpas_dbus_subscribe_noc(priv); 3703 3704 /* 3705 * Double-check it's still alive to make sure that we didn't 3706 * miss the NameOwnerChanged signal, e.g. while strdup'ing. 3707 */ 3708 if (!dbus_bus_name_has_owner(priv->con, name, NULL)) { 3709 /* 3710 * Application no longer exists, clean up. 3711 * The return value is irrelevant now. 3712 * 3713 * Need to check if the NameOwnerChanged handling 3714 * already cleaned up because we have processed 3715 * DBus messages while checking if the name still 3716 * has an owner. 3717 */ 3718 if (!wpa_s->preq_notify_peer) 3719 return NULL; 3720 os_free(wpa_s->preq_notify_peer); 3721 wpa_s->preq_notify_peer = NULL; 3722 wpas_dbus_unsubscribe_noc(priv); 3723 } 3724 3725 return NULL; 3726 } 3727 3728 3729 DBusMessage * wpas_dbus_handler_unsubscribe_preq( 3730 DBusMessage *message, struct wpa_supplicant *wpa_s) 3731 { 3732 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 3733 3734 if (!wpa_s->preq_notify_peer) 3735 return dbus_message_new_error(message, 3736 WPAS_DBUS_ERROR_NO_SUBSCRIPTION, 3737 "Not subscribed"); 3738 3739 if (os_strcmp(wpa_s->preq_notify_peer, 3740 dbus_message_get_sender(message))) 3741 return dbus_message_new_error(message, 3742 WPAS_DBUS_ERROR_SUBSCRIPTION_EPERM, 3743 "Can't unsubscribe others"); 3744 3745 os_free(wpa_s->preq_notify_peer); 3746 wpa_s->preq_notify_peer = NULL; 3747 wpas_dbus_unsubscribe_noc(priv); 3748 return NULL; 3749 } 3750 3751 3752 void wpas_dbus_signal_preq(struct wpa_supplicant *wpa_s, 3753 const u8 *addr, const u8 *dst, const u8 *bssid, 3754 const u8 *ie, size_t ie_len, u32 ssi_signal) 3755 { 3756 DBusMessage *msg; 3757 DBusMessageIter iter, dict_iter; 3758 struct wpas_dbus_priv *priv = wpa_s->global->dbus; 3759 3760 /* Do nothing if the control interface is not turned on */ 3761 if (priv == NULL) 3762 return; 3763 3764 if (wpa_s->preq_notify_peer == NULL) 3765 return; 3766 3767 msg = dbus_message_new_signal(wpa_s->dbus_new_path, 3768 WPAS_DBUS_NEW_IFACE_INTERFACE, 3769 "ProbeRequest"); 3770 if (msg == NULL) 3771 return; 3772 3773 dbus_message_set_destination(msg, wpa_s->preq_notify_peer); 3774 3775 dbus_message_iter_init_append(msg, &iter); 3776 3777 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) 3778 goto fail; 3779 if (addr && !wpa_dbus_dict_append_byte_array(&dict_iter, "addr", 3780 (const char *) addr, 3781 ETH_ALEN)) 3782 goto fail; 3783 if (dst && !wpa_dbus_dict_append_byte_array(&dict_iter, "dst", 3784 (const char *) dst, 3785 ETH_ALEN)) 3786 goto fail; 3787 if (bssid && !wpa_dbus_dict_append_byte_array(&dict_iter, "bssid", 3788 (const char *) bssid, 3789 ETH_ALEN)) 3790 goto fail; 3791 if (ie && ie_len && !wpa_dbus_dict_append_byte_array(&dict_iter, "ies", 3792 (const char *) ie, 3793 ie_len)) 3794 goto fail; 3795 if (ssi_signal && !wpa_dbus_dict_append_int32(&dict_iter, "signal", 3796 ssi_signal)) 3797 goto fail; 3798 if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) 3799 goto fail; 3800 3801 dbus_connection_send(priv->con, msg, NULL); 3802 goto out; 3803 fail: 3804 wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); 3805 out: 3806 dbus_message_unref(msg); 3807 } 3808 3809 #endif /* CONFIG_AP */ 3810