dbus_old_handlers.c revision fb79edc9df1f20461e90e478363d207348213d35
1/* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9#include "includes.h" 10#include <dbus/dbus.h> 11 12#include "common.h" 13#include "eap_peer/eap_methods.h" 14#include "common/ieee802_11_defs.h" 15#include "eapol_supp/eapol_supp_sm.h" 16#include "rsn_supp/wpa.h" 17#include "../config.h" 18#include "../wpa_supplicant_i.h" 19#include "../driver_i.h" 20#include "../notify.h" 21#include "../wpas_glue.h" 22#include "../bss.h" 23#include "../scan.h" 24#include "dbus_old.h" 25#include "dbus_old_handlers.h" 26#include "dbus_dict_helpers.h" 27 28/** 29 * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message 30 * @message: Pointer to incoming dbus message this error refers to 31 * Returns: a dbus error message 32 * 33 * Convenience function to create and return an invalid options error 34 */ 35DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message, 36 const char *arg) 37{ 38 DBusMessage *reply; 39 40 reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS, 41 "Did not receive correct message " 42 "arguments."); 43 if (arg != NULL) 44 dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg, 45 DBUS_TYPE_INVALID); 46 47 return reply; 48} 49 50 51/** 52 * wpas_dbus_new_success_reply - Return a new success reply message 53 * @message: Pointer to incoming dbus message this reply refers to 54 * Returns: a dbus message containing a single UINT32 that indicates 55 * success (ie, a value of 1) 56 * 57 * Convenience function to create and return a success reply message 58 */ 59DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message) 60{ 61 DBusMessage *reply; 62 unsigned int success = 1; 63 64 reply = dbus_message_new_method_return(message); 65 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success, 66 DBUS_TYPE_INVALID); 67 return reply; 68} 69 70 71/** 72 * wpas_dbus_global_add_interface - Request registration of a network interface 73 * @message: Pointer to incoming dbus message 74 * @global: %wpa_supplicant global data structure 75 * Returns: The object path of the new interface object, 76 * or a dbus error message with more information 77 * 78 * Handler function for "addInterface" method call. Handles requests 79 * by dbus clients to register a network interface that wpa_supplicant 80 * will manage. 81 */ 82DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message, 83 struct wpa_global *global) 84{ 85 char *ifname = NULL; 86 char *driver = NULL; 87 char *driver_param = NULL; 88 char *confname = NULL; 89 char *bridge_ifname = NULL; 90 DBusMessage *reply = NULL; 91 DBusMessageIter iter; 92 93 dbus_message_iter_init(message, &iter); 94 95 /* First argument: interface name (DBUS_TYPE_STRING) 96 * Required; must be non-zero length 97 */ 98 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 99 goto error; 100 dbus_message_iter_get_basic(&iter, &ifname); 101 if (!os_strlen(ifname)) 102 goto error; 103 104 /* Second argument: dict of options */ 105 if (dbus_message_iter_next(&iter)) { 106 DBusMessageIter iter_dict; 107 struct wpa_dbus_dict_entry entry; 108 109 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 110 goto error; 111 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 112 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 113 goto error; 114 if (!strcmp(entry.key, "driver") && 115 (entry.type == DBUS_TYPE_STRING)) { 116 driver = os_strdup(entry.str_value); 117 wpa_dbus_dict_entry_clear(&entry); 118 if (driver == NULL) 119 goto error; 120 } else if (!strcmp(entry.key, "driver-params") && 121 (entry.type == DBUS_TYPE_STRING)) { 122 driver_param = os_strdup(entry.str_value); 123 wpa_dbus_dict_entry_clear(&entry); 124 if (driver_param == NULL) 125 goto error; 126 } else if (!strcmp(entry.key, "config-file") && 127 (entry.type == DBUS_TYPE_STRING)) { 128 confname = os_strdup(entry.str_value); 129 wpa_dbus_dict_entry_clear(&entry); 130 if (confname == NULL) 131 goto error; 132 } else if (!strcmp(entry.key, "bridge-ifname") && 133 (entry.type == DBUS_TYPE_STRING)) { 134 bridge_ifname = os_strdup(entry.str_value); 135 wpa_dbus_dict_entry_clear(&entry); 136 if (bridge_ifname == NULL) 137 goto error; 138 } else { 139 wpa_dbus_dict_entry_clear(&entry); 140 goto error; 141 } 142 } 143 } 144 145 /* 146 * Try to get the wpa_supplicant record for this iface, return 147 * an error if we already control it. 148 */ 149 if (wpa_supplicant_get_iface(global, ifname) != NULL) { 150 reply = dbus_message_new_error(message, 151 WPAS_ERROR_EXISTS_ERROR, 152 "wpa_supplicant already " 153 "controls this interface."); 154 } else { 155 struct wpa_supplicant *wpa_s; 156 struct wpa_interface iface; 157 os_memset(&iface, 0, sizeof(iface)); 158 iface.ifname = ifname; 159 iface.driver = driver; 160 iface.driver_param = driver_param; 161 iface.confname = confname; 162 iface.bridge_ifname = bridge_ifname; 163 /* Otherwise, have wpa_supplicant attach to it. */ 164 if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) { 165 const char *path = wpa_s->dbus_path; 166 reply = dbus_message_new_method_return(message); 167 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 168 &path, DBUS_TYPE_INVALID); 169 } else { 170 reply = dbus_message_new_error(message, 171 WPAS_ERROR_ADD_ERROR, 172 "wpa_supplicant " 173 "couldn't grab this " 174 "interface."); 175 } 176 } 177 178out: 179 os_free(driver); 180 os_free(driver_param); 181 os_free(confname); 182 os_free(bridge_ifname); 183 return reply; 184 185error: 186 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 187 goto out; 188} 189 190 191/** 192 * wpas_dbus_global_remove_interface - Request deregistration of an interface 193 * @message: Pointer to incoming dbus message 194 * @global: wpa_supplicant global data structure 195 * Returns: a dbus message containing a UINT32 indicating success (1) or 196 * failure (0), or returns a dbus error message with more information 197 * 198 * Handler function for "removeInterface" method call. Handles requests 199 * by dbus clients to deregister a network interface that wpa_supplicant 200 * currently manages. 201 */ 202DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message, 203 struct wpa_global *global) 204{ 205 struct wpa_supplicant *wpa_s; 206 char *path; 207 DBusMessage *reply = NULL; 208 209 if (!dbus_message_get_args(message, NULL, 210 DBUS_TYPE_OBJECT_PATH, &path, 211 DBUS_TYPE_INVALID)) { 212 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 213 goto out; 214 } 215 216 wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path); 217 if (wpa_s == NULL) { 218 reply = wpas_dbus_new_invalid_iface_error(message); 219 goto out; 220 } 221 222 if (!wpa_supplicant_remove_iface(global, wpa_s, 0)) { 223 reply = wpas_dbus_new_success_reply(message); 224 } else { 225 reply = dbus_message_new_error(message, 226 WPAS_ERROR_REMOVE_ERROR, 227 "wpa_supplicant couldn't " 228 "remove this interface."); 229 } 230 231out: 232 return reply; 233} 234 235 236/** 237 * wpas_dbus_global_get_interface - Get the object path for an interface name 238 * @message: Pointer to incoming dbus message 239 * @global: %wpa_supplicant global data structure 240 * Returns: The object path of the interface object, 241 * or a dbus error message with more information 242 * 243 * Handler function for "getInterface" method call. Handles requests 244 * by dbus clients for the object path of an specific network interface. 245 */ 246DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message, 247 struct wpa_global *global) 248{ 249 DBusMessage *reply = NULL; 250 const char *ifname; 251 const char *path; 252 struct wpa_supplicant *wpa_s; 253 254 if (!dbus_message_get_args(message, NULL, 255 DBUS_TYPE_STRING, &ifname, 256 DBUS_TYPE_INVALID)) { 257 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 258 goto out; 259 } 260 261 wpa_s = wpa_supplicant_get_iface(global, ifname); 262 if (wpa_s == NULL) { 263 reply = wpas_dbus_new_invalid_iface_error(message); 264 goto out; 265 } 266 267 path = wpa_s->dbus_path; 268 reply = dbus_message_new_method_return(message); 269 dbus_message_append_args(reply, 270 DBUS_TYPE_OBJECT_PATH, &path, 271 DBUS_TYPE_INVALID); 272 273out: 274 return reply; 275} 276 277 278/** 279 * wpas_dbus_global_set_debugparams- Set the debug params 280 * @message: Pointer to incoming dbus message 281 * @global: %wpa_supplicant global data structure 282 * Returns: a dbus message containing a UINT32 indicating success (1) or 283 * failure (0), or returns a dbus error message with more information 284 * 285 * Handler function for "setDebugParams" method call. Handles requests 286 * by dbus clients for the object path of an specific network interface. 287 */ 288DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message, 289 struct wpa_global *global) 290{ 291 DBusMessage *reply = NULL; 292 int debug_level; 293 dbus_bool_t debug_timestamp; 294 dbus_bool_t debug_show_keys; 295 296 if (!dbus_message_get_args(message, NULL, 297 DBUS_TYPE_INT32, &debug_level, 298 DBUS_TYPE_BOOLEAN, &debug_timestamp, 299 DBUS_TYPE_BOOLEAN, &debug_show_keys, 300 DBUS_TYPE_INVALID)) { 301 return wpas_dbus_new_invalid_opts_error(message, NULL); 302 } 303 304 if (wpa_supplicant_set_debug_params(global, debug_level, 305 debug_timestamp ? 1 : 0, 306 debug_show_keys ? 1 : 0)) { 307 return wpas_dbus_new_invalid_opts_error(message, NULL); 308 } 309 310 reply = wpas_dbus_new_success_reply(message); 311 312 return reply; 313} 314 315 316/** 317 * wpas_dbus_iface_scan - Request a wireless scan on an interface 318 * @message: Pointer to incoming dbus message 319 * @wpa_s: wpa_supplicant structure for a network interface 320 * Returns: a dbus message containing a UINT32 indicating success (1) or 321 * failure (0) 322 * 323 * Handler function for "scan" method call of a network device. Requests 324 * that wpa_supplicant perform a wireless scan as soon as possible 325 * on a particular wireless interface. 326 */ 327DBusMessage * wpas_dbus_iface_scan(DBusMessage *message, 328 struct wpa_supplicant *wpa_s) 329{ 330 wpa_s->scan_req = MANUAL_SCAN_REQ; 331 wpa_supplicant_req_scan(wpa_s, 0, 0); 332 return wpas_dbus_new_success_reply(message); 333} 334 335 336/** 337 * wpas_dbus_iface_scan_results - Get the results of a recent scan request 338 * @message: Pointer to incoming dbus message 339 * @wpa_s: wpa_supplicant structure for a network interface 340 * Returns: a dbus message containing a dbus array of objects paths, or returns 341 * a dbus error message if not scan results could be found 342 * 343 * Handler function for "scanResults" method call of a network device. Returns 344 * a dbus message containing the object paths of wireless networks found. 345 */ 346DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message, 347 struct wpa_supplicant *wpa_s) 348{ 349 DBusMessage *reply = NULL; 350 DBusMessageIter iter; 351 DBusMessageIter sub_iter; 352 struct wpa_bss *bss; 353 354 /* Create and initialize the return message */ 355 reply = dbus_message_new_method_return(message); 356 dbus_message_iter_init_append(reply, &iter); 357 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 358 DBUS_TYPE_OBJECT_PATH_AS_STRING, 359 &sub_iter); 360 361 /* Loop through scan results and append each result's object path */ 362 dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { 363 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX]; 364 char *path = path_buf; 365 366 /* Construct the object path for this network. Note that ':' 367 * is not a valid character in dbus object paths. 368 */ 369 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 370 "%s/" WPAS_DBUS_BSSIDS_PART "/" 371 WPAS_DBUS_BSSID_FORMAT, 372 wpa_s->dbus_path, MAC2STR(bss->bssid)); 373 dbus_message_iter_append_basic(&sub_iter, 374 DBUS_TYPE_OBJECT_PATH, &path); 375 } 376 377 dbus_message_iter_close_container(&iter, &sub_iter); 378 379 return reply; 380} 381 382 383/** 384 * wpas_dbus_bssid_properties - Return the properties of a scanned network 385 * @message: Pointer to incoming dbus message 386 * @wpa_s: wpa_supplicant structure for a network interface 387 * @res: wpa_supplicant scan result for which to get properties 388 * Returns: a dbus message containing the properties for the requested network 389 * 390 * Handler function for "properties" method call of a scanned network. 391 * Returns a dbus message containing the the properties. 392 */ 393DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message, 394 struct wpa_supplicant *wpa_s, 395 struct wpa_bss *bss) 396{ 397 DBusMessage *reply; 398 DBusMessageIter iter, iter_dict; 399 const u8 *ie; 400 401 /* Dump the properties into a dbus message */ 402 reply = dbus_message_new_method_return(message); 403 404 dbus_message_iter_init_append(reply, &iter); 405 if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 406 goto error; 407 408 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid", 409 (const char *) bss->bssid, 410 ETH_ALEN)) 411 goto error; 412 413 ie = wpa_bss_get_ie(bss, WLAN_EID_SSID); 414 if (ie) { 415 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid", 416 (const char *) (ie + 2), 417 ie[1])) 418 goto error; 419 } 420 421 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); 422 if (ie) { 423 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie", 424 (const char *) ie, 425 ie[1] + 2)) 426 goto error; 427 } 428 429 ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); 430 if (ie) { 431 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie", 432 (const char *) ie, 433 ie[1] + 2)) 434 goto error; 435 } 436 437 ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE); 438 if (ie) { 439 if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie", 440 (const char *) ie, 441 ie[1] + 2)) 442 goto error; 443 } 444 445 if (bss->freq) { 446 if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency", 447 bss->freq)) 448 goto error; 449 } 450 if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities", 451 bss->caps)) 452 goto error; 453 if (!(bss->flags & WPA_BSS_QUAL_INVALID) && 454 !wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual)) 455 goto error; 456 if (!(bss->flags & WPA_BSS_NOISE_INVALID) && 457 !wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise)) 458 goto error; 459 if (!(bss->flags & WPA_BSS_LEVEL_INVALID) && 460 !wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level)) 461 goto error; 462 if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate", 463 wpa_bss_get_max_rate(bss) * 500000)) 464 goto error; 465 466 if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 467 goto error; 468 469 return reply; 470 471error: 472 if (reply) 473 dbus_message_unref(reply); 474 return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, 475 "an internal error occurred returning " 476 "BSSID properties."); 477} 478 479 480/** 481 * wpas_dbus_iface_capabilities - Return interface capabilities 482 * @message: Pointer to incoming dbus message 483 * @wpa_s: wpa_supplicant structure for a network interface 484 * Returns: A dbus message containing a dict of strings 485 * 486 * Handler function for "capabilities" method call of an interface. 487 */ 488DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message, 489 struct wpa_supplicant *wpa_s) 490{ 491 DBusMessage *reply = NULL; 492 struct wpa_driver_capa capa; 493 int res; 494 DBusMessageIter iter, iter_dict; 495 char **eap_methods; 496 size_t num_items; 497 dbus_bool_t strict = FALSE; 498 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; 499 500 if (!dbus_message_get_args(message, NULL, 501 DBUS_TYPE_BOOLEAN, &strict, 502 DBUS_TYPE_INVALID)) 503 strict = FALSE; 504 505 reply = dbus_message_new_method_return(message); 506 507 dbus_message_iter_init_append(reply, &iter); 508 if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) 509 goto error; 510 511 /* EAP methods */ 512 eap_methods = eap_get_names_as_string_array(&num_items); 513 if (eap_methods) { 514 dbus_bool_t success = FALSE; 515 size_t i = 0; 516 517 success = wpa_dbus_dict_append_string_array( 518 &iter_dict, "eap", (const char **) eap_methods, 519 num_items); 520 521 /* free returned method array */ 522 while (eap_methods[i]) 523 os_free(eap_methods[i++]); 524 os_free(eap_methods); 525 526 if (!success) 527 goto error; 528 } 529 530 res = wpa_drv_get_capa(wpa_s, &capa); 531 532 /***** pairwise cipher */ 533 if (res < 0) { 534 if (!strict) { 535 const char *args[] = {"CCMP", "TKIP", "NONE"}; 536 if (!wpa_dbus_dict_append_string_array( 537 &iter_dict, "pairwise", args, 538 ARRAY_SIZE(args))) 539 goto error; 540 } 541 } else { 542 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise", 543 &iter_dict_entry, 544 &iter_dict_val, 545 &iter_array)) 546 goto error; 547 548 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 549 if (!wpa_dbus_dict_string_array_add_element( 550 &iter_array, "CCMP")) 551 goto error; 552 } 553 554 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 555 if (!wpa_dbus_dict_string_array_add_element( 556 &iter_array, "TKIP")) 557 goto error; 558 } 559 560 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 561 if (!wpa_dbus_dict_string_array_add_element( 562 &iter_array, "NONE")) 563 goto error; 564 } 565 566 if (!wpa_dbus_dict_end_string_array(&iter_dict, 567 &iter_dict_entry, 568 &iter_dict_val, 569 &iter_array)) 570 goto error; 571 } 572 573 /***** group cipher */ 574 if (res < 0) { 575 if (!strict) { 576 const char *args[] = { 577 "CCMP", "TKIP", "WEP104", "WEP40" 578 }; 579 if (!wpa_dbus_dict_append_string_array( 580 &iter_dict, "group", args, 581 ARRAY_SIZE(args))) 582 goto error; 583 } 584 } else { 585 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group", 586 &iter_dict_entry, 587 &iter_dict_val, 588 &iter_array)) 589 goto error; 590 591 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { 592 if (!wpa_dbus_dict_string_array_add_element( 593 &iter_array, "CCMP")) 594 goto error; 595 } 596 597 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { 598 if (!wpa_dbus_dict_string_array_add_element( 599 &iter_array, "TKIP")) 600 goto error; 601 } 602 603 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { 604 if (!wpa_dbus_dict_string_array_add_element( 605 &iter_array, "WEP104")) 606 goto error; 607 } 608 609 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { 610 if (!wpa_dbus_dict_string_array_add_element( 611 &iter_array, "WEP40")) 612 goto error; 613 } 614 615 if (!wpa_dbus_dict_end_string_array(&iter_dict, 616 &iter_dict_entry, 617 &iter_dict_val, 618 &iter_array)) 619 goto error; 620 } 621 622 /***** key management */ 623 if (res < 0) { 624 if (!strict) { 625 const char *args[] = { 626 "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE", 627 "NONE" 628 }; 629 if (!wpa_dbus_dict_append_string_array( 630 &iter_dict, "key_mgmt", args, 631 ARRAY_SIZE(args))) 632 goto error; 633 } 634 } else { 635 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt", 636 &iter_dict_entry, 637 &iter_dict_val, 638 &iter_array)) 639 goto error; 640 641 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 642 "NONE")) 643 goto error; 644 645 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 646 "IEEE8021X")) 647 goto error; 648 649 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 650 WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { 651 if (!wpa_dbus_dict_string_array_add_element( 652 &iter_array, "WPA-EAP")) 653 goto error; 654 } 655 656 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 657 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 658 if (!wpa_dbus_dict_string_array_add_element( 659 &iter_array, "WPA-PSK")) 660 goto error; 661 } 662 663 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { 664 if (!wpa_dbus_dict_string_array_add_element( 665 &iter_array, "WPA-NONE")) 666 goto error; 667 } 668 669 if (!wpa_dbus_dict_end_string_array(&iter_dict, 670 &iter_dict_entry, 671 &iter_dict_val, 672 &iter_array)) 673 goto error; 674 } 675 676 /***** WPA protocol */ 677 if (res < 0) { 678 if (!strict) { 679 const char *args[] = { "RSN", "WPA" }; 680 if (!wpa_dbus_dict_append_string_array( 681 &iter_dict, "proto", args, 682 ARRAY_SIZE(args))) 683 goto error; 684 } 685 } else { 686 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto", 687 &iter_dict_entry, 688 &iter_dict_val, 689 &iter_array)) 690 goto error; 691 692 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 693 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { 694 if (!wpa_dbus_dict_string_array_add_element( 695 &iter_array, "RSN")) 696 goto error; 697 } 698 699 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | 700 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { 701 if (!wpa_dbus_dict_string_array_add_element( 702 &iter_array, "WPA")) 703 goto error; 704 } 705 706 if (!wpa_dbus_dict_end_string_array(&iter_dict, 707 &iter_dict_entry, 708 &iter_dict_val, 709 &iter_array)) 710 goto error; 711 } 712 713 /***** auth alg */ 714 if (res < 0) { 715 if (!strict) { 716 const char *args[] = { "OPEN", "SHARED", "LEAP" }; 717 if (!wpa_dbus_dict_append_string_array( 718 &iter_dict, "auth_alg", args, 719 ARRAY_SIZE(args))) 720 goto error; 721 } 722 } else { 723 if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg", 724 &iter_dict_entry, 725 &iter_dict_val, 726 &iter_array)) 727 goto error; 728 729 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { 730 if (!wpa_dbus_dict_string_array_add_element( 731 &iter_array, "OPEN")) 732 goto error; 733 } 734 735 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { 736 if (!wpa_dbus_dict_string_array_add_element( 737 &iter_array, "SHARED")) 738 goto error; 739 } 740 741 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { 742 if (!wpa_dbus_dict_string_array_add_element( 743 &iter_array, "LEAP")) 744 goto error; 745 } 746 747 if (!wpa_dbus_dict_end_string_array(&iter_dict, 748 &iter_dict_entry, 749 &iter_dict_val, 750 &iter_array)) 751 goto error; 752 } 753 754 if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) 755 goto error; 756 757 return reply; 758 759error: 760 if (reply) 761 dbus_message_unref(reply); 762 return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, 763 "an internal error occurred returning " 764 "interface capabilities."); 765} 766 767 768/** 769 * wpas_dbus_iface_add_network - Add a new configured network 770 * @message: Pointer to incoming dbus message 771 * @wpa_s: wpa_supplicant structure for a network interface 772 * Returns: A dbus message containing the object path of the new network 773 * 774 * Handler function for "addNetwork" method call of a network interface. 775 */ 776DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message, 777 struct wpa_supplicant *wpa_s) 778{ 779 DBusMessage *reply = NULL; 780 struct wpa_ssid *ssid; 781 char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; 782 783 ssid = wpa_config_add_network(wpa_s->conf); 784 if (ssid == NULL) { 785 reply = dbus_message_new_error(message, 786 WPAS_ERROR_ADD_NETWORK_ERROR, 787 "wpa_supplicant could not add " 788 "a network on this interface."); 789 goto out; 790 } 791 wpas_notify_network_added(wpa_s, ssid); 792 ssid->disabled = 1; 793 wpa_config_set_network_defaults(ssid); 794 795 /* Construct the object path for this network. */ 796 os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, 797 "%s/" WPAS_DBUS_NETWORKS_PART "/%d", 798 wpa_s->dbus_path, ssid->id); 799 800 reply = dbus_message_new_method_return(message); 801 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, 802 &path, DBUS_TYPE_INVALID); 803 804out: 805 return reply; 806} 807 808 809/** 810 * wpas_dbus_iface_remove_network - Remove a configured network 811 * @message: Pointer to incoming dbus message 812 * @wpa_s: wpa_supplicant structure for a network interface 813 * Returns: A dbus message containing a UINT32 indicating success (1) or 814 * failure (0) 815 * 816 * Handler function for "removeNetwork" method call of a network interface. 817 */ 818DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message, 819 struct wpa_supplicant *wpa_s) 820{ 821 DBusMessage *reply = NULL; 822 const char *op; 823 char *iface = NULL, *net_id = NULL; 824 int id; 825 struct wpa_ssid *ssid; 826 827 if (!dbus_message_get_args(message, NULL, 828 DBUS_TYPE_OBJECT_PATH, &op, 829 DBUS_TYPE_INVALID)) { 830 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 831 goto out; 832 } 833 834 /* Extract the network ID */ 835 iface = wpas_dbus_decompose_object_path(op, &net_id, NULL); 836 if (iface == NULL) { 837 reply = wpas_dbus_new_invalid_network_error(message); 838 goto out; 839 } 840 841 /* Ensure the network is actually a child of this interface */ 842 if (os_strcmp(iface, wpa_s->dbus_path) != 0) { 843 reply = wpas_dbus_new_invalid_network_error(message); 844 goto out; 845 } 846 847 id = strtoul(net_id, NULL, 10); 848 ssid = wpa_config_get_network(wpa_s->conf, id); 849 if (ssid == NULL) { 850 reply = wpas_dbus_new_invalid_network_error(message); 851 goto out; 852 } 853 854 wpas_notify_network_removed(wpa_s, ssid); 855 856 if (wpa_config_remove_network(wpa_s->conf, id) < 0) { 857 reply = dbus_message_new_error(message, 858 WPAS_ERROR_REMOVE_NETWORK_ERROR, 859 "error removing the specified " 860 "on this interface."); 861 goto out; 862 } 863 864 if (ssid == wpa_s->current_ssid) 865 wpa_supplicant_deauthenticate(wpa_s, 866 WLAN_REASON_DEAUTH_LEAVING); 867 reply = wpas_dbus_new_success_reply(message); 868 869out: 870 os_free(iface); 871 os_free(net_id); 872 return reply; 873} 874 875 876static const char *dont_quote[] = { 877 "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", 878 "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path", 879 "bssid", NULL 880}; 881 882 883static dbus_bool_t should_quote_opt(const char *key) 884{ 885 int i = 0; 886 while (dont_quote[i] != NULL) { 887 if (strcmp(key, dont_quote[i]) == 0) 888 return FALSE; 889 i++; 890 } 891 return TRUE; 892} 893 894 895/** 896 * wpas_dbus_iface_set_network - Set options for a configured network 897 * @message: Pointer to incoming dbus message 898 * @wpa_s: wpa_supplicant structure for a network interface 899 * @ssid: wpa_ssid structure for a configured network 900 * Returns: a dbus message containing a UINT32 indicating success (1) or 901 * failure (0) 902 * 903 * Handler function for "set" method call of a configured network. 904 */ 905DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message, 906 struct wpa_supplicant *wpa_s, 907 struct wpa_ssid *ssid) 908{ 909 DBusMessage *reply = NULL; 910 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 911 DBusMessageIter iter, iter_dict; 912 913 dbus_message_iter_init(message, &iter); 914 915 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) { 916 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 917 goto out; 918 } 919 920 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 921 char *value = NULL; 922 size_t size = 50; 923 int ret; 924 925 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 926 reply = wpas_dbus_new_invalid_opts_error(message, 927 NULL); 928 goto out; 929 } 930 931 /* Type conversions, since wpa_supplicant wants strings */ 932 if (entry.type == DBUS_TYPE_ARRAY && 933 entry.array_type == DBUS_TYPE_BYTE) { 934 if (entry.array_len <= 0) 935 goto error; 936 937 size = entry.array_len * 2 + 1; 938 value = os_zalloc(size); 939 if (value == NULL) 940 goto error; 941 ret = wpa_snprintf_hex(value, size, 942 (u8 *) entry.bytearray_value, 943 entry.array_len); 944 if (ret <= 0) 945 goto error; 946 } else if (entry.type == DBUS_TYPE_STRING) { 947 if (should_quote_opt(entry.key)) { 948 size = os_strlen(entry.str_value); 949 /* Zero-length option check */ 950 if (size <= 0) 951 goto error; 952 size += 3; /* For quotes and terminator */ 953 value = os_zalloc(size); 954 if (value == NULL) 955 goto error; 956 ret = os_snprintf(value, size, "\"%s\"", 957 entry.str_value); 958 if (ret < 0 || (size_t) ret != (size - 1)) 959 goto error; 960 } else { 961 value = os_strdup(entry.str_value); 962 if (value == NULL) 963 goto error; 964 } 965 } else if (entry.type == DBUS_TYPE_UINT32) { 966 value = os_zalloc(size); 967 if (value == NULL) 968 goto error; 969 ret = os_snprintf(value, size, "%u", 970 entry.uint32_value); 971 if (ret <= 0) 972 goto error; 973 } else if (entry.type == DBUS_TYPE_INT32) { 974 value = os_zalloc(size); 975 if (value == NULL) 976 goto error; 977 ret = os_snprintf(value, size, "%d", 978 entry.int32_value); 979 if (ret <= 0) 980 goto error; 981 } else 982 goto error; 983 984 if (wpa_config_set(ssid, entry.key, value, 0) < 0) 985 goto error; 986 987 if ((os_strcmp(entry.key, "psk") == 0 && 988 value[0] == '"' && ssid->ssid_len) || 989 (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase)) 990 wpa_config_update_psk(ssid); 991 else if (os_strcmp(entry.key, "priority") == 0) 992 wpa_config_update_prio_list(wpa_s->conf); 993 994 os_free(value); 995 wpa_dbus_dict_entry_clear(&entry); 996 continue; 997 998 error: 999 os_free(value); 1000 reply = wpas_dbus_new_invalid_opts_error(message, entry.key); 1001 wpa_dbus_dict_entry_clear(&entry); 1002 break; 1003 } 1004 1005 if (!reply) 1006 reply = wpas_dbus_new_success_reply(message); 1007 1008out: 1009 return reply; 1010} 1011 1012 1013/** 1014 * wpas_dbus_iface_enable_network - Mark a configured network as enabled 1015 * @message: Pointer to incoming dbus message 1016 * @wpa_s: wpa_supplicant structure for a network interface 1017 * @ssid: wpa_ssid structure for a configured network 1018 * Returns: A dbus message containing a UINT32 indicating success (1) or 1019 * failure (0) 1020 * 1021 * Handler function for "enable" method call of a configured network. 1022 */ 1023DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message, 1024 struct wpa_supplicant *wpa_s, 1025 struct wpa_ssid *ssid) 1026{ 1027 wpa_supplicant_enable_network(wpa_s, ssid); 1028 return wpas_dbus_new_success_reply(message); 1029} 1030 1031 1032/** 1033 * wpas_dbus_iface_disable_network - Mark a configured network as disabled 1034 * @message: Pointer to incoming dbus message 1035 * @wpa_s: wpa_supplicant structure for a network interface 1036 * @ssid: wpa_ssid structure for a configured network 1037 * Returns: A dbus message containing a UINT32 indicating success (1) or 1038 * failure (0) 1039 * 1040 * Handler function for "disable" method call of a configured network. 1041 */ 1042DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message, 1043 struct wpa_supplicant *wpa_s, 1044 struct wpa_ssid *ssid) 1045{ 1046 wpa_supplicant_disable_network(wpa_s, ssid); 1047 return wpas_dbus_new_success_reply(message); 1048} 1049 1050 1051/** 1052 * wpas_dbus_iface_select_network - Attempt association with a configured network 1053 * @message: Pointer to incoming dbus message 1054 * @wpa_s: wpa_supplicant structure for a network interface 1055 * Returns: A dbus message containing a UINT32 indicating success (1) or 1056 * failure (0) 1057 * 1058 * Handler function for "selectNetwork" method call of network interface. 1059 */ 1060DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, 1061 struct wpa_supplicant *wpa_s) 1062{ 1063 DBusMessage *reply = NULL; 1064 const char *op; 1065 struct wpa_ssid *ssid; 1066 char *iface_obj_path = NULL; 1067 char *network = NULL; 1068 1069 if (os_strlen(dbus_message_get_signature(message)) == 0) { 1070 /* Any network */ 1071 ssid = NULL; 1072 } else { 1073 int nid; 1074 1075 if (!dbus_message_get_args(message, NULL, 1076 DBUS_TYPE_OBJECT_PATH, &op, 1077 DBUS_TYPE_INVALID)) { 1078 reply = wpas_dbus_new_invalid_opts_error(message, 1079 NULL); 1080 goto out; 1081 } 1082 1083 /* Extract the network number */ 1084 iface_obj_path = wpas_dbus_decompose_object_path(op, 1085 &network, 1086 NULL); 1087 if (iface_obj_path == NULL) { 1088 reply = wpas_dbus_new_invalid_iface_error(message); 1089 goto out; 1090 } 1091 /* Ensure the object path really points to this interface */ 1092 if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) { 1093 reply = wpas_dbus_new_invalid_network_error(message); 1094 goto out; 1095 } 1096 1097 nid = strtoul(network, NULL, 10); 1098 if (errno == EINVAL) { 1099 reply = wpas_dbus_new_invalid_network_error(message); 1100 goto out; 1101 } 1102 1103 ssid = wpa_config_get_network(wpa_s->conf, nid); 1104 if (ssid == NULL) { 1105 reply = wpas_dbus_new_invalid_network_error(message); 1106 goto out; 1107 } 1108 } 1109 1110 /* Finally, associate with the network */ 1111 wpa_supplicant_select_network(wpa_s, ssid); 1112 1113 reply = wpas_dbus_new_success_reply(message); 1114 1115out: 1116 os_free(iface_obj_path); 1117 os_free(network); 1118 return reply; 1119} 1120 1121 1122/** 1123 * wpas_dbus_iface_disconnect - Terminate the current connection 1124 * @message: Pointer to incoming dbus message 1125 * @wpa_s: wpa_supplicant structure for a network interface 1126 * Returns: A dbus message containing a UINT32 indicating success (1) or 1127 * failure (0) 1128 * 1129 * Handler function for "disconnect" method call of network interface. 1130 */ 1131DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message, 1132 struct wpa_supplicant *wpa_s) 1133{ 1134 wpa_s->disconnected = 1; 1135 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); 1136 1137 return wpas_dbus_new_success_reply(message); 1138} 1139 1140 1141/** 1142 * wpas_dbus_iface_set_ap_scan - Control roaming mode 1143 * @message: Pointer to incoming dbus message 1144 * @wpa_s: wpa_supplicant structure for a network interface 1145 * Returns: A dbus message containing a UINT32 indicating success (1) or 1146 * failure (0) 1147 * 1148 * Handler function for "setAPScan" method call. 1149 */ 1150DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message, 1151 struct wpa_supplicant *wpa_s) 1152{ 1153 DBusMessage *reply = NULL; 1154 dbus_uint32_t ap_scan = 1; 1155 1156 if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan, 1157 DBUS_TYPE_INVALID)) { 1158 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 1159 goto out; 1160 } 1161 1162 if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) { 1163 reply = wpas_dbus_new_invalid_opts_error(message, NULL); 1164 goto out; 1165 } 1166 1167 reply = wpas_dbus_new_success_reply(message); 1168 1169out: 1170 return reply; 1171} 1172 1173 1174/** 1175 * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths 1176 * @message: Pointer to incoming dbus message 1177 * @wpa_s: wpa_supplicant structure for a network interface 1178 * Returns: A dbus message containing a UINT32 indicating success (1) or 1179 * failure (0) 1180 * 1181 * Handler function for "setSmartcardModules" method call. 1182 */ 1183DBusMessage * wpas_dbus_iface_set_smartcard_modules( 1184 DBusMessage *message, struct wpa_supplicant *wpa_s) 1185{ 1186 DBusMessageIter iter, iter_dict; 1187 char *opensc_engine_path = NULL; 1188 char *pkcs11_engine_path = NULL; 1189 char *pkcs11_module_path = NULL; 1190 struct wpa_dbus_dict_entry entry; 1191 1192 if (!dbus_message_iter_init(message, &iter)) 1193 goto error; 1194 1195 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 1196 goto error; 1197 1198 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 1199 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) 1200 goto error; 1201 if (!strcmp(entry.key, "opensc_engine_path") && 1202 (entry.type == DBUS_TYPE_STRING)) { 1203 opensc_engine_path = os_strdup(entry.str_value); 1204 if (opensc_engine_path == NULL) 1205 goto error; 1206 } else if (!strcmp(entry.key, "pkcs11_engine_path") && 1207 (entry.type == DBUS_TYPE_STRING)) { 1208 pkcs11_engine_path = os_strdup(entry.str_value); 1209 if (pkcs11_engine_path == NULL) 1210 goto error; 1211 } else if (!strcmp(entry.key, "pkcs11_module_path") && 1212 (entry.type == DBUS_TYPE_STRING)) { 1213 pkcs11_module_path = os_strdup(entry.str_value); 1214 if (pkcs11_module_path == NULL) 1215 goto error; 1216 } else { 1217 wpa_dbus_dict_entry_clear(&entry); 1218 goto error; 1219 } 1220 wpa_dbus_dict_entry_clear(&entry); 1221 } 1222 1223 os_free(wpa_s->conf->opensc_engine_path); 1224 wpa_s->conf->opensc_engine_path = opensc_engine_path; 1225 os_free(wpa_s->conf->pkcs11_engine_path); 1226 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path; 1227 os_free(wpa_s->conf->pkcs11_module_path); 1228 wpa_s->conf->pkcs11_module_path = pkcs11_module_path; 1229 1230 wpa_sm_set_eapol(wpa_s->wpa, NULL); 1231 eapol_sm_deinit(wpa_s->eapol); 1232 wpa_s->eapol = NULL; 1233 wpa_supplicant_init_eapol(wpa_s); 1234 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); 1235 1236 return wpas_dbus_new_success_reply(message); 1237 1238error: 1239 os_free(opensc_engine_path); 1240 os_free(pkcs11_engine_path); 1241 os_free(pkcs11_module_path); 1242 return wpas_dbus_new_invalid_opts_error(message, NULL); 1243} 1244 1245 1246/** 1247 * wpas_dbus_iface_get_state - Get interface state 1248 * @message: Pointer to incoming dbus message 1249 * @wpa_s: wpa_supplicant structure for a network interface 1250 * Returns: A dbus message containing a STRING representing the current 1251 * interface state 1252 * 1253 * Handler function for "state" method call. 1254 */ 1255DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message, 1256 struct wpa_supplicant *wpa_s) 1257{ 1258 DBusMessage *reply = NULL; 1259 const char *str_state; 1260 1261 reply = dbus_message_new_method_return(message); 1262 if (reply != NULL) { 1263 str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); 1264 dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state, 1265 DBUS_TYPE_INVALID); 1266 } 1267 1268 return reply; 1269} 1270 1271 1272/** 1273 * wpas_dbus_iface_get_scanning - Get interface scanning state 1274 * @message: Pointer to incoming dbus message 1275 * @wpa_s: wpa_supplicant structure for a network interface 1276 * Returns: A dbus message containing whether the interface is scanning 1277 * 1278 * Handler function for "scanning" method call. 1279 */ 1280DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message, 1281 struct wpa_supplicant *wpa_s) 1282{ 1283 DBusMessage *reply = NULL; 1284 dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE; 1285 1286 reply = dbus_message_new_method_return(message); 1287 if (reply != NULL) { 1288 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning, 1289 DBUS_TYPE_INVALID); 1290 } else { 1291 wpa_printf(MSG_ERROR, "dbus: Not enough memory to return " 1292 "scanning state"); 1293 } 1294 1295 return reply; 1296} 1297 1298 1299#ifndef CONFIG_NO_CONFIG_BLOBS 1300 1301/** 1302 * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates) 1303 * @message: Pointer to incoming dbus message 1304 * @wpa_s: %wpa_supplicant data structure 1305 * Returns: A dbus message containing a UINT32 indicating success (1) or 1306 * failure (0) 1307 * 1308 * Asks wpa_supplicant to internally store a one or more binary blobs. 1309 */ 1310DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, 1311 struct wpa_supplicant *wpa_s) 1312{ 1313 DBusMessage *reply = NULL; 1314 struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; 1315 DBusMessageIter iter, iter_dict; 1316 1317 dbus_message_iter_init(message, &iter); 1318 1319 if (!wpa_dbus_dict_open_read(&iter, &iter_dict, NULL)) 1320 return wpas_dbus_new_invalid_opts_error(message, NULL); 1321 1322 while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { 1323 struct wpa_config_blob *blob; 1324 1325 if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { 1326 reply = wpas_dbus_new_invalid_opts_error(message, 1327 NULL); 1328 break; 1329 } 1330 1331 if (entry.type != DBUS_TYPE_ARRAY || 1332 entry.array_type != DBUS_TYPE_BYTE) { 1333 reply = wpas_dbus_new_invalid_opts_error( 1334 message, "Byte array expected."); 1335 break; 1336 } 1337 1338 if ((entry.array_len <= 0) || (entry.array_len > 65536) || 1339 !strlen(entry.key)) { 1340 reply = wpas_dbus_new_invalid_opts_error( 1341 message, "Invalid array size."); 1342 break; 1343 } 1344 1345 blob = os_zalloc(sizeof(*blob)); 1346 if (blob == NULL) { 1347 reply = dbus_message_new_error( 1348 message, WPAS_ERROR_ADD_ERROR, 1349 "Not enough memory to add blob."); 1350 break; 1351 } 1352 blob->data = os_zalloc(entry.array_len); 1353 if (blob->data == NULL) { 1354 reply = dbus_message_new_error( 1355 message, WPAS_ERROR_ADD_ERROR, 1356 "Not enough memory to add blob data."); 1357 os_free(blob); 1358 break; 1359 } 1360 1361 blob->name = os_strdup(entry.key); 1362 blob->len = entry.array_len; 1363 os_memcpy(blob->data, (u8 *) entry.bytearray_value, 1364 entry.array_len); 1365 if (blob->name == NULL || blob->data == NULL) { 1366 wpa_config_free_blob(blob); 1367 reply = dbus_message_new_error( 1368 message, WPAS_ERROR_ADD_ERROR, 1369 "Error adding blob."); 1370 break; 1371 } 1372 1373 /* Success */ 1374 if (!wpa_config_remove_blob(wpa_s->conf, blob->name)) 1375 wpas_notify_blob_removed(wpa_s, blob->name); 1376 wpa_config_set_blob(wpa_s->conf, blob); 1377 wpas_notify_blob_added(wpa_s, blob->name); 1378 1379 wpa_dbus_dict_entry_clear(&entry); 1380 } 1381 wpa_dbus_dict_entry_clear(&entry); 1382 1383 return reply ? reply : wpas_dbus_new_success_reply(message); 1384} 1385 1386 1387/** 1388 * wpas_dbus_iface_remove_blob - Remove named binary blobs 1389 * @message: Pointer to incoming dbus message 1390 * @wpa_s: %wpa_supplicant data structure 1391 * Returns: A dbus message containing a UINT32 indicating success (1) or 1392 * failure (0) 1393 * 1394 * Asks wpa_supplicant to remove one or more previously stored binary blobs. 1395 */ 1396DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, 1397 struct wpa_supplicant *wpa_s) 1398{ 1399 DBusMessageIter iter, array; 1400 char *err_msg = NULL; 1401 1402 dbus_message_iter_init(message, &iter); 1403 1404 if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) || 1405 (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)) 1406 return wpas_dbus_new_invalid_opts_error(message, NULL); 1407 1408 dbus_message_iter_recurse(&iter, &array); 1409 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { 1410 const char *name; 1411 1412 dbus_message_iter_get_basic(&array, &name); 1413 if (!os_strlen(name)) 1414 err_msg = "Invalid blob name."; 1415 1416 if (wpa_config_remove_blob(wpa_s->conf, name) != 0) 1417 err_msg = "Error removing blob."; 1418 else 1419 wpas_notify_blob_removed(wpa_s, name); 1420 dbus_message_iter_next(&array); 1421 } 1422 1423 if (err_msg) 1424 return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR, 1425 err_msg); 1426 1427 return wpas_dbus_new_success_reply(message); 1428} 1429 1430#endif /* CONFIG_NO_CONFIG_BLOBS */ 1431 1432 1433/** 1434 * wpas_dbus_iface_flush - Clear BSS of old or all inactive entries 1435 * @message: Pointer to incoming dbus message 1436 * @wpa_s: %wpa_supplicant data structure 1437 * Returns: a dbus message containing a UINT32 indicating success (1) or 1438 * failure (0), or returns a dbus error message with more information 1439 * 1440 * Handler function for "flush" method call. Handles requests for an 1441 * interface with an optional "age" parameter that specifies the minimum 1442 * age of a BSS to be flushed. 1443 */ 1444DBusMessage * wpas_dbus_iface_flush(DBusMessage *message, 1445 struct wpa_supplicant *wpa_s) 1446{ 1447 int flush_age = 0; 1448 1449 if (os_strlen(dbus_message_get_signature(message)) != 0 && 1450 !dbus_message_get_args(message, NULL, 1451 DBUS_TYPE_INT32, &flush_age, 1452 DBUS_TYPE_INVALID)) { 1453 return wpas_dbus_new_invalid_opts_error(message, NULL); 1454 } 1455 1456 if (flush_age == 0) 1457 wpa_bss_flush(wpa_s); 1458 else 1459 wpa_bss_flush_by_age(wpa_s, flush_age); 1460 1461 return wpas_dbus_new_success_reply(message); 1462} 1463