1 /* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 4 * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com> 5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * Alternatively, this software may be distributed under the terms of BSD 12 * license. 13 * 14 * See README and COPYING for more details. 15 */ 16 17 #include "includes.h" 18 19 #include "common.h" 20 #include "common/ieee802_11_defs.h" 21 #include "eap_peer/eap_methods.h" 22 #include "eapol_supp/eapol_supp_sm.h" 23 #include "rsn_supp/wpa.h" 24 #include "../config.h" 25 #include "../wpa_supplicant_i.h" 26 #include "../driver_i.h" 27 #include "../notify.h" 28 #include "../wpas_glue.h" 29 #include "../bss.h" 30 #include "../scan.h" 31 #include "dbus_new_helpers.h" 32 #include "dbus_new.h" 33 #include "dbus_new_handlers.h" 34 #include "dbus_dict_helpers.h" 35 36 extern int wpa_debug_level; 37 extern int wpa_debug_show_keys; 38 extern int wpa_debug_timestamp; 39 40 static const char *debug_strings[] = { 41 "msgdump", "debug", "info", "warning", "error", NULL 42 }; 43 44 45 /** 46 * wpas_dbus_new_decompose_object_path - Decompose an interface object path into parts 47 * @path: The dbus object path 48 * @network: (out) the configured network this object path refers to, if any 49 * @bssid: (out) the scanned bssid this object path refers to, if any 50 * Returns: The object path of the network interface this path refers to 51 * 52 * For a given object path, decomposes the object path into object id, network, 53 * and BSSID parts, if those parts exist. 54 */ 55 static char * wpas_dbus_new_decompose_object_path(const char *path, 56 char **network, 57 char **bssid) 58 { 59 const unsigned int dev_path_prefix_len = 60 strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/"); 61 char *obj_path_only; 62 char *next_sep; 63 64 /* Be a bit paranoid about path */ 65 if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/", 66 dev_path_prefix_len)) 67 return NULL; 68 69 /* Ensure there's something at the end of the path */ 70 if ((path + dev_path_prefix_len)[0] == '\0') 71 return NULL; 72 73 obj_path_only = os_strdup(path); 74 if (obj_path_only == NULL) 75 return NULL; 76 77 next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/'); 78 if (next_sep != NULL) { 79 const char *net_part = os_strstr( 80 next_sep, WPAS_DBUS_NEW_NETWORKS_PART "/"); 81 const char *bssid_part = os_strstr( 82 next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/"); 83 84 if (network && net_part) { 85 /* Deal with a request for a configured network */ 86 const char *net_name = net_part + 87 os_strlen(WPAS_DBUS_NEW_NETWORKS_PART "/"); 88 *network = NULL; 89 if (os_strlen(net_name)) 90 *network = os_strdup(net_name); 91 } else if (bssid && bssid_part) { 92 /* Deal with a request for a scanned BSSID */ 93 const char *bssid_name = bssid_part + 94 os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/"); 95 if (strlen(bssid_name)) 96 *bssid = os_strdup(bssid_name); 97 else 98 *bssid = NULL; 99 } 100 101 /* Cut off interface object path before "/" */ 102 *next_sep = '\0'; 103 } 104 105 return obj_path_only; 106 } 107 108 109 /** 110 * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message 111 * @message: Pointer to incoming dbus message this error refers to 112 * @arg: Optional string appended to error message 113 * Returns: a dbus error message 114 * 115 * Convenience function to create and return an UnknownError 116 */ 117 DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message, 118 const char *arg) 119 { 120 return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR, 121 arg); 122 } 123 124 125 /** 126 * wpas_dbus_error_iface_unknown - Return a new invalid interface error message 127 * @message: Pointer to incoming dbus message this error refers to 128 * Returns: A dbus error message 129 * 130 * Convenience function to create and return an invalid interface error 131 */ 132 static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message) 133 { 134 return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN, 135 "wpa_supplicant knows nothing about " 136 "this interface."); 137 } 138 139 140 /** 141 * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message 142 * @message: Pointer to incoming dbus message this error refers to 143 * Returns: a dbus error message 144 * 145 * Convenience function to create and return an invalid network error 146 */ 147 static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message) 148 { 149 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN, 150 "There is no such a network in this " 151 "interface."); 152 } 153 154 155 /** 156 * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message 157 * @message: Pointer to incoming dbus message this error refers to 158 * Returns: a dbus error message 159 * 160 * Convenience function to create and return an invalid options error 161 */ 162 DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message, 163 const char *arg) 164 { 165 DBusMessage *reply; 166 167 reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS, 168 "Did not receive correct message " 169 "arguments."); 170 if (arg != NULL) 171 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg, 172 DBUS_TYPE_INVALID); 173 174 return reply; 175 } 176 177 178 static const char *dont_quote[] = { 179 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", 180 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path", 181 "bssid", NULL 182 }; 183 184 static dbus_bool_t should_quote_opt(const char *key) 185 { 186 int i = 0; 187 while (dont_quote[i] != NULL) { 188 if (os_strcmp(key, dont_quote[i]) == 0) 189 return FALSE; 190 i++; 191 } 192 return TRUE; 193 } 194 195 /** 196 * get_iface_by_dbus_path - Get a new network interface 197 * @global: Pointer to global data from wpa_supplicant_init() 198 * @path: Pointer to a dbus object path representing an interface 199 * Returns: Pointer to the interface or %NULL if not found 200 */ 201 static struct wpa_supplicant * get_iface_by_dbus_path( 202 struct wpa_global *global, const char *path) 203 { 204 struct wpa_supplicant *wpa_s; 205 206 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { 207 if (os_strcmp(wpa_s->dbus_new_path, path) == 0) 208 return wpa_s; 209 } 210 return NULL; 211 } 212 213 214 /** 215 * set_network_properties - Set properties of a configured network 216 * @message: Pointer to incoming dbus message 217 * @wpa_s: wpa_supplicant structure for a network interface 218 * @ssid: wpa_ssid structure for a configured network 219 * @iter: DBus message iterator containing dictionary of network 220 * properties to set. 221 * Returns: NULL when succeed or DBus error on failure 222 * 223 * Sets network configuration with parameters given id DBus dictionary 224 */ 225 static DBusMessage * set_network_properties(DBusMessage *message, 226 struct wpa_supplicant *wpa_s, 227 struct wpa_ssid *ssid, 228 DBusMessageIter *iter) 229 { 230 231 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 232 DBusMessage *reply = NULL; 233 DBusMessageIter iter_dict; 234 235 if (!wpa_dbus_dict_open_read(iter, &iter_dict)) 236 return wpas_dbus_error_invalid_args(message, NULL); 237 238 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 239 char *value = NULL; 240 size_t size = 50; 241 int ret; 242 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 243 reply = wpas_dbus_error_invalid_args(message, NULL); 244 break; 245 } 246 if (entry.type == DBUS_TYPE_ARRAY && 247 entry.array_type == DBUS_TYPE_BYTE) { 248 if (entry.array_len <= 0) 249 goto error; 250 251 size = entry.array_len * 2 + 1; 252 value = os_zalloc(size); 253 if (value == NULL) 254 goto error; 255 256 ret = wpa_snprintf_hex(value, size, 257 (u8 *) entry.bytearray_value, 258 entry.array_len); 259 if (ret <= 0) 260 goto error; 261 } else if (entry.type == DBUS_TYPE_STRING) { 262 if (should_quote_opt(entry.key)) { 263 size = os_strlen(entry.str_value); 264 if (size <= 0) 265 goto error; 266 267 size += 3; 268 value = os_zalloc(size); 269 if (value == NULL) 270 goto error; 271 272 ret = os_snprintf(value, size, "\"%s\"", 273 entry.str_value); 274 if (ret < 0 || (size_t) ret != (size - 1)) 275 goto error; 276 } else { 277 value = os_strdup(entry.str_value); 278 if (value == NULL) 279 goto error; 280 } 281 } else if (entry.type == DBUS_TYPE_UINT32) { 282 value = os_zalloc(size); 283 if (value == NULL) 284 goto error; 285 286 ret = os_snprintf(value, size, "%u", 287 entry.uint32_value); 288 if (ret <= 0) 289 goto error; 290 } else if (entry.type == DBUS_TYPE_INT32) { 291 value = os_zalloc(size); 292 if (value == NULL) 293 goto error; 294 295 ret = os_snprintf(value, size, "%d", 296 entry.int32_value); 297 if (ret <= 0) 298 goto error; 299 } else 300 goto error; 301 302 if (wpa_config_set(ssid, entry.key, value, 0) < 0) 303 goto error; 304 305 if ((os_strcmp(entry.key, "psk") == 0 && 306 value[0] == '"' && ssid->ssid_len) || 307 (strcmp(entry.key, "ssid") == 0 && ssid->passphrase)) 308 wpa_config_update_psk(ssid); 309 else if (os_strcmp(entry.key, "priority") == 0) 310 wpa_config_update_prio_list(wpa_s->conf); 311 312 os_free(value); 313 wpa_dbus_dict_entry_clear(&entry); 314 continue; 315 316 error: 317 os_free(value); 318 reply = wpas_dbus_error_invalid_args(message, entry.key); 319 wpa_dbus_dict_entry_clear(&entry); 320 break; 321 } 322 323 return reply; 324 } 325 326 327 /** 328 * wpas_dbus_simple_property_getter - Get basic type property 329 * @message: Pointer to incoming dbus message 330 * @type: DBus type of property (must be basic type) 331 * @val: pointer to place holding property value 332 * Returns: The DBus message containing response for Properties.Get call 333 * or DBus error message if error occurred. 334 * 335 * Generic getter for basic type properties. Type is required to be basic. 336 */ 337 DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message, 338 const int type, const void *val) 339 { 340 DBusMessage *reply = NULL; 341 DBusMessageIter iter, variant_iter; 342 343 if (!dbus_type_is_basic(type)) { 344 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:" 345 " given type is not basic"); 346 return wpas_dbus_error_unknown_error(message, NULL); 347 } 348 349 if (message == NULL) 350 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); 351 else 352 reply = dbus_message_new_method_return(message); 353 354 if (reply != NULL) { 355 dbus_message_iter_init_append(reply, &iter); 356 if (!dbus_message_iter_open_container( 357 &iter, DBUS_TYPE_VARIANT, 358 wpa_dbus_type_as_string(type), &variant_iter) || 359 !dbus_message_iter_append_basic(&variant_iter, type, 360 val) || 361 !dbus_message_iter_close_container(&iter, &variant_iter)) { 362 wpa_printf(MSG_ERROR, "dbus: " 363 "wpas_dbus_simple_property_getter: out of " 364 "memory to put property value into " 365 "message"); 366 dbus_message_unref(reply); 367 reply = dbus_message_new_error(message, 368 DBUS_ERROR_NO_MEMORY, 369 NULL); 370 } 371 } else { 372 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:" 373 " out of memory to return property value"); 374 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 375 NULL); 376 } 377 378 return reply; 379 } 380 381 382 /** 383 * wpas_dbus_simple_property_setter - Set basic type property 384 * @message: Pointer to incoming dbus message 385 * @type: DBus type of property (must be basic type) 386 * @val: pointer to place where value being set will be stored 387 * Returns: NULL or DBus error message if error occurred. 388 * 389 * Generic setter for basic type properties. Type is required to be basic. 390 */ 391 DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message, 392 const int type, void *val) 393 { 394 DBusMessageIter iter, variant_iter; 395 396 if (!dbus_type_is_basic(type)) { 397 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:" 398 " given type is not basic"); 399 return wpas_dbus_error_unknown_error(message, NULL); 400 } 401 402 if (!dbus_message_iter_init(message, &iter)) { 403 wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:" 404 " out of memory to return scanning state"); 405 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 406 NULL); 407 } 408 409 /* omit first and second argument and get value from third */ 410 dbus_message_iter_next(&iter); 411 dbus_message_iter_next(&iter); 412 dbus_message_iter_recurse(&iter, &variant_iter); 413 414 if (dbus_message_iter_get_arg_type(&variant_iter) != type) { 415 wpa_printf(MSG_DEBUG, "dbus: wpas_dbus_simple_property_setter:" 416 " wrong property type"); 417 return wpas_dbus_error_invalid_args(message, 418 "wrong property type"); 419 } 420 dbus_message_iter_get_basic(&variant_iter, val); 421 422 return NULL; 423 } 424 425 426 /** 427 * wpas_dbus_simple_array_property_getter - Get array type property 428 * @message: Pointer to incoming dbus message 429 * @type: DBus type of property array elements (must be basic type) 430 * @array: pointer to array of elements to put into response message 431 * @array_len: length of above array 432 * Returns: The DBus message containing response for Properties.Get call 433 * or DBus error message if error occurred. 434 * 435 * Generic getter for array type properties. Array elements type is 436 * required to be basic. 437 */ 438 DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message, 439 const int type, 440 const void *array, 441 size_t array_len) 442 { 443 DBusMessage *reply = NULL; 444 DBusMessageIter iter, variant_iter, array_iter; 445 char type_str[] = "a?"; /* ? will be replaced with subtype letter; */ 446 const char *sub_type_str; 447 size_t element_size, i; 448 449 if (!dbus_type_is_basic(type)) { 450 wpa_printf(MSG_ERROR, "dbus: " 451 "wpas_dbus_simple_array_property_getter: given " 452 "type is not basic"); 453 return wpas_dbus_error_unknown_error(message, NULL); 454 } 455 456 sub_type_str = wpa_dbus_type_as_string(type); 457 type_str[1] = sub_type_str[0]; 458 459 if (message == NULL) 460 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); 461 else 462 reply = dbus_message_new_method_return(message); 463 if (reply == NULL) { 464 wpa_printf(MSG_ERROR, "dbus: " 465 "wpas_dbus_simple_array_property_getter: out of " 466 "memory to create return message"); 467 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 468 NULL); 469 } 470 471 dbus_message_iter_init_append(reply, &iter); 472 473 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, 474 type_str, &variant_iter) || 475 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 476 sub_type_str, &array_iter)) { 477 wpa_printf(MSG_ERROR, "dbus: " 478 "wpas_dbus_simple_array_property_getter: out of " 479 "memory to open container"); 480 dbus_message_unref(reply); 481 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 482 NULL); 483 } 484 485 switch(type) { 486 case DBUS_TYPE_BYTE: 487 case DBUS_TYPE_BOOLEAN: 488 element_size = 1; 489 break; 490 case DBUS_TYPE_INT16: 491 case DBUS_TYPE_UINT16: 492 element_size = sizeof(uint16_t); 493 break; 494 case DBUS_TYPE_INT32: 495 case DBUS_TYPE_UINT32: 496 element_size = sizeof(uint32_t); 497 break; 498 case DBUS_TYPE_INT64: 499 case DBUS_TYPE_UINT64: 500 element_size = sizeof(uint64_t); 501 break; 502 case DBUS_TYPE_DOUBLE: 503 element_size = sizeof(double); 504 break; 505 case DBUS_TYPE_STRING: 506 case DBUS_TYPE_OBJECT_PATH: 507 element_size = sizeof(char *); 508 break; 509 default: 510 wpa_printf(MSG_ERROR, "dbus: " 511 "wpas_dbus_simple_array_property_getter: " 512 "fatal: unknown element type"); 513 element_size = 1; 514 break; 515 } 516 517 for (i = 0; i < array_len; i++) { 518 dbus_message_iter_append_basic(&array_iter, type, 519 array + i * element_size); 520 } 521 522 if (!dbus_message_iter_close_container(&variant_iter, &array_iter) || 523 !dbus_message_iter_close_container(&iter, &variant_iter)) { 524 wpa_printf(MSG_ERROR, "dbus: " 525 "wpas_dbus_simple_array_property_getter: out of " 526 "memory to close container"); 527 dbus_message_unref(reply); 528 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 529 NULL); 530 } 531 532 return reply; 533 } 534 535 536 /** 537 * wpas_dbus_handler_create_interface - Request registration of a network iface 538 * @message: Pointer to incoming dbus message 539 * @global: %wpa_supplicant global data structure 540 * Returns: The object path of the new interface object, 541 * or a dbus error message with more information 542 * 543 * Handler function for "CreateInterface" method call. Handles requests 544 * by dbus clients to register a network interface that wpa_supplicant 545 * will manage. 546 */ 547 DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message, 548 struct wpa_global *global) 549 { 550 DBusMessageIter iter_dict; 551 DBusMessage *reply = NULL; 552 DBusMessageIter iter; 553 struct wpa_dbus_dict_entry entry; 554 char *driver = NULL; 555 char *ifname = NULL; 556 char *bridge_ifname = NULL; 557 558 dbus_message_iter_init(message, &iter); 559 560 if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) 561 goto error; 562 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 563 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 564 goto error; 565 if (!strcmp(entry.key, "Driver") && 566 (entry.type == DBUS_TYPE_STRING)) { 567 driver = os_strdup(entry.str_value); 568 wpa_dbus_dict_entry_clear(&entry); 569 if (driver == NULL) 570 goto error; 571 } else if (!strcmp(entry.key, "Ifname") && 572 (entry.type == DBUS_TYPE_STRING)) { 573 ifname = os_strdup(entry.str_value); 574 wpa_dbus_dict_entry_clear(&entry); 575 if (ifname == NULL) 576 goto error; 577 } else if (!strcmp(entry.key, "BridgeIfname") && 578 (entry.type == DBUS_TYPE_STRING)) { 579 bridge_ifname = os_strdup(entry.str_value); 580 wpa_dbus_dict_entry_clear(&entry); 581 if (bridge_ifname == NULL) 582 goto error; 583 } else { 584 wpa_dbus_dict_entry_clear(&entry); 585 goto error; 586 } 587 } 588 589 if (ifname == NULL) 590 goto error; /* Required Ifname argument missing */ 591 592 /* 593 * Try to get the wpa_supplicant record for this iface, return 594 * an error if we already control it. 595 */ 596 if (wpa_supplicant_get_iface(global, ifname) != NULL) { 597 reply = dbus_message_new_error(message, 598 WPAS_DBUS_ERROR_IFACE_EXISTS, 599 "wpa_supplicant already " 600 "controls this interface."); 601 } else { 602 struct wpa_supplicant *wpa_s; 603 struct wpa_interface iface; 604 os_memset(&iface, 0, sizeof(iface)); 605 iface.driver = driver; 606 iface.ifname = ifname; 607 iface.bridge_ifname = bridge_ifname; 608 /* Otherwise, have wpa_supplicant attach to it. */ 609 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) { 610 const char *path = wpa_s->dbus_new_path; 611 reply = dbus_message_new_method_return(message); 612 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 613 &path, DBUS_TYPE_INVALID); 614 } else { 615 reply = wpas_dbus_error_unknown_error( 616 message, "wpa_supplicant couldn't grab this " 617 "interface."); 618 } 619 } 620 621 out: 622 os_free(driver); 623 os_free(ifname); 624 os_free(bridge_ifname); 625 return reply; 626 627 error: 628 reply = wpas_dbus_error_invalid_args(message, NULL); 629 goto out; 630 } 631 632 633 /** 634 * wpas_dbus_handler_remove_interface - Request deregistration of an interface 635 * @message: Pointer to incoming dbus message 636 * @global: wpa_supplicant global data structure 637 * Returns: a dbus message containing a UINT32 indicating success (1) or 638 * failure (0), or returns a dbus error message with more information 639 * 640 * Handler function for "removeInterface" method call. Handles requests 641 * by dbus clients to deregister a network interface that wpa_supplicant 642 * currently manages. 643 */ 644 DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message, 645 struct wpa_global *global) 646 { 647 struct wpa_supplicant *wpa_s; 648 char *path; 649 DBusMessage *reply = NULL; 650 651 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, 652 DBUS_TYPE_INVALID); 653 654 wpa_s = get_iface_by_dbus_path(global, path); 655 if (wpa_s == NULL) 656 reply = wpas_dbus_error_iface_unknown(message); 657 else if (wpa_supplicant_remove_iface(global, wpa_s)) { 658 reply = wpas_dbus_error_unknown_error( 659 message, "wpa_supplicant couldn't remove this " 660 "interface."); 661 } 662 663 return reply; 664 } 665 666 667 /** 668 * wpas_dbus_handler_get_interface - Get the object path for an interface name 669 * @message: Pointer to incoming dbus message 670 * @global: %wpa_supplicant global data structure 671 * Returns: The object path of the interface object, 672 * or a dbus error message with more information 673 * 674 * Handler function for "getInterface" method call. 675 */ 676 DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message, 677 struct wpa_global *global) 678 { 679 DBusMessage *reply = NULL; 680 const char *ifname; 681 const char *path; 682 struct wpa_supplicant *wpa_s; 683 684 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname, 685 DBUS_TYPE_INVALID); 686 687 wpa_s = wpa_supplicant_get_iface(global, ifname); 688 if (wpa_s == NULL) 689 return wpas_dbus_error_iface_unknown(message); 690 691 path = wpa_s->dbus_new_path; 692 reply = dbus_message_new_method_return(message); 693 if (reply == NULL) 694 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 695 NULL); 696 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, 697 DBUS_TYPE_INVALID)) { 698 dbus_message_unref(reply); 699 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 700 NULL); 701 } 702 703 return reply; 704 } 705 706 707 /** 708 * wpas_dbus_getter_debug_level - Get debug level 709 * @message: Pointer to incoming dbus message 710 * @global: %wpa_supplicant global data structure 711 * Returns: DBus message with value of debug level 712 * 713 * Getter for "DebugLevel" property. 714 */ 715 DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message, 716 struct wpa_global *global) 717 { 718 const char *str; 719 int idx = wpa_debug_level; 720 if (idx < 0) 721 idx = 0; 722 if (idx > 4) 723 idx = 4; 724 str = debug_strings[idx]; 725 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, 726 &str); 727 } 728 729 730 /** 731 * wpas_dbus_getter_debug_timestamp - Get debug timestamp 732 * @message: Pointer to incoming dbus message 733 * @global: %wpa_supplicant global data structure 734 * Returns: DBus message with value of debug timestamp 735 * 736 * Getter for "DebugTimestamp" property. 737 */ 738 DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message, 739 struct wpa_global *global) 740 { 741 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, 742 &wpa_debug_timestamp); 743 744 } 745 746 747 /** 748 * wpas_dbus_getter_debug_show_keys - Get debug show keys 749 * @message: Pointer to incoming dbus message 750 * @global: %wpa_supplicant global data structure 751 * Returns: DBus message with value of debug show_keys 752 * 753 * Getter for "DebugShowKeys" property. 754 */ 755 DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message, 756 struct wpa_global *global) 757 { 758 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, 759 &wpa_debug_show_keys); 760 761 } 762 763 /** 764 * wpas_dbus_setter_debug_level - Set debug level 765 * @message: Pointer to incoming dbus message 766 * @global: %wpa_supplicant global data structure 767 * Returns: %NULL or DBus error message 768 * 769 * Setter for "DebugLevel" property. 770 */ 771 DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message, 772 struct wpa_global *global) 773 { 774 DBusMessage *reply; 775 const char *str = NULL; 776 int i, val = -1; 777 778 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING, 779 &str); 780 if (reply) 781 return reply; 782 783 for (i = 0; debug_strings[i]; i++) 784 if (os_strcmp(debug_strings[i], str) == 0) { 785 val = i; 786 break; 787 } 788 789 if (val < 0 || 790 wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp, 791 wpa_debug_show_keys)) { 792 dbus_message_unref(reply); 793 return wpas_dbus_error_invalid_args( 794 message, "Wrong debug level value"); 795 } 796 797 return NULL; 798 } 799 800 801 /** 802 * wpas_dbus_setter_debug_timestamp - Set debug timestamp 803 * @message: Pointer to incoming dbus message 804 * @global: %wpa_supplicant global data structure 805 * Returns: %NULL or DBus error message 806 * 807 * Setter for "DebugTimestamp" property. 808 */ 809 DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message, 810 struct wpa_global *global) 811 { 812 DBusMessage *reply; 813 dbus_bool_t val; 814 815 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, 816 &val); 817 if (reply) 818 return reply; 819 820 wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0, 821 wpa_debug_show_keys); 822 823 return NULL; 824 } 825 826 827 /** 828 * wpas_dbus_setter_debug_show_keys - Set debug show keys 829 * @message: Pointer to incoming dbus message 830 * @global: %wpa_supplicant global data structure 831 * Returns: %NULL or DBus error message 832 * 833 * Setter for "DebugShowKeys" property. 834 */ 835 DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message, 836 struct wpa_global *global) 837 { 838 DBusMessage *reply; 839 dbus_bool_t val; 840 841 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, 842 &val); 843 if (reply) 844 return reply; 845 846 wpa_supplicant_set_debug_params(global, wpa_debug_level, 847 wpa_debug_timestamp, 848 val ? 1 : 0); 849 850 return NULL; 851 } 852 853 854 /** 855 * wpas_dbus_getter_interfaces - Request registered interfaces list 856 * @message: Pointer to incoming dbus message 857 * @global: %wpa_supplicant global data structure 858 * Returns: The object paths array containing registered interfaces 859 * objects paths or DBus error on failure 860 * 861 * Getter for "Interfaces" property. Handles requests 862 * by dbus clients to return list of registered interfaces objects 863 * paths 864 */ 865 DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message, 866 struct wpa_global *global) 867 { 868 DBusMessage *reply = NULL; 869 struct wpa_supplicant *wpa_s; 870 const char **paths; 871 unsigned int i = 0, num = 0; 872 873 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) 874 num++; 875 876 paths = os_zalloc(num * sizeof(char*)); 877 if (!paths) { 878 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 879 NULL); 880 } 881 882 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) 883 paths[i] = wpa_s->dbus_new_path; 884 885 reply = wpas_dbus_simple_array_property_getter(message, 886 DBUS_TYPE_OBJECT_PATH, 887 paths, num); 888 889 os_free(paths); 890 return reply; 891 } 892 893 894 /** 895 * wpas_dbus_getter_eap_methods - Request supported EAP methods list 896 * @message: Pointer to incoming dbus message 897 * @nothing: not used argument. may be NULL or anything else 898 * Returns: The object paths array containing supported EAP methods 899 * represented by strings or DBus error on failure 900 * 901 * Getter for "EapMethods" property. Handles requests 902 * by dbus clients to return list of strings with supported EAP methods 903 */ 904 DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing) 905 { 906 DBusMessage *reply = NULL; 907 char **eap_methods; 908 size_t num_items = 0; 909 910 eap_methods = eap_get_names_as_string_array(&num_items); 911 if (!eap_methods) { 912 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 913 NULL); 914 } 915 916 reply = wpas_dbus_simple_array_property_getter(message, 917 DBUS_TYPE_STRING, 918 eap_methods, num_items); 919 920 while (num_items) 921 os_free(eap_methods[--num_items]); 922 os_free(eap_methods); 923 return reply; 924 } 925 926 927 static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var, 928 char **type, DBusMessage **reply) 929 { 930 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) { 931 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 932 "Type must be a string"); 933 *reply = wpas_dbus_error_invalid_args( 934 message, "Wrong Type value type. String required"); 935 return -1; 936 } 937 dbus_message_iter_get_basic(var, type); 938 return 0; 939 } 940 941 942 static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var, 943 struct wpa_driver_scan_params *params, 944 DBusMessage **reply) 945 { 946 struct wpa_driver_scan_ssid *ssids = params->ssids; 947 size_t ssids_num = 0; 948 u8 *ssid; 949 DBusMessageIter array_iter, sub_array_iter; 950 char *val; 951 int len; 952 953 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) { 954 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids " 955 "must be an array of arrays of bytes"); 956 *reply = wpas_dbus_error_invalid_args( 957 message, "Wrong SSIDs value type. Array of arrays of " 958 "bytes required"); 959 return -1; 960 } 961 962 dbus_message_iter_recurse(var, &array_iter); 963 964 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY || 965 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) 966 { 967 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids " 968 "must be an array of arrays of bytes"); 969 *reply = wpas_dbus_error_invalid_args( 970 message, "Wrong SSIDs value type. Array of arrays of " 971 "bytes required"); 972 return -1; 973 } 974 975 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) 976 { 977 if (ssids_num >= WPAS_MAX_SCAN_SSIDS) { 978 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 979 "Too many ssids specified on scan dbus " 980 "call"); 981 *reply = wpas_dbus_error_invalid_args( 982 message, "Too many ssids specified. Specify " 983 "at most four"); 984 return -1; 985 } 986 987 dbus_message_iter_recurse(&array_iter, &sub_array_iter); 988 989 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len); 990 if (len == 0) { 991 dbus_message_iter_next(&array_iter); 992 continue; 993 } 994 995 ssid = os_malloc(len); 996 if (ssid == NULL) { 997 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 998 "out of memory. Cannot allocate memory for " 999 "SSID"); 1000 *reply = dbus_message_new_error( 1001 message, DBUS_ERROR_NO_MEMORY, NULL); 1002 return -1; 1003 } 1004 os_memcpy(ssid, val, len); 1005 ssids[ssids_num].ssid = ssid; 1006 ssids[ssids_num].ssid_len = len; 1007 1008 dbus_message_iter_next(&array_iter); 1009 ssids_num++; 1010 } 1011 1012 params->num_ssids = ssids_num; 1013 return 0; 1014 } 1015 1016 1017 static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var, 1018 struct wpa_driver_scan_params *params, 1019 DBusMessage **reply) 1020 { 1021 u8 *ies = NULL, *nies; 1022 int ies_len = 0; 1023 DBusMessageIter array_iter, sub_array_iter; 1024 char *val; 1025 int len; 1026 1027 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) { 1028 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must " 1029 "be an array of arrays of bytes"); 1030 *reply = wpas_dbus_error_invalid_args( 1031 message, "Wrong IEs value type. Array of arrays of " 1032 "bytes required"); 1033 return -1; 1034 } 1035 1036 dbus_message_iter_recurse(var, &array_iter); 1037 1038 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY || 1039 dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE) 1040 { 1041 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must " 1042 "be an array of arrays of bytes"); 1043 *reply = wpas_dbus_error_invalid_args( 1044 message, "Wrong IEs value type. Array required"); 1045 return -1; 1046 } 1047 1048 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY) 1049 { 1050 dbus_message_iter_recurse(&array_iter, &sub_array_iter); 1051 1052 dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len); 1053 if (len == 0) { 1054 dbus_message_iter_next(&array_iter); 1055 continue; 1056 } 1057 1058 nies = os_realloc(ies, ies_len + len); 1059 if (nies == NULL) { 1060 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1061 "out of memory. Cannot allocate memory for " 1062 "IE"); 1063 os_free(ies); 1064 *reply = dbus_message_new_error( 1065 message, DBUS_ERROR_NO_MEMORY, NULL); 1066 return -1; 1067 } 1068 ies = nies; 1069 os_memcpy(ies + ies_len, val, len); 1070 ies_len += len; 1071 1072 dbus_message_iter_next(&array_iter); 1073 } 1074 1075 params->extra_ies = ies; 1076 params->extra_ies_len = ies_len; 1077 return 0; 1078 } 1079 1080 1081 static int wpas_dbus_get_scan_channels(DBusMessage *message, 1082 DBusMessageIter *var, 1083 struct wpa_driver_scan_params *params, 1084 DBusMessage **reply) 1085 { 1086 DBusMessageIter array_iter, sub_array_iter; 1087 int *freqs = NULL, *nfreqs; 1088 int freqs_num = 0; 1089 1090 if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) { 1091 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1092 "Channels must be an array of structs"); 1093 *reply = wpas_dbus_error_invalid_args( 1094 message, "Wrong Channels value type. Array of structs " 1095 "required"); 1096 return -1; 1097 } 1098 1099 dbus_message_iter_recurse(var, &array_iter); 1100 1101 if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) { 1102 wpa_printf(MSG_DEBUG, 1103 "wpas_dbus_handler_scan[dbus]: Channels must be an " 1104 "array of structs"); 1105 *reply = wpas_dbus_error_invalid_args( 1106 message, "Wrong Channels value type. Array of structs " 1107 "required"); 1108 return -1; 1109 } 1110 1111 while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT) 1112 { 1113 int freq, width; 1114 1115 dbus_message_iter_recurse(&array_iter, &sub_array_iter); 1116 1117 if (dbus_message_iter_get_arg_type(&sub_array_iter) != 1118 DBUS_TYPE_UINT32) { 1119 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1120 "Channel must by specified by struct of " 1121 "two UINT32s %c", 1122 dbus_message_iter_get_arg_type( 1123 &sub_array_iter)); 1124 *reply = wpas_dbus_error_invalid_args( 1125 message, "Wrong Channel struct. Two UINT32s " 1126 "required"); 1127 os_free(freqs); 1128 return -1; 1129 } 1130 dbus_message_iter_get_basic(&sub_array_iter, &freq); 1131 1132 if (!dbus_message_iter_next(&sub_array_iter) || 1133 dbus_message_iter_get_arg_type(&sub_array_iter) != 1134 DBUS_TYPE_UINT32) { 1135 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1136 "Channel must by specified by struct of " 1137 "two UINT32s"); 1138 *reply = wpas_dbus_error_invalid_args( 1139 message, 1140 "Wrong Channel struct. Two UINT32s required"); 1141 os_free(freqs); 1142 return -1; 1143 } 1144 1145 dbus_message_iter_get_basic(&sub_array_iter, &width); 1146 1147 #define FREQS_ALLOC_CHUNK 32 1148 if (freqs_num % FREQS_ALLOC_CHUNK == 0) { 1149 nfreqs = os_realloc(freqs, sizeof(int) * 1150 (freqs_num + FREQS_ALLOC_CHUNK)); 1151 if (nfreqs == NULL) 1152 os_free(freqs); 1153 freqs = nfreqs; 1154 } 1155 if (freqs == NULL) { 1156 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1157 "out of memory. can't allocate memory for " 1158 "freqs"); 1159 *reply = dbus_message_new_error( 1160 message, DBUS_ERROR_NO_MEMORY, NULL); 1161 return -1; 1162 } 1163 1164 freqs[freqs_num] = freq; 1165 1166 freqs_num++; 1167 dbus_message_iter_next(&array_iter); 1168 } 1169 1170 nfreqs = os_realloc(freqs, 1171 sizeof(int) * (freqs_num + 1)); 1172 if (nfreqs == NULL) 1173 os_free(freqs); 1174 freqs = nfreqs; 1175 if (freqs == NULL) { 1176 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1177 "out of memory. Can't allocate memory for freqs"); 1178 *reply = dbus_message_new_error( 1179 message, DBUS_ERROR_NO_MEMORY, NULL); 1180 return -1; 1181 } 1182 freqs[freqs_num] = 0; 1183 1184 params->freqs = freqs; 1185 return 0; 1186 } 1187 1188 1189 /** 1190 * wpas_dbus_handler_scan - Request a wireless scan on an interface 1191 * @message: Pointer to incoming dbus message 1192 * @wpa_s: wpa_supplicant structure for a network interface 1193 * Returns: NULL indicating success or DBus error message on failure 1194 * 1195 * Handler function for "Scan" method call of a network device. Requests 1196 * that wpa_supplicant perform a wireless scan as soon as possible 1197 * on a particular wireless interface. 1198 */ 1199 DBusMessage * wpas_dbus_handler_scan(DBusMessage *message, 1200 struct wpa_supplicant *wpa_s) 1201 { 1202 DBusMessage *reply = NULL; 1203 DBusMessageIter iter, dict_iter, entry_iter, variant_iter; 1204 char *key = NULL, *type = NULL; 1205 struct wpa_driver_scan_params params; 1206 size_t i; 1207 1208 os_memset(¶ms, 0, sizeof(params)); 1209 1210 dbus_message_iter_init(message, &iter); 1211 1212 dbus_message_iter_recurse(&iter, &dict_iter); 1213 1214 while (dbus_message_iter_get_arg_type(&dict_iter) == 1215 DBUS_TYPE_DICT_ENTRY) { 1216 dbus_message_iter_recurse(&dict_iter, &entry_iter); 1217 dbus_message_iter_get_basic(&entry_iter, &key); 1218 dbus_message_iter_next(&entry_iter); 1219 dbus_message_iter_recurse(&entry_iter, &variant_iter); 1220 1221 if (os_strcmp(key, "Type") == 0) { 1222 if (wpas_dbus_get_scan_type(message, &variant_iter, 1223 &type, &reply) < 0) 1224 goto out; 1225 } else if (os_strcmp(key, "SSIDs") == 0) { 1226 if (wpas_dbus_get_scan_ssids(message, &variant_iter, 1227 ¶ms, &reply) < 0) 1228 goto out; 1229 } else if (os_strcmp(key, "IEs") == 0) { 1230 if (wpas_dbus_get_scan_ies(message, &variant_iter, 1231 ¶ms, &reply) < 0) 1232 goto out; 1233 } else if (os_strcmp(key, "Channels") == 0) { 1234 if (wpas_dbus_get_scan_channels(message, &variant_iter, 1235 ¶ms, &reply) < 0) 1236 goto out; 1237 } else { 1238 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1239 "Unknown argument %s", key); 1240 reply = wpas_dbus_error_invalid_args(message, key); 1241 goto out; 1242 } 1243 1244 dbus_message_iter_next(&dict_iter); 1245 } 1246 1247 if (!type) { 1248 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1249 "Scan type not specified"); 1250 reply = wpas_dbus_error_invalid_args(message, key); 1251 goto out; 1252 } 1253 1254 if (!os_strcmp(type, "passive")) { 1255 if (params.num_ssids || params.extra_ies_len) { 1256 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1257 "SSIDs or IEs specified for passive scan."); 1258 reply = wpas_dbus_error_invalid_args( 1259 message, "You can specify only Channels in " 1260 "passive scan"); 1261 goto out; 1262 } else if (params.freqs && params.freqs[0]) { 1263 /* wildcard ssid */ 1264 params.num_ssids++; 1265 wpa_supplicant_trigger_scan(wpa_s, ¶ms); 1266 } else { 1267 wpa_s->scan_req = 2; 1268 wpa_supplicant_req_scan(wpa_s, 0, 0); 1269 } 1270 } else if (!os_strcmp(type, "active")) { 1271 wpa_supplicant_trigger_scan(wpa_s, ¶ms); 1272 } else { 1273 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: " 1274 "Unknown scan type: %s", type); 1275 reply = wpas_dbus_error_invalid_args(message, 1276 "Wrong scan type"); 1277 goto out; 1278 } 1279 1280 out: 1281 for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++) 1282 os_free((u8 *) params.ssids[i].ssid); 1283 os_free((u8 *) params.extra_ies); 1284 os_free(params.freqs); 1285 return reply; 1286 } 1287 1288 1289 /* 1290 * wpas_dbus_handler_disconnect - Terminate the current connection 1291 * @message: Pointer to incoming dbus message 1292 * @wpa_s: wpa_supplicant structure for a network interface 1293 * Returns: NotConnected DBus error message if already not connected 1294 * or NULL otherwise. 1295 * 1296 * Handler function for "Disconnect" method call of network interface. 1297 */ 1298 DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message, 1299 struct wpa_supplicant *wpa_s) 1300 { 1301 if (wpa_s->current_ssid != NULL) { 1302 wpa_s->disconnected = 1; 1303 wpa_supplicant_deauthenticate(wpa_s, 1304 WLAN_REASON_DEAUTH_LEAVING); 1305 1306 return NULL; 1307 } 1308 1309 return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED, 1310 "This interface is not connected"); 1311 } 1312 1313 1314 /** 1315 * wpas_dbus_new_iface_add_network - Add a new configured network 1316 * @message: Pointer to incoming dbus message 1317 * @wpa_s: wpa_supplicant structure for a network interface 1318 * Returns: A dbus message containing the object path of the new network 1319 * 1320 * Handler function for "AddNetwork" method call of a network interface. 1321 */ 1322 DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message, 1323 struct wpa_supplicant *wpa_s) 1324 { 1325 DBusMessage *reply = NULL; 1326 DBusMessageIter iter; 1327 struct wpa_ssid *ssid = NULL; 1328 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 1329 1330 dbus_message_iter_init(message, &iter); 1331 1332 ssid = wpa_config_add_network(wpa_s->conf); 1333 if (ssid == NULL) { 1334 wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: " 1335 "can't add new interface."); 1336 reply = wpas_dbus_error_unknown_error( 1337 message, 1338 "wpa_supplicant could not add " 1339 "a network on this interface."); 1340 goto err; 1341 } 1342 wpas_notify_network_added(wpa_s, ssid); 1343 ssid->disabled = 1; 1344 wpa_config_set_network_defaults(ssid); 1345 1346 reply = set_network_properties(message, wpa_s, ssid, &iter); 1347 if (reply) { 1348 wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:" 1349 "control interface couldn't set network " 1350 "properties"); 1351 goto err; 1352 } 1353 1354 /* Construct the object path for this network. */ 1355 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 1356 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 1357 wpa_s->dbus_new_path, ssid->id); 1358 1359 reply = dbus_message_new_method_return(message); 1360 if (reply == NULL) { 1361 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1362 NULL); 1363 goto err; 1364 } 1365 if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, 1366 DBUS_TYPE_INVALID)) { 1367 dbus_message_unref(reply); 1368 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1369 NULL); 1370 goto err; 1371 } 1372 1373 return reply; 1374 1375 err: 1376 if (ssid) { 1377 wpas_notify_network_removed(wpa_s, ssid); 1378 wpa_config_remove_network(wpa_s->conf, ssid->id); 1379 } 1380 return reply; 1381 } 1382 1383 1384 /** 1385 * wpas_dbus_handler_remove_network - Remove a configured network 1386 * @message: Pointer to incoming dbus message 1387 * @wpa_s: wpa_supplicant structure for a network interface 1388 * Returns: NULL on success or dbus error on failure 1389 * 1390 * Handler function for "RemoveNetwork" method call of a network interface. 1391 */ 1392 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message, 1393 struct wpa_supplicant *wpa_s) 1394 { 1395 DBusMessage *reply = NULL; 1396 const char *op; 1397 char *iface = NULL, *net_id = NULL; 1398 int id; 1399 struct wpa_ssid *ssid; 1400 1401 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 1402 DBUS_TYPE_INVALID); 1403 1404 /* Extract the network ID and ensure the network */ 1405 /* is actually a child of this interface */ 1406 iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL); 1407 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 1408 reply = wpas_dbus_error_invalid_args(message, op); 1409 goto out; 1410 } 1411 1412 id = strtoul(net_id, NULL, 10); 1413 if (errno == EINVAL) { 1414 reply = wpas_dbus_error_invalid_args(message, op); 1415 goto out; 1416 } 1417 1418 ssid = wpa_config_get_network(wpa_s->conf, id); 1419 if (ssid == NULL) { 1420 reply = wpas_dbus_error_network_unknown(message); 1421 goto out; 1422 } 1423 1424 wpas_notify_network_removed(wpa_s, ssid); 1425 1426 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 1427 wpa_printf(MSG_ERROR, 1428 "wpas_dbus_handler_remove_network[dbus]: " 1429 "error occurred when removing network %d", id); 1430 reply = wpas_dbus_error_unknown_error( 1431 message, "error removing the specified network on " 1432 "this interface."); 1433 goto out; 1434 } 1435 1436 if (ssid == wpa_s->current_ssid) 1437 wpa_supplicant_deauthenticate(wpa_s, 1438 WLAN_REASON_DEAUTH_LEAVING); 1439 1440 out: 1441 os_free(iface); 1442 os_free(net_id); 1443 return reply; 1444 } 1445 1446 1447 /** 1448 * wpas_dbus_handler_select_network - Attempt association with a network 1449 * @message: Pointer to incoming dbus message 1450 * @wpa_s: wpa_supplicant structure for a network interface 1451 * Returns: NULL on success or dbus error on failure 1452 * 1453 * Handler function for "SelectNetwork" method call of network interface. 1454 */ 1455 DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message, 1456 struct wpa_supplicant *wpa_s) 1457 { 1458 DBusMessage *reply = NULL; 1459 const char *op; 1460 char *iface = NULL, *net_id = NULL; 1461 int id; 1462 struct wpa_ssid *ssid; 1463 1464 dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, 1465 DBUS_TYPE_INVALID); 1466 1467 /* Extract the network ID and ensure the network */ 1468 /* is actually a child of this interface */ 1469 iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL); 1470 if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) { 1471 reply = wpas_dbus_error_invalid_args(message, op); 1472 goto out; 1473 } 1474 1475 id = strtoul(net_id, NULL, 10); 1476 if (errno == EINVAL) { 1477 reply = wpas_dbus_error_invalid_args(message, op); 1478 goto out; 1479 } 1480 1481 ssid = wpa_config_get_network(wpa_s->conf, id); 1482 if (ssid == NULL) { 1483 reply = wpas_dbus_error_network_unknown(message); 1484 goto out; 1485 } 1486 1487 /* Finally, associate with the network */ 1488 wpa_supplicant_select_network(wpa_s, ssid); 1489 1490 out: 1491 os_free(iface); 1492 os_free(net_id); 1493 return reply; 1494 } 1495 1496 1497 /** 1498 * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates) 1499 * @message: Pointer to incoming dbus message 1500 * @wpa_s: %wpa_supplicant data structure 1501 * Returns: A dbus message containing an error on failure or NULL on success 1502 * 1503 * Asks wpa_supplicant to internally store a binary blobs. 1504 */ 1505 DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message, 1506 struct wpa_supplicant *wpa_s) 1507 { 1508 DBusMessage *reply = NULL; 1509 DBusMessageIter iter, array_iter; 1510 1511 char *blob_name; 1512 u8 *blob_data; 1513 int blob_len; 1514 struct wpa_config_blob *blob = NULL; 1515 1516 dbus_message_iter_init(message, &iter); 1517 dbus_message_iter_get_basic(&iter, &blob_name); 1518 1519 if (wpa_config_get_blob(wpa_s->conf, blob_name)) { 1520 return dbus_message_new_error(message, 1521 WPAS_DBUS_ERROR_BLOB_EXISTS, 1522 NULL); 1523 } 1524 1525 dbus_message_iter_next(&iter); 1526 dbus_message_iter_recurse(&iter, &array_iter); 1527 1528 dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len); 1529 1530 blob = os_zalloc(sizeof(*blob)); 1531 if (!blob) { 1532 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1533 NULL); 1534 goto err; 1535 } 1536 1537 blob->data = os_malloc(blob_len); 1538 if (!blob->data) { 1539 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1540 NULL); 1541 goto err; 1542 } 1543 os_memcpy(blob->data, blob_data, blob_len); 1544 1545 blob->len = blob_len; 1546 blob->name = os_strdup(blob_name); 1547 if (!blob->name) { 1548 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1549 NULL); 1550 goto err; 1551 } 1552 1553 wpa_config_set_blob(wpa_s->conf, blob); 1554 wpas_notify_blob_added(wpa_s, blob->name); 1555 1556 return reply; 1557 1558 err: 1559 if (blob) { 1560 os_free(blob->name); 1561 os_free(blob->data); 1562 os_free(blob); 1563 } 1564 return reply; 1565 } 1566 1567 1568 /** 1569 * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates) 1570 * @message: Pointer to incoming dbus message 1571 * @wpa_s: %wpa_supplicant data structure 1572 * Returns: A dbus message containing array of bytes (blob) 1573 * 1574 * Gets one wpa_supplicant's binary blobs. 1575 */ 1576 DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message, 1577 struct wpa_supplicant *wpa_s) 1578 { 1579 DBusMessage *reply = NULL; 1580 DBusMessageIter iter, array_iter; 1581 1582 char *blob_name; 1583 const struct wpa_config_blob *blob; 1584 1585 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name, 1586 DBUS_TYPE_INVALID); 1587 1588 blob = wpa_config_get_blob(wpa_s->conf, blob_name); 1589 if (!blob) { 1590 return dbus_message_new_error(message, 1591 WPAS_DBUS_ERROR_BLOB_UNKNOWN, 1592 "Blob id not set"); 1593 } 1594 1595 reply = dbus_message_new_method_return(message); 1596 if (!reply) { 1597 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1598 NULL); 1599 goto out; 1600 } 1601 1602 dbus_message_iter_init_append(reply, &iter); 1603 1604 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 1605 DBUS_TYPE_BYTE_AS_STRING, 1606 &array_iter)) { 1607 dbus_message_unref(reply); 1608 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1609 NULL); 1610 goto out; 1611 } 1612 1613 if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE, 1614 &(blob->data), blob->len)) { 1615 dbus_message_unref(reply); 1616 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1617 NULL); 1618 goto out; 1619 } 1620 1621 if (!dbus_message_iter_close_container(&iter, &array_iter)) { 1622 dbus_message_unref(reply); 1623 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1624 NULL); 1625 goto out; 1626 } 1627 1628 out: 1629 return reply; 1630 } 1631 1632 1633 /** 1634 * wpas_remove_handler_remove_blob - Remove named binary blob 1635 * @message: Pointer to incoming dbus message 1636 * @wpa_s: %wpa_supplicant data structure 1637 * Returns: NULL on success or dbus error 1638 * 1639 * Asks wpa_supplicant to internally remove a binary blobs. 1640 */ 1641 DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message, 1642 struct wpa_supplicant *wpa_s) 1643 { 1644 DBusMessage *reply = NULL; 1645 char *blob_name; 1646 1647 dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name, 1648 DBUS_TYPE_INVALID); 1649 1650 if (wpa_config_remove_blob(wpa_s->conf, blob_name)) { 1651 return dbus_message_new_error(message, 1652 WPAS_DBUS_ERROR_BLOB_UNKNOWN, 1653 "Blob id not set"); 1654 } 1655 wpas_notify_blob_removed(wpa_s, blob_name); 1656 1657 return reply; 1658 1659 } 1660 1661 1662 /** 1663 * wpas_dbus_getter_capabilities - Return interface capabilities 1664 * @message: Pointer to incoming dbus message 1665 * @wpa_s: wpa_supplicant structure for a network interface 1666 * Returns: A dbus message containing a dict of strings 1667 * 1668 * Getter for "Capabilities" property of an interface. 1669 */ 1670 DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message, 1671 struct wpa_supplicant *wpa_s) 1672 { 1673 DBusMessage *reply = NULL; 1674 struct wpa_driver_capa capa; 1675 int res; 1676 DBusMessageIter iter, iter_dict; 1677 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array, 1678 variant_iter; 1679 const char *scans[] = { "active", "passive", "ssid" }; 1680 const char *modes[] = { "infrastructure", "ad-hoc", "ap" }; 1681 int n = sizeof(modes) / sizeof(char *); 1682 1683 if (message == NULL) 1684 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); 1685 else 1686 reply = dbus_message_new_method_return(message); 1687 if (!reply) 1688 goto nomem; 1689 1690 dbus_message_iter_init_append(reply, &iter); 1691 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, 1692 "a{sv}", &variant_iter)) 1693 goto nomem; 1694 1695 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 1696 goto nomem; 1697 1698 res = wpa_drv_get_capa(wpa_s, &capa); 1699 1700 /***** pairwise cipher */ 1701 if (res < 0) { 1702 const char *args[] = {"ccmp", "tkip", "none"}; 1703 if (!wpa_dbus_dict_append_string_array( 1704 &iter_dict, "Pairwise", args, 1705 sizeof(args) / sizeof(char*))) 1706 goto nomem; 1707 } else { 1708 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise", 1709 &iter_dict_entry, 1710 &iter_dict_val, 1711 &iter_array)) 1712 goto nomem; 1713 1714 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 1715 if (!wpa_dbus_dict_string_array_add_element( 1716 &iter_array, "ccmp")) 1717 goto nomem; 1718 } 1719 1720 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 1721 if (!wpa_dbus_dict_string_array_add_element( 1722 &iter_array, "tkip")) 1723 goto nomem; 1724 } 1725 1726 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1727 if (!wpa_dbus_dict_string_array_add_element( 1728 &iter_array, "none")) 1729 goto nomem; 1730 } 1731 1732 if (!wpa_dbus_dict_end_string_array(&iter_dict, 1733 &iter_dict_entry, 1734 &iter_dict_val, 1735 &iter_array)) 1736 goto nomem; 1737 } 1738 1739 /***** group cipher */ 1740 if (res < 0) { 1741 const char *args[] = { 1742 "ccmp", "tkip", "wep104", "wep40" 1743 }; 1744 if (!wpa_dbus_dict_append_string_array( 1745 &iter_dict, "Group", args, 1746 sizeof(args) / sizeof(char*))) 1747 goto nomem; 1748 } else { 1749 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group", 1750 &iter_dict_entry, 1751 &iter_dict_val, 1752 &iter_array)) 1753 goto nomem; 1754 1755 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 1756 if (!wpa_dbus_dict_string_array_add_element( 1757 &iter_array, "ccmp")) 1758 goto nomem; 1759 } 1760 1761 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 1762 if (!wpa_dbus_dict_string_array_add_element( 1763 &iter_array, "tkip")) 1764 goto nomem; 1765 } 1766 1767 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { 1768 if (!wpa_dbus_dict_string_array_add_element( 1769 &iter_array, "wep104")) 1770 goto nomem; 1771 } 1772 1773 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { 1774 if (!wpa_dbus_dict_string_array_add_element( 1775 &iter_array, "wep40")) 1776 goto nomem; 1777 } 1778 1779 if (!wpa_dbus_dict_end_string_array(&iter_dict, 1780 &iter_dict_entry, 1781 &iter_dict_val, 1782 &iter_array)) 1783 goto nomem; 1784 } 1785 1786 /***** key management */ 1787 if (res < 0) { 1788 const char *args[] = { 1789 "wpa-psk", "wpa-eap", "ieee8021x", "wpa-none", 1790 #ifdef CONFIG_WPS 1791 "wps", 1792 #endif /* CONFIG_WPS */ 1793 "none" 1794 }; 1795 if (!wpa_dbus_dict_append_string_array( 1796 &iter_dict, "KeyMgmt", args, 1797 sizeof(args) / sizeof(char*))) 1798 goto nomem; 1799 } else { 1800 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt", 1801 &iter_dict_entry, 1802 &iter_dict_val, 1803 &iter_array)) 1804 goto nomem; 1805 1806 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 1807 "none")) 1808 goto nomem; 1809 1810 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 1811 "ieee8021x")) 1812 goto nomem; 1813 1814 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1815 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 1816 if (!wpa_dbus_dict_string_array_add_element( 1817 &iter_array, "wpa-eap")) 1818 goto nomem; 1819 1820 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) 1821 if (!wpa_dbus_dict_string_array_add_element( 1822 &iter_array, "wpa-ft-eap")) 1823 goto nomem; 1824 1825 /* TODO: Ensure that driver actually supports sha256 encryption. */ 1826 #ifdef CONFIG_IEEE80211W 1827 if (!wpa_dbus_dict_string_array_add_element( 1828 &iter_array, "wpa-eap-sha256")) 1829 goto nomem; 1830 #endif /* CONFIG_IEEE80211W */ 1831 } 1832 1833 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 1834 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1835 if (!wpa_dbus_dict_string_array_add_element( 1836 &iter_array, "wpa-psk")) 1837 goto nomem; 1838 1839 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) 1840 if (!wpa_dbus_dict_string_array_add_element( 1841 &iter_array, "wpa-ft-psk")) 1842 goto nomem; 1843 1844 /* TODO: Ensure that driver actually supports sha256 encryption. */ 1845 #ifdef CONFIG_IEEE80211W 1846 if (!wpa_dbus_dict_string_array_add_element( 1847 &iter_array, "wpa-psk-sha256")) 1848 goto nomem; 1849 #endif /* CONFIG_IEEE80211W */ 1850 } 1851 1852 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 1853 if (!wpa_dbus_dict_string_array_add_element( 1854 &iter_array, "wpa-none")) 1855 goto nomem; 1856 } 1857 1858 1859 #ifdef CONFIG_WPS 1860 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 1861 "wps")) 1862 goto nomem; 1863 #endif /* CONFIG_WPS */ 1864 1865 if (!wpa_dbus_dict_end_string_array(&iter_dict, 1866 &iter_dict_entry, 1867 &iter_dict_val, 1868 &iter_array)) 1869 goto nomem; 1870 } 1871 1872 /***** WPA protocol */ 1873 if (res < 0) { 1874 const char *args[] = { "rsn", "wpa" }; 1875 if (!wpa_dbus_dict_append_string_array( 1876 &iter_dict, "Protocol", args, 1877 sizeof(args) / sizeof(char*))) 1878 goto nomem; 1879 } else { 1880 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol", 1881 &iter_dict_entry, 1882 &iter_dict_val, 1883 &iter_array)) 1884 goto nomem; 1885 1886 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 1887 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 1888 if (!wpa_dbus_dict_string_array_add_element( 1889 &iter_array, "rsn")) 1890 goto nomem; 1891 } 1892 1893 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 1894 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 1895 if (!wpa_dbus_dict_string_array_add_element( 1896 &iter_array, "wpa")) 1897 goto nomem; 1898 } 1899 1900 if (!wpa_dbus_dict_end_string_array(&iter_dict, 1901 &iter_dict_entry, 1902 &iter_dict_val, 1903 &iter_array)) 1904 goto nomem; 1905 } 1906 1907 /***** auth alg */ 1908 if (res < 0) { 1909 const char *args[] = { "open", "shared", "leap" }; 1910 if (!wpa_dbus_dict_append_string_array( 1911 &iter_dict, "AuthAlg", args, 1912 sizeof(args) / sizeof(char*))) 1913 goto nomem; 1914 } else { 1915 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg", 1916 &iter_dict_entry, 1917 &iter_dict_val, 1918 &iter_array)) 1919 goto nomem; 1920 1921 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { 1922 if (!wpa_dbus_dict_string_array_add_element( 1923 &iter_array, "open")) 1924 goto nomem; 1925 } 1926 1927 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { 1928 if (!wpa_dbus_dict_string_array_add_element( 1929 &iter_array, "shared")) 1930 goto nomem; 1931 } 1932 1933 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { 1934 if (!wpa_dbus_dict_string_array_add_element( 1935 &iter_array, "leap")) 1936 goto nomem; 1937 } 1938 1939 if (!wpa_dbus_dict_end_string_array(&iter_dict, 1940 &iter_dict_entry, 1941 &iter_dict_val, 1942 &iter_array)) 1943 goto nomem; 1944 } 1945 1946 /***** Scan */ 1947 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans, 1948 sizeof(scans) / sizeof(char *))) 1949 goto nomem; 1950 1951 /***** Modes */ 1952 if (res < 0 || !(capa.flags & WPA_DRIVER_FLAGS_AP)) 1953 n--; /* exclude ap mode if it is not supported by the driver */ 1954 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Modes", modes, n)) 1955 goto nomem; 1956 1957 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) 1958 goto nomem; 1959 if (!dbus_message_iter_close_container(&iter, &variant_iter)) 1960 goto nomem; 1961 1962 return reply; 1963 1964 nomem: 1965 if (reply) 1966 dbus_message_unref(reply); 1967 1968 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL); 1969 } 1970 1971 1972 /** 1973 * wpas_dbus_getter_state - Get interface state 1974 * @message: Pointer to incoming dbus message 1975 * @wpa_s: wpa_supplicant structure for a network interface 1976 * Returns: A dbus message containing a STRING representing the current 1977 * interface state 1978 * 1979 * Getter for "State" property. 1980 */ 1981 DBusMessage * wpas_dbus_getter_state(DBusMessage *message, 1982 struct wpa_supplicant *wpa_s) 1983 { 1984 DBusMessage *reply = NULL; 1985 const char *str_state; 1986 char *state_ls, *tmp; 1987 1988 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 1989 1990 /* make state string lowercase to fit new DBus API convention 1991 */ 1992 state_ls = tmp = os_strdup(str_state); 1993 if (!tmp) { 1994 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 1995 NULL); 1996 } 1997 while (*tmp) { 1998 *tmp = tolower(*tmp); 1999 tmp++; 2000 } 2001 2002 reply = wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, 2003 &state_ls); 2004 2005 os_free(state_ls); 2006 2007 return reply; 2008 } 2009 2010 2011 /** 2012 * wpas_dbus_new_iface_get_scanning - Get interface scanning state 2013 * @message: Pointer to incoming dbus message 2014 * @wpa_s: wpa_supplicant structure for a network interface 2015 * Returns: A dbus message containing whether the interface is scanning 2016 * 2017 * Getter for "scanning" property. 2018 */ 2019 DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message, 2020 struct wpa_supplicant *wpa_s) 2021 { 2022 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 2023 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, 2024 &scanning); 2025 } 2026 2027 2028 /** 2029 * wpas_dbus_getter_ap_scan - Control roaming mode 2030 * @message: Pointer to incoming dbus message 2031 * @wpa_s: wpa_supplicant structure for a network interface 2032 * Returns: A message containong value of ap_scan variable 2033 * 2034 * Getter function for "ApScan" property. 2035 */ 2036 DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message, 2037 struct wpa_supplicant *wpa_s) 2038 { 2039 dbus_uint32_t ap_scan = wpa_s->conf->ap_scan; 2040 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32, 2041 &ap_scan); 2042 } 2043 2044 2045 /** 2046 * wpas_dbus_setter_ap_scan - Control roaming mode 2047 * @message: Pointer to incoming dbus message 2048 * @wpa_s: wpa_supplicant structure for a network interface 2049 * Returns: NULL 2050 * 2051 * Setter function for "ApScan" property. 2052 */ 2053 DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message, 2054 struct wpa_supplicant *wpa_s) 2055 { 2056 DBusMessage *reply = NULL; 2057 dbus_uint32_t ap_scan; 2058 2059 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32, 2060 &ap_scan); 2061 if (reply) 2062 return reply; 2063 2064 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 2065 return wpas_dbus_error_invalid_args( 2066 message, "ap_scan must equal 0, 1 or 2"); 2067 } 2068 return NULL; 2069 } 2070 2071 2072 /** 2073 * wpas_dbus_getter_ifname - Get interface name 2074 * @message: Pointer to incoming dbus message 2075 * @wpa_s: wpa_supplicant structure for a network interface 2076 * Returns: A dbus message containing a name of network interface 2077 * associated with with wpa_s 2078 * 2079 * Getter for "Ifname" property. 2080 */ 2081 DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message, 2082 struct wpa_supplicant *wpa_s) 2083 { 2084 const char *ifname = wpa_s->ifname; 2085 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, 2086 &ifname); 2087 } 2088 2089 2090 /** 2091 * wpas_dbus_getter_driver - Get interface name 2092 * @message: Pointer to incoming dbus message 2093 * @wpa_s: wpa_supplicant structure for a network interface 2094 * Returns: A dbus message containing a name of network interface 2095 * driver associated with with wpa_s 2096 * 2097 * Getter for "Driver" property. 2098 */ 2099 DBusMessage * wpas_dbus_getter_driver(DBusMessage *message, 2100 struct wpa_supplicant *wpa_s) 2101 { 2102 const char *driver; 2103 2104 if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) { 2105 wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: " 2106 "wpa_s has no driver set"); 2107 return wpas_dbus_error_unknown_error(message, NULL); 2108 } 2109 2110 driver = wpa_s->driver->name; 2111 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, 2112 &driver); 2113 } 2114 2115 2116 /** 2117 * wpas_dbus_getter_current_bss - Get current bss object path 2118 * @message: Pointer to incoming dbus message 2119 * @wpa_s: wpa_supplicant structure for a network interface 2120 * Returns: A dbus message containing a DBus object path to 2121 * current BSS 2122 * 2123 * Getter for "CurrentBSS" property. 2124 */ 2125 DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message, 2126 struct wpa_supplicant *wpa_s) 2127 { 2128 DBusMessage *reply; 2129 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf; 2130 2131 if (wpa_s->current_bss) 2132 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2133 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2134 wpa_s->dbus_new_path, wpa_s->current_bss->id); 2135 else 2136 os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 2137 2138 reply = wpas_dbus_simple_property_getter(message, 2139 DBUS_TYPE_OBJECT_PATH, 2140 &bss_obj_path); 2141 2142 return reply; 2143 } 2144 2145 2146 /** 2147 * wpas_dbus_getter_current_network - Get current network object path 2148 * @message: Pointer to incoming dbus message 2149 * @wpa_s: wpa_supplicant structure for a network interface 2150 * Returns: A dbus message containing a DBus object path to 2151 * current network 2152 * 2153 * Getter for "CurrentNetwork" property. 2154 */ 2155 DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message, 2156 struct wpa_supplicant *wpa_s) 2157 { 2158 DBusMessage *reply; 2159 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf; 2160 2161 if (wpa_s->current_ssid) 2162 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, 2163 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u", 2164 wpa_s->dbus_new_path, wpa_s->current_ssid->id); 2165 else 2166 os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/"); 2167 2168 reply = wpas_dbus_simple_property_getter(message, 2169 DBUS_TYPE_OBJECT_PATH, 2170 &net_obj_path); 2171 2172 return reply; 2173 } 2174 2175 2176 /** 2177 * wpas_dbus_getter_bridge_ifname - Get interface name 2178 * @message: Pointer to incoming dbus message 2179 * @wpa_s: wpa_supplicant structure for a network interface 2180 * Returns: A dbus message containing a name of bridge network 2181 * interface associated with with wpa_s 2182 * 2183 * Getter for "BridgeIfname" property. 2184 */ 2185 DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message, 2186 struct wpa_supplicant *wpa_s) 2187 { 2188 const char *bridge_ifname = NULL; 2189 2190 bridge_ifname = wpa_s->bridge_ifname; 2191 if (bridge_ifname == NULL) { 2192 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: " 2193 "wpa_s has no bridge interface name set"); 2194 return wpas_dbus_error_unknown_error(message, NULL); 2195 } 2196 2197 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, 2198 &bridge_ifname); 2199 } 2200 2201 2202 /** 2203 * wpas_dbus_getter_bsss - Get array of BSSs objects 2204 * @message: Pointer to incoming dbus message 2205 * @wpa_s: wpa_supplicant structure for a network interface 2206 * Returns: a dbus message containing an array of all known BSS objects 2207 * dbus paths 2208 * 2209 * Getter for "BSSs" property. 2210 */ 2211 DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message, 2212 struct wpa_supplicant *wpa_s) 2213 { 2214 DBusMessage *reply = NULL; 2215 struct wpa_bss *bss; 2216 char **paths; 2217 unsigned int i = 0; 2218 2219 paths = os_zalloc(wpa_s->num_bss * sizeof(char *)); 2220 if (!paths) { 2221 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2222 NULL); 2223 } 2224 2225 /* Loop through scan results and append each result's object path */ 2226 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 2227 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 2228 if (paths[i] == NULL) { 2229 reply = dbus_message_new_error(message, 2230 DBUS_ERROR_NO_MEMORY, 2231 NULL); 2232 goto out; 2233 } 2234 /* Construct the object path for this BSS. */ 2235 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 2236 "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", 2237 wpa_s->dbus_new_path, bss->id); 2238 } 2239 2240 reply = wpas_dbus_simple_array_property_getter(message, 2241 DBUS_TYPE_OBJECT_PATH, 2242 paths, wpa_s->num_bss); 2243 2244 out: 2245 while (i) 2246 os_free(paths[--i]); 2247 os_free(paths); 2248 return reply; 2249 } 2250 2251 2252 /** 2253 * wpas_dbus_getter_networks - Get array of networks objects 2254 * @message: Pointer to incoming dbus message 2255 * @wpa_s: wpa_supplicant structure for a network interface 2256 * Returns: a dbus message containing an array of all configured 2257 * networks dbus object paths. 2258 * 2259 * Getter for "Networks" property. 2260 */ 2261 DBusMessage * wpas_dbus_getter_networks(DBusMessage *message, 2262 struct wpa_supplicant *wpa_s) 2263 { 2264 DBusMessage *reply = NULL; 2265 struct wpa_ssid *ssid; 2266 char **paths; 2267 unsigned int i = 0, num = 0; 2268 2269 if (wpa_s->conf == NULL) { 2270 wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: " 2271 "An error occurred getting networks list."); 2272 return wpas_dbus_error_unknown_error(message, NULL); 2273 } 2274 2275 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) 2276 num++; 2277 2278 paths = os_zalloc(num * sizeof(char *)); 2279 if (!paths) { 2280 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2281 NULL); 2282 } 2283 2284 /* Loop through configured networks and append object path of each */ 2285 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { 2286 paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); 2287 if (paths[i] == NULL) { 2288 reply = dbus_message_new_error(message, 2289 DBUS_ERROR_NO_MEMORY, 2290 NULL); 2291 goto out; 2292 } 2293 2294 /* Construct the object path for this network. */ 2295 os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX, 2296 "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d", 2297 wpa_s->dbus_new_path, ssid->id); 2298 } 2299 2300 reply = wpas_dbus_simple_array_property_getter(message, 2301 DBUS_TYPE_OBJECT_PATH, 2302 paths, num); 2303 2304 out: 2305 while (i) 2306 os_free(paths[--i]); 2307 os_free(paths); 2308 return reply; 2309 } 2310 2311 2312 /** 2313 * wpas_dbus_getter_blobs - Get all blobs defined for this interface 2314 * @message: Pointer to incoming dbus message 2315 * @wpa_s: wpa_supplicant structure for a network interface 2316 * Returns: a dbus message containing a dictionary of pairs (blob_name, blob) 2317 * 2318 * Getter for "Blobs" property. 2319 */ 2320 DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message, 2321 struct wpa_supplicant *wpa_s) 2322 { 2323 DBusMessage *reply = NULL; 2324 DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter; 2325 struct wpa_config_blob *blob; 2326 2327 if (message == NULL) 2328 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); 2329 else 2330 reply = dbus_message_new_method_return(message); 2331 if (!reply) 2332 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2333 NULL); 2334 2335 dbus_message_iter_init_append(reply, &iter); 2336 2337 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, 2338 "a{say}", &variant_iter) || 2339 !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY, 2340 "{say}", &dict_iter)) { 2341 dbus_message_unref(reply); 2342 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2343 NULL); 2344 } 2345 2346 blob = wpa_s->conf->blobs; 2347 while (blob) { 2348 if (!dbus_message_iter_open_container(&dict_iter, 2349 DBUS_TYPE_DICT_ENTRY, 2350 NULL, &entry_iter) || 2351 !dbus_message_iter_append_basic(&entry_iter, 2352 DBUS_TYPE_STRING, 2353 &(blob->name)) || 2354 !dbus_message_iter_open_container(&entry_iter, 2355 DBUS_TYPE_ARRAY, 2356 DBUS_TYPE_BYTE_AS_STRING, 2357 &array_iter) || 2358 !dbus_message_iter_append_fixed_array(&array_iter, 2359 DBUS_TYPE_BYTE, 2360 &(blob->data), 2361 blob->len) || 2362 !dbus_message_iter_close_container(&entry_iter, 2363 &array_iter) || 2364 !dbus_message_iter_close_container(&dict_iter, 2365 &entry_iter)) { 2366 dbus_message_unref(reply); 2367 return dbus_message_new_error(message, 2368 DBUS_ERROR_NO_MEMORY, 2369 NULL); 2370 } 2371 2372 blob = blob->next; 2373 } 2374 2375 if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) || 2376 !dbus_message_iter_close_container(&iter, &variant_iter)) { 2377 dbus_message_unref(reply); 2378 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2379 NULL); 2380 } 2381 2382 return reply; 2383 } 2384 2385 2386 /** 2387 * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS 2388 * @message: Pointer to incoming dbus message 2389 * @bss: a pair of interface describing structure and bss's id 2390 * Returns: a dbus message containing the bssid for the requested bss 2391 * 2392 * Getter for "BSSID" property. 2393 */ 2394 DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message, 2395 struct bss_handler_args *bss) 2396 { 2397 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2398 2399 if (!res) { 2400 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_bssid[dbus]: no " 2401 "bss with id %d found", bss->id); 2402 return NULL; 2403 } 2404 2405 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE, 2406 res->bssid, ETH_ALEN); 2407 } 2408 2409 2410 /** 2411 * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS 2412 * @message: Pointer to incoming dbus message 2413 * @bss: a pair of interface describing structure and bss's id 2414 * Returns: a dbus message containing the ssid for the requested bss 2415 * 2416 * Getter for "SSID" property. 2417 */ 2418 DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message, 2419 struct bss_handler_args *bss) 2420 { 2421 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2422 2423 if (!res) { 2424 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ssid[dbus]: no " 2425 "bss with id %d found", bss->id); 2426 return NULL; 2427 } 2428 2429 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE, 2430 res->ssid, 2431 res->ssid_len); 2432 } 2433 2434 2435 /** 2436 * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS 2437 * @message: Pointer to incoming dbus message 2438 * @bss: a pair of interface describing structure and bss's id 2439 * Returns: a dbus message containing the privacy flag value of requested bss 2440 * 2441 * Getter for "Privacy" property. 2442 */ 2443 DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message, 2444 struct bss_handler_args *bss) 2445 { 2446 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2447 dbus_bool_t privacy; 2448 2449 if (!res) { 2450 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_privacy[dbus]: no " 2451 "bss with id %d found", bss->id); 2452 return NULL; 2453 } 2454 2455 privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE; 2456 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, 2457 &privacy); 2458 } 2459 2460 2461 /** 2462 * wpas_dbus_getter_bss_mode - Return the mode of a BSS 2463 * @message: Pointer to incoming dbus message 2464 * @bss: a pair of interface describing structure and bss's id 2465 * Returns: a dbus message containing the mode of requested bss 2466 * 2467 * Getter for "Mode" property. 2468 */ 2469 DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message, 2470 struct bss_handler_args *bss) 2471 { 2472 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2473 const char *mode; 2474 2475 if (!res) { 2476 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_mode[dbus]: no " 2477 "bss with id %d found", bss->id); 2478 return NULL; 2479 } 2480 2481 if (res->caps & IEEE80211_CAP_IBSS) 2482 mode = "ad-hoc"; 2483 else 2484 mode = "infrastructure"; 2485 2486 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING, 2487 &mode); 2488 } 2489 2490 2491 /** 2492 * wpas_dbus_getter_bss_level - Return the signal strength of a BSS 2493 * @message: Pointer to incoming dbus message 2494 * @bss: a pair of interface describing structure and bss's id 2495 * Returns: a dbus message containing the signal strength of requested bss 2496 * 2497 * Getter for "Level" property. 2498 */ 2499 DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message, 2500 struct bss_handler_args *bss) 2501 { 2502 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2503 2504 if (!res) { 2505 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_signal[dbus]: no " 2506 "bss with id %d found", bss->id); 2507 return NULL; 2508 } 2509 2510 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_INT16, 2511 &res->level); 2512 } 2513 2514 2515 /** 2516 * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS 2517 * @message: Pointer to incoming dbus message 2518 * @bss: a pair of interface describing structure and bss's id 2519 * Returns: a dbus message containing the frequency of requested bss 2520 * 2521 * Getter for "Frequency" property. 2522 */ 2523 DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message, 2524 struct bss_handler_args *bss) 2525 { 2526 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2527 2528 if (!res) { 2529 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_frequency[dbus]: " 2530 "no bss with id %d found", bss->id); 2531 return NULL; 2532 } 2533 2534 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT16, 2535 &res->freq); 2536 } 2537 2538 2539 static int cmp_u8s_desc(const void *a, const void *b) 2540 { 2541 return (*(u8 *) b - *(u8 *) a); 2542 } 2543 2544 2545 /** 2546 * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS 2547 * @message: Pointer to incoming dbus message 2548 * @bss: a pair of interface describing structure and bss's id 2549 * Returns: a dbus message containing sorted array of bit rates 2550 * 2551 * Getter for "Rates" property. 2552 */ 2553 DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message, 2554 struct bss_handler_args *bss) 2555 { 2556 DBusMessage *reply; 2557 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2558 u8 *ie_rates = NULL; 2559 u32 *real_rates; 2560 int rates_num, i; 2561 2562 if (!res) { 2563 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rates[dbus]: " 2564 "no bss with id %d found", bss->id); 2565 return NULL; 2566 } 2567 2568 rates_num = wpa_bss_get_bit_rates(res, &ie_rates); 2569 if (rates_num < 0) 2570 return NULL; 2571 2572 qsort(ie_rates, rates_num, 1, cmp_u8s_desc); 2573 2574 real_rates = os_malloc(sizeof(u32) * rates_num); 2575 if (!real_rates) { 2576 os_free(ie_rates); 2577 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2578 NULL); 2579 } 2580 2581 for (i = 0; i < rates_num; i++) 2582 real_rates[i] = ie_rates[i] * 500000; 2583 2584 reply = wpas_dbus_simple_array_property_getter(message, 2585 DBUS_TYPE_UINT32, 2586 real_rates, rates_num); 2587 2588 os_free(ie_rates); 2589 os_free(real_rates); 2590 return reply; 2591 } 2592 2593 2594 static DBusMessage * wpas_dbus_get_bss_security_prop( 2595 DBusMessage *message, struct wpa_ie_data *ie_data) 2596 { 2597 DBusMessage *reply; 2598 DBusMessageIter iter, iter_dict, variant_iter; 2599 const char *group; 2600 const char *pairwise[2]; /* max 2 pairwise ciphers is supported */ 2601 const char *key_mgmt[7]; /* max 7 key managements may be supported */ 2602 int n; 2603 2604 if (message == NULL) 2605 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); 2606 else 2607 reply = dbus_message_new_method_return(message); 2608 if (!reply) 2609 goto nomem; 2610 2611 dbus_message_iter_init_append(reply, &iter); 2612 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, 2613 "a{sv}", &variant_iter)) 2614 goto nomem; 2615 2616 if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict)) 2617 goto nomem; 2618 2619 /* KeyMgmt */ 2620 n = 0; 2621 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK) 2622 key_mgmt[n++] = "wpa-psk"; 2623 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK) 2624 key_mgmt[n++] = "wpa-ft-psk"; 2625 if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) 2626 key_mgmt[n++] = "wpa-psk-sha256"; 2627 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X) 2628 key_mgmt[n++] = "wpa-eap"; 2629 if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) 2630 key_mgmt[n++] = "wpa-ft-eap"; 2631 if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) 2632 key_mgmt[n++] = "wpa-eap-sha256"; 2633 if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE) 2634 key_mgmt[n++] = "wpa-none"; 2635 2636 if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt", 2637 key_mgmt, n)) 2638 goto nomem; 2639 2640 /* Group */ 2641 switch (ie_data->group_cipher) { 2642 case WPA_CIPHER_WEP40: 2643 group = "wep40"; 2644 break; 2645 case WPA_CIPHER_TKIP: 2646 group = "tkip"; 2647 break; 2648 case WPA_CIPHER_CCMP: 2649 group = "ccmp"; 2650 break; 2651 case WPA_CIPHER_WEP104: 2652 group = "wep104"; 2653 break; 2654 default: 2655 group = ""; 2656 break; 2657 } 2658 2659 if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group)) 2660 goto nomem; 2661 2662 /* Pairwise */ 2663 n = 0; 2664 if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP) 2665 pairwise[n++] = "tkip"; 2666 if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP) 2667 pairwise[n++] = "ccmp"; 2668 2669 if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise", 2670 pairwise, n)) 2671 goto nomem; 2672 2673 /* Management group (RSN only) */ 2674 if (ie_data->proto == WPA_PROTO_RSN) { 2675 switch (ie_data->mgmt_group_cipher) { 2676 #ifdef CONFIG_IEEE80211W 2677 case WPA_CIPHER_AES_128_CMAC: 2678 group = "aes128cmac"; 2679 break; 2680 #endif /* CONFIG_IEEE80211W */ 2681 default: 2682 group = ""; 2683 break; 2684 } 2685 2686 if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup", 2687 group)) 2688 goto nomem; 2689 } 2690 2691 if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict)) 2692 goto nomem; 2693 if (!dbus_message_iter_close_container(&iter, &variant_iter)) 2694 goto nomem; 2695 2696 return reply; 2697 2698 nomem: 2699 if (reply) 2700 dbus_message_unref(reply); 2701 2702 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL); 2703 } 2704 2705 2706 /** 2707 * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS 2708 * @message: Pointer to incoming dbus message 2709 * @bss: a pair of interface describing structure and bss's id 2710 * Returns: a dbus message containing the WPA options of requested bss 2711 * 2712 * Getter for "WPA" property. 2713 */ 2714 DBusMessage * wpas_dbus_getter_bss_wpa(DBusMessage *message, 2715 struct bss_handler_args *bss) 2716 { 2717 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2718 struct wpa_ie_data wpa_data; 2719 const u8 *ie; 2720 2721 if (!res) { 2722 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_wpa[dbus]: no " 2723 "bss with id %d found", bss->id); 2724 return NULL; 2725 } 2726 2727 os_memset(&wpa_data, 0, sizeof(wpa_data)); 2728 ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE); 2729 if (ie) { 2730 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) 2731 return wpas_dbus_error_unknown_error(message, 2732 "invalid WPA IE"); 2733 } 2734 2735 return wpas_dbus_get_bss_security_prop(message, &wpa_data); 2736 } 2737 2738 2739 /** 2740 * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS 2741 * @message: Pointer to incoming dbus message 2742 * @bss: a pair of interface describing structure and bss's id 2743 * Returns: a dbus message containing the RSN options of requested bss 2744 * 2745 * Getter for "RSN" property. 2746 */ 2747 DBusMessage * wpas_dbus_getter_bss_rsn(DBusMessage *message, 2748 struct bss_handler_args *bss) 2749 { 2750 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2751 struct wpa_ie_data wpa_data; 2752 const u8 *ie; 2753 2754 if (!res) { 2755 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rsn[dbus]: no " 2756 "bss with id %d found", bss->id); 2757 return NULL; 2758 } 2759 2760 os_memset(&wpa_data, 0, sizeof(wpa_data)); 2761 ie = wpa_bss_get_ie(res, WLAN_EID_RSN); 2762 if (ie) { 2763 if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0) 2764 return wpas_dbus_error_unknown_error(message, 2765 "invalid RSN IE"); 2766 } 2767 2768 return wpas_dbus_get_bss_security_prop(message, &wpa_data); 2769 } 2770 2771 2772 /** 2773 * wpas_dbus_getter_bss_ies - Return all IEs of a BSS 2774 * @message: Pointer to incoming dbus message 2775 * @bss: a pair of interface describing structure and bss's id 2776 * Returns: a dbus message containing IEs byte array 2777 * 2778 * Getter for "IEs" property. 2779 */ 2780 DBusMessage * wpas_dbus_getter_bss_ies(DBusMessage *message, 2781 struct bss_handler_args *bss) 2782 { 2783 struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id); 2784 2785 if (!res) { 2786 wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ies[dbus]: no " 2787 "bss with id %d found", bss->id); 2788 return NULL; 2789 } 2790 2791 return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE, 2792 res + 1, res->ie_len); 2793 } 2794 2795 2796 /** 2797 * wpas_dbus_getter_enabled - Check whether network is enabled or disabled 2798 * @message: Pointer to incoming dbus message 2799 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface 2800 * and wpa_ssid structure for a configured network 2801 * Returns: DBus message with boolean indicating state of configured network 2802 * or DBus error on failure 2803 * 2804 * Getter for "enabled" property of a configured network. 2805 */ 2806 DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message, 2807 struct network_handler_args *net) 2808 { 2809 dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE; 2810 return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN, 2811 &enabled); 2812 } 2813 2814 2815 /** 2816 * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled 2817 * @message: Pointer to incoming dbus message 2818 * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface 2819 * and wpa_ssid structure for a configured network 2820 * Returns: NULL indicating success or DBus error on failure 2821 * 2822 * Setter for "Enabled" property of a configured network. 2823 */ 2824 DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message, 2825 struct network_handler_args *net) 2826 { 2827 DBusMessage *reply = NULL; 2828 2829 struct wpa_supplicant *wpa_s; 2830 struct wpa_ssid *ssid; 2831 2832 dbus_bool_t enable; 2833 2834 reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN, 2835 &enable); 2836 2837 if (reply) 2838 return reply; 2839 2840 wpa_s = net->wpa_s; 2841 ssid = net->ssid; 2842 2843 if (enable) 2844 wpa_supplicant_enable_network(wpa_s, ssid); 2845 else 2846 wpa_supplicant_disable_network(wpa_s, ssid); 2847 2848 return NULL; 2849 } 2850 2851 2852 /** 2853 * wpas_dbus_getter_network_properties - Get options for a configured network 2854 * @message: Pointer to incoming dbus message 2855 * @net: wpa_supplicant structure for a network interface and 2856 * wpa_ssid structure for a configured network 2857 * Returns: DBus message with network properties or DBus error on failure 2858 * 2859 * Getter for "Properties" property of a configured network. 2860 */ 2861 DBusMessage * wpas_dbus_getter_network_properties( 2862 DBusMessage *message, struct network_handler_args *net) 2863 { 2864 DBusMessage *reply = NULL; 2865 DBusMessageIter iter, variant_iter, dict_iter; 2866 char **iterator; 2867 char **props = wpa_config_get_all(net->ssid, 0); 2868 if (!props) 2869 return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2870 NULL); 2871 2872 if (message == NULL) 2873 reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); 2874 else 2875 reply = dbus_message_new_method_return(message); 2876 if (!reply) { 2877 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2878 NULL); 2879 goto out; 2880 } 2881 2882 dbus_message_iter_init_append(reply, &iter); 2883 2884 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, 2885 "a{sv}", &variant_iter) || 2886 !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) { 2887 dbus_message_unref(reply); 2888 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2889 NULL); 2890 goto out; 2891 } 2892 2893 iterator = props; 2894 while (*iterator) { 2895 if (!wpa_dbus_dict_append_string(&dict_iter, *iterator, 2896 *(iterator + 1))) { 2897 dbus_message_unref(reply); 2898 reply = dbus_message_new_error(message, 2899 DBUS_ERROR_NO_MEMORY, 2900 NULL); 2901 goto out; 2902 } 2903 iterator += 2; 2904 } 2905 2906 2907 if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) || 2908 !dbus_message_iter_close_container(&iter, &variant_iter)) { 2909 dbus_message_unref(reply); 2910 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 2911 NULL); 2912 goto out; 2913 } 2914 2915 out: 2916 iterator = props; 2917 while (*iterator) { 2918 os_free(*iterator); 2919 iterator++; 2920 } 2921 os_free(props); 2922 return reply; 2923 } 2924 2925 2926 /** 2927 * wpas_dbus_setter_network_properties - Set options for a configured network 2928 * @message: Pointer to incoming dbus message 2929 * @net: wpa_supplicant structure for a network interface and 2930 * wpa_ssid structure for a configured network 2931 * Returns: NULL indicating success or DBus error on failure 2932 * 2933 * Setter for "Properties" property of a configured network. 2934 */ 2935 DBusMessage * wpas_dbus_setter_network_properties( 2936 DBusMessage *message, struct network_handler_args *net) 2937 { 2938 struct wpa_ssid *ssid = net->ssid; 2939 2940 DBusMessage *reply = NULL; 2941 DBusMessageIter iter, variant_iter; 2942 2943 dbus_message_iter_init(message, &iter); 2944 2945 dbus_message_iter_next(&iter); 2946 dbus_message_iter_next(&iter); 2947 2948 dbus_message_iter_recurse(&iter, &variant_iter); 2949 2950 reply = set_network_properties(message, net->wpa_s, ssid, 2951 &variant_iter); 2952 if (reply) 2953 wpa_printf(MSG_DEBUG, "dbus control interface couldn't set " 2954 "network properties"); 2955 2956 return reply; 2957 } 2958