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