1 /* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 #include <dbus/dbus.h> 17 18 #include "common.h" 19 #include "wpabuf.h" 20 #include "dbus_dict_helpers.h" 21 22 23 /** 24 * Start a dict in a dbus message. Should be paired with a call to 25 * wpa_dbus_dict_close_write(). 26 * 27 * @param iter A valid dbus message iterator 28 * @param iter_dict (out) A dict iterator to pass to further dict functions 29 * @return TRUE on success, FALSE on failure 30 * 31 */ 32 dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter, 33 DBusMessageIter *iter_dict) 34 { 35 dbus_bool_t result; 36 37 if (!iter || !iter_dict) 38 return FALSE; 39 40 result = dbus_message_iter_open_container( 41 iter, 42 DBUS_TYPE_ARRAY, 43 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 44 DBUS_TYPE_STRING_AS_STRING 45 DBUS_TYPE_VARIANT_AS_STRING 46 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, 47 iter_dict); 48 return result; 49 } 50 51 52 /** 53 * End a dict element in a dbus message. Should be paired with 54 * a call to wpa_dbus_dict_open_write(). 55 * 56 * @param iter valid dbus message iterator, same as passed to 57 * wpa_dbus_dict_open_write() 58 * @param iter_dict a dbus dict iterator returned from 59 * wpa_dbus_dict_open_write() 60 * @return TRUE on success, FALSE on failure 61 * 62 */ 63 dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter, 64 DBusMessageIter *iter_dict) 65 { 66 if (!iter || !iter_dict) 67 return FALSE; 68 69 return dbus_message_iter_close_container(iter, iter_dict); 70 } 71 72 73 const char * wpa_dbus_type_as_string(const int type) 74 { 75 switch(type) { 76 case DBUS_TYPE_BYTE: 77 return DBUS_TYPE_BYTE_AS_STRING; 78 case DBUS_TYPE_BOOLEAN: 79 return DBUS_TYPE_BOOLEAN_AS_STRING; 80 case DBUS_TYPE_INT16: 81 return DBUS_TYPE_INT16_AS_STRING; 82 case DBUS_TYPE_UINT16: 83 return DBUS_TYPE_UINT16_AS_STRING; 84 case DBUS_TYPE_INT32: 85 return DBUS_TYPE_INT32_AS_STRING; 86 case DBUS_TYPE_UINT32: 87 return DBUS_TYPE_UINT32_AS_STRING; 88 case DBUS_TYPE_INT64: 89 return DBUS_TYPE_INT64_AS_STRING; 90 case DBUS_TYPE_UINT64: 91 return DBUS_TYPE_UINT64_AS_STRING; 92 case DBUS_TYPE_DOUBLE: 93 return DBUS_TYPE_DOUBLE_AS_STRING; 94 case DBUS_TYPE_STRING: 95 return DBUS_TYPE_STRING_AS_STRING; 96 case DBUS_TYPE_OBJECT_PATH: 97 return DBUS_TYPE_OBJECT_PATH_AS_STRING; 98 case DBUS_TYPE_ARRAY: 99 return DBUS_TYPE_ARRAY_AS_STRING; 100 default: 101 return NULL; 102 } 103 } 104 105 106 static dbus_bool_t _wpa_dbus_add_dict_entry_start( 107 DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry, 108 const char *key, const int value_type) 109 { 110 if (!dbus_message_iter_open_container(iter_dict, 111 DBUS_TYPE_DICT_ENTRY, NULL, 112 iter_dict_entry)) 113 return FALSE; 114 115 if (!dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING, 116 &key)) 117 return FALSE; 118 119 return TRUE; 120 } 121 122 123 static dbus_bool_t _wpa_dbus_add_dict_entry_end( 124 DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry, 125 DBusMessageIter *iter_dict_val) 126 { 127 if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val)) 128 return FALSE; 129 if (!dbus_message_iter_close_container(iter_dict, iter_dict_entry)) 130 return FALSE; 131 132 return TRUE; 133 } 134 135 136 static dbus_bool_t _wpa_dbus_add_dict_entry_basic(DBusMessageIter *iter_dict, 137 const char *key, 138 const int value_type, 139 const void *value) 140 { 141 DBusMessageIter iter_dict_entry, iter_dict_val; 142 const char *type_as_string = NULL; 143 144 if (key == NULL) 145 return FALSE; 146 147 type_as_string = wpa_dbus_type_as_string(value_type); 148 if (!type_as_string) 149 return FALSE; 150 151 if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry, 152 key, value_type)) 153 return FALSE; 154 155 if (!dbus_message_iter_open_container(&iter_dict_entry, 156 DBUS_TYPE_VARIANT, 157 type_as_string, &iter_dict_val)) 158 return FALSE; 159 160 if (!dbus_message_iter_append_basic(&iter_dict_val, value_type, value)) 161 return FALSE; 162 163 if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry, 164 &iter_dict_val)) 165 return FALSE; 166 167 return TRUE; 168 } 169 170 171 static dbus_bool_t _wpa_dbus_add_dict_entry_byte_array( 172 DBusMessageIter *iter_dict, const char *key, 173 const char *value, const dbus_uint32_t value_len) 174 { 175 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; 176 dbus_uint32_t i; 177 178 if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry, 179 key, DBUS_TYPE_ARRAY)) 180 return FALSE; 181 182 if (!dbus_message_iter_open_container(&iter_dict_entry, 183 DBUS_TYPE_VARIANT, 184 DBUS_TYPE_ARRAY_AS_STRING 185 DBUS_TYPE_BYTE_AS_STRING, 186 &iter_dict_val)) 187 return FALSE; 188 189 if (!dbus_message_iter_open_container(&iter_dict_val, DBUS_TYPE_ARRAY, 190 DBUS_TYPE_BYTE_AS_STRING, 191 &iter_array)) 192 return FALSE; 193 194 for (i = 0; i < value_len; i++) { 195 if (!dbus_message_iter_append_basic(&iter_array, 196 DBUS_TYPE_BYTE, 197 &(value[i]))) 198 return FALSE; 199 } 200 201 if (!dbus_message_iter_close_container(&iter_dict_val, &iter_array)) 202 return FALSE; 203 204 if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry, 205 &iter_dict_val)) 206 return FALSE; 207 208 return TRUE; 209 } 210 211 212 /** 213 * Add a string entry to the dict. 214 * 215 * @param iter_dict A valid DBusMessageIter returned from 216 * wpa_dbus_dict_open_write() 217 * @param key The key of the dict item 218 * @param value The string value 219 * @return TRUE on success, FALSE on failure 220 * 221 */ 222 dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict, 223 const char *key, const char *value) 224 { 225 if (!value) 226 return FALSE; 227 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING, 228 &value); 229 } 230 231 232 /** 233 * Add a byte entry to the dict. 234 * 235 * @param iter_dict A valid DBusMessageIter returned from 236 * wpa_dbus_dict_open_write() 237 * @param key The key of the dict item 238 * @param value The byte value 239 * @return TRUE on success, FALSE on failure 240 * 241 */ 242 dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict, 243 const char *key, const char value) 244 { 245 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_BYTE, 246 &value); 247 } 248 249 250 /** 251 * Add a boolean entry to the dict. 252 * 253 * @param iter_dict A valid DBusMessageIter returned from 254 * wpa_dbus_dict_open_write() 255 * @param key The key of the dict item 256 * @param value The boolean value 257 * @return TRUE on success, FALSE on failure 258 * 259 */ 260 dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict, 261 const char *key, const dbus_bool_t value) 262 { 263 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, 264 DBUS_TYPE_BOOLEAN, &value); 265 } 266 267 268 /** 269 * Add a 16-bit signed integer entry to the dict. 270 * 271 * @param iter_dict A valid DBusMessageIter returned from 272 * wpa_dbus_dict_open_write() 273 * @param key The key of the dict item 274 * @param value The 16-bit signed integer value 275 * @return TRUE on success, FALSE on failure 276 * 277 */ 278 dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict, 279 const char *key, 280 const dbus_int16_t value) 281 { 282 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT16, 283 &value); 284 } 285 286 287 /** 288 * Add a 16-bit unsigned integer entry to the dict. 289 * 290 * @param iter_dict A valid DBusMessageIter returned from 291 * wpa_dbus_dict_open_write() 292 * @param key The key of the dict item 293 * @param value The 16-bit unsigned integer value 294 * @return TRUE on success, FALSE on failure 295 * 296 */ 297 dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict, 298 const char *key, 299 const dbus_uint16_t value) 300 { 301 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT16, 302 &value); 303 } 304 305 306 /** 307 * Add a 32-bit signed integer to the dict. 308 * 309 * @param iter_dict A valid DBusMessageIter returned from 310 * wpa_dbus_dict_open_write() 311 * @param key The key of the dict item 312 * @param value The 32-bit signed integer value 313 * @return TRUE on success, FALSE on failure 314 * 315 */ 316 dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict, 317 const char *key, 318 const dbus_int32_t value) 319 { 320 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32, 321 &value); 322 } 323 324 325 /** 326 * Add a 32-bit unsigned integer entry to the dict. 327 * 328 * @param iter_dict A valid DBusMessageIter returned from 329 * wpa_dbus_dict_open_write() 330 * @param key The key of the dict item 331 * @param value The 32-bit unsigned integer value 332 * @return TRUE on success, FALSE on failure 333 * 334 */ 335 dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict, 336 const char *key, 337 const dbus_uint32_t value) 338 { 339 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT32, 340 &value); 341 } 342 343 344 /** 345 * Add a 64-bit integer entry to the dict. 346 * 347 * @param iter_dict A valid DBusMessageIter returned from 348 * wpa_dbus_dict_open_write() 349 * @param key The key of the dict item 350 * @param value The 64-bit integer value 351 * @return TRUE on success, FALSE on failure 352 * 353 */ 354 dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict, 355 const char *key, 356 const dbus_int64_t value) 357 { 358 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT64, 359 &value); 360 } 361 362 363 /** 364 * Add a 64-bit unsigned integer entry to the dict. 365 * 366 * @param iter_dict A valid DBusMessageIter returned from 367 * wpa_dbus_dict_open_write() 368 * @param key The key of the dict item 369 * @param value The 64-bit unsigned integer value 370 * @return TRUE on success, FALSE on failure 371 * 372 */ 373 dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict, 374 const char *key, 375 const dbus_uint64_t value) 376 { 377 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT64, 378 &value); 379 } 380 381 382 /** 383 * Add a double-precision floating point entry to the dict. 384 * 385 * @param iter_dict A valid DBusMessageIter returned from 386 * wpa_dbus_dict_open_write() 387 * @param key The key of the dict item 388 * @param value The double-precision floating point value 389 * @return TRUE on success, FALSE on failure 390 * 391 */ 392 dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict, 393 const char *key, const double value) 394 { 395 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_DOUBLE, 396 &value); 397 } 398 399 400 /** 401 * Add a DBus object path entry to the dict. 402 * 403 * @param iter_dict A valid DBusMessageIter returned from 404 * wpa_dbus_dict_open_write() 405 * @param key The key of the dict item 406 * @param value The DBus object path value 407 * @return TRUE on success, FALSE on failure 408 * 409 */ 410 dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict, 411 const char *key, 412 const char *value) 413 { 414 if (!value) 415 return FALSE; 416 return _wpa_dbus_add_dict_entry_basic(iter_dict, key, 417 DBUS_TYPE_OBJECT_PATH, &value); 418 } 419 420 421 /** 422 * Add a byte array entry to the dict. 423 * 424 * @param iter_dict A valid DBusMessageIter returned from 425 * wpa_dbus_dict_open_write() 426 * @param key The key of the dict item 427 * @param value The byte array 428 * @param value_len The length of the byte array, in bytes 429 * @return TRUE on success, FALSE on failure 430 * 431 */ 432 dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict, 433 const char *key, 434 const char *value, 435 const dbus_uint32_t value_len) 436 { 437 if (!key) 438 return FALSE; 439 if (!value && (value_len != 0)) 440 return FALSE; 441 return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value, 442 value_len); 443 } 444 445 446 /** 447 * Begin an array entry in the dict 448 * 449 * @param iter_dict A valid DBusMessageIter returned from 450 * wpa_dbus_dict_open_write() 451 * @param key The key of the dict item 452 * @param type The type of the contained data 453 * @param iter_dict_entry A private DBusMessageIter provided by the caller to 454 * be passed to wpa_dbus_dict_end_string_array() 455 * @param iter_dict_val A private DBusMessageIter provided by the caller to 456 * be passed to wpa_dbus_dict_end_string_array() 457 * @param iter_array On return, the DBusMessageIter to be passed to 458 * wpa_dbus_dict_string_array_add_element() 459 * @return TRUE on success, FALSE on failure 460 * 461 */ 462 dbus_bool_t wpa_dbus_dict_begin_array(DBusMessageIter *iter_dict, 463 const char *key, const char *type, 464 DBusMessageIter *iter_dict_entry, 465 DBusMessageIter *iter_dict_val, 466 DBusMessageIter *iter_array) 467 { 468 char array_type[10]; 469 int err; 470 471 err = os_snprintf(array_type, sizeof(array_type), 472 DBUS_TYPE_ARRAY_AS_STRING "%s", 473 type); 474 if (err < 0 || err > (int) sizeof(array_type)) 475 return FALSE; 476 477 if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array) 478 return FALSE; 479 480 if (!_wpa_dbus_add_dict_entry_start(iter_dict, iter_dict_entry, 481 key, DBUS_TYPE_ARRAY)) 482 return FALSE; 483 484 if (!dbus_message_iter_open_container(iter_dict_entry, 485 DBUS_TYPE_VARIANT, 486 array_type, 487 iter_dict_val)) 488 return FALSE; 489 490 if (!dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY, 491 type, iter_array)) 492 return FALSE; 493 494 return TRUE; 495 } 496 497 498 dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict, 499 const char *key, 500 DBusMessageIter *iter_dict_entry, 501 DBusMessageIter *iter_dict_val, 502 DBusMessageIter *iter_array) 503 { 504 return wpa_dbus_dict_begin_array( 505 iter_dict, key, 506 DBUS_TYPE_STRING_AS_STRING, 507 iter_dict_entry, iter_dict_val, iter_array); 508 } 509 510 511 /** 512 * Add a single string element to a string array dict entry 513 * 514 * @param iter_array A valid DBusMessageIter returned from 515 * wpa_dbus_dict_begin_string_array()'s 516 * iter_array parameter 517 * @param elem The string element to be added to the dict entry's string array 518 * @return TRUE on success, FALSE on failure 519 * 520 */ 521 dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array, 522 const char *elem) 523 { 524 if (!iter_array || !elem) 525 return FALSE; 526 527 return dbus_message_iter_append_basic(iter_array, DBUS_TYPE_STRING, 528 &elem); 529 } 530 531 532 /** 533 * Add a single byte array element to a string array dict entry 534 * 535 * @param iter_array A valid DBusMessageIter returned from 536 * wpa_dbus_dict_begin_array()'s iter_array 537 * parameter -- note that wpa_dbus_dict_begin_array() 538 * must have been called with "ay" as the type 539 * @param value The data to be added to the dict entry's array 540 * @param value_len The length of the data 541 * @return TRUE on success, FALSE on failure 542 * 543 */ 544 dbus_bool_t wpa_dbus_dict_bin_array_add_element(DBusMessageIter *iter_array, 545 const u8 *value, 546 size_t value_len) 547 { 548 DBusMessageIter iter_bytes; 549 size_t i; 550 551 if (!iter_array || !value) 552 return FALSE; 553 554 if (!dbus_message_iter_open_container(iter_array, DBUS_TYPE_ARRAY, 555 DBUS_TYPE_BYTE_AS_STRING, 556 &iter_bytes)) 557 return FALSE; 558 559 for (i = 0; i < value_len; i++) { 560 if (!dbus_message_iter_append_basic(&iter_bytes, 561 DBUS_TYPE_BYTE, 562 &(value[i]))) 563 return FALSE; 564 } 565 566 if (!dbus_message_iter_close_container(iter_array, &iter_bytes)) 567 return FALSE; 568 569 return TRUE; 570 } 571 572 573 /** 574 * End an array dict entry 575 * 576 * @param iter_dict A valid DBusMessageIter returned from 577 * wpa_dbus_dict_open_write() 578 * @param iter_dict_entry A private DBusMessageIter returned from 579 * wpa_dbus_dict_begin_string_array() or 580 * wpa_dbus_dict_begin_array() 581 * @param iter_dict_val A private DBusMessageIter returned from 582 * wpa_dbus_dict_begin_string_array() or 583 * wpa_dbus_dict_begin_array() 584 * @param iter_array A DBusMessageIter returned from 585 * wpa_dbus_dict_begin_string_array() or 586 * wpa_dbus_dict_begin_array() 587 * @return TRUE on success, FALSE on failure 588 * 589 */ 590 dbus_bool_t wpa_dbus_dict_end_array(DBusMessageIter *iter_dict, 591 DBusMessageIter *iter_dict_entry, 592 DBusMessageIter *iter_dict_val, 593 DBusMessageIter *iter_array) 594 { 595 if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array) 596 return FALSE; 597 598 if (!dbus_message_iter_close_container(iter_dict_val, iter_array)) 599 return FALSE; 600 601 if (!_wpa_dbus_add_dict_entry_end(iter_dict, iter_dict_entry, 602 iter_dict_val)) 603 return FALSE; 604 605 return TRUE; 606 } 607 608 609 /** 610 * Convenience function to add an entire string array to the dict. 611 * 612 * @param iter_dict A valid DBusMessageIter returned from 613 * wpa_dbus_dict_open_write() 614 * @param key The key of the dict item 615 * @param items The array of strings 616 * @param num_items The number of strings in the array 617 * @return TRUE on success, FALSE on failure 618 * 619 */ 620 dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict, 621 const char *key, 622 const char **items, 623 const dbus_uint32_t num_items) 624 { 625 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; 626 dbus_uint32_t i; 627 628 if (!key) 629 return FALSE; 630 if (!items && (num_items != 0)) 631 return FALSE; 632 633 if (!wpa_dbus_dict_begin_string_array(iter_dict, key, 634 &iter_dict_entry, &iter_dict_val, 635 &iter_array)) 636 return FALSE; 637 638 for (i = 0; i < num_items; i++) { 639 if (!wpa_dbus_dict_string_array_add_element(&iter_array, 640 items[i])) 641 return FALSE; 642 } 643 644 if (!wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry, 645 &iter_dict_val, &iter_array)) 646 return FALSE; 647 648 return TRUE; 649 } 650 651 652 /** 653 * Convenience function to add an wpabuf binary array to the dict. 654 * 655 * @param iter_dict A valid DBusMessageIter returned from 656 * wpa_dbus_dict_open_write() 657 * @param key The key of the dict item 658 * @param items The array of wpabuf structures 659 * @param num_items The number of strings in the array 660 * @return TRUE on success, FALSE on failure 661 * 662 */ 663 dbus_bool_t wpa_dbus_dict_append_wpabuf_array(DBusMessageIter *iter_dict, 664 const char *key, 665 const struct wpabuf **items, 666 const dbus_uint32_t num_items) 667 { 668 DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; 669 dbus_uint32_t i; 670 671 if (!key) 672 return FALSE; 673 if (!items && (num_items != 0)) 674 return FALSE; 675 676 if (!wpa_dbus_dict_begin_array(iter_dict, key, 677 DBUS_TYPE_ARRAY_AS_STRING 678 DBUS_TYPE_BYTE_AS_STRING, 679 &iter_dict_entry, &iter_dict_val, 680 &iter_array)) 681 return FALSE; 682 683 for (i = 0; i < num_items; i++) { 684 if (!wpa_dbus_dict_bin_array_add_element(&iter_array, 685 wpabuf_head(items[i]), 686 wpabuf_len(items[i]))) 687 return FALSE; 688 } 689 690 if (!wpa_dbus_dict_end_array(iter_dict, &iter_dict_entry, 691 &iter_dict_val, &iter_array)) 692 return FALSE; 693 694 return TRUE; 695 } 696 697 698 /*****************************************************/ 699 /* Stuff for reading dicts */ 700 /*****************************************************/ 701 702 /** 703 * Start reading from a dbus dict. 704 * 705 * @param iter A valid DBusMessageIter pointing to the start of the dict 706 * @param iter_dict (out) A DBusMessageIter to be passed to 707 * wpa_dbus_dict_read_next_entry() 708 * @return TRUE on success, FALSE on failure 709 * 710 */ 711 dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter, 712 DBusMessageIter *iter_dict) 713 { 714 if (!iter || !iter_dict) 715 return FALSE; 716 717 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY || 718 dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY) 719 return FALSE; 720 721 dbus_message_iter_recurse(iter, iter_dict); 722 return TRUE; 723 } 724 725 726 #define BYTE_ARRAY_CHUNK_SIZE 34 727 #define BYTE_ARRAY_ITEM_SIZE (sizeof(char)) 728 729 static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array( 730 DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry) 731 { 732 dbus_uint32_t count = 0; 733 dbus_bool_t success = FALSE; 734 char *buffer, *nbuffer;; 735 736 entry->bytearray_value = NULL; 737 entry->array_type = DBUS_TYPE_BYTE; 738 739 buffer = os_zalloc(BYTE_ARRAY_ITEM_SIZE * BYTE_ARRAY_CHUNK_SIZE); 740 if (!buffer) 741 return FALSE; 742 743 entry->bytearray_value = buffer; 744 entry->array_len = 0; 745 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) { 746 char byte; 747 748 if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) { 749 nbuffer = os_realloc(buffer, BYTE_ARRAY_ITEM_SIZE * 750 (count + BYTE_ARRAY_CHUNK_SIZE)); 751 if (nbuffer == NULL) { 752 os_free(buffer); 753 wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_" 754 "entry_get_byte_array out of " 755 "memory trying to retrieve the " 756 "string array"); 757 goto done; 758 } 759 buffer = nbuffer; 760 } 761 entry->bytearray_value = buffer; 762 763 dbus_message_iter_get_basic(iter, &byte); 764 entry->bytearray_value[count] = byte; 765 entry->array_len = ++count; 766 dbus_message_iter_next(iter); 767 } 768 769 /* Zero-length arrays are valid. */ 770 if (entry->array_len == 0) { 771 os_free(entry->bytearray_value); 772 entry->bytearray_value = NULL; 773 } 774 775 success = TRUE; 776 777 done: 778 return success; 779 } 780 781 782 #define STR_ARRAY_CHUNK_SIZE 8 783 #define STR_ARRAY_ITEM_SIZE (sizeof(char *)) 784 785 static dbus_bool_t _wpa_dbus_dict_entry_get_string_array( 786 DBusMessageIter *iter, int array_type, 787 struct wpa_dbus_dict_entry *entry) 788 { 789 dbus_uint32_t count = 0; 790 dbus_bool_t success = FALSE; 791 char **buffer, **nbuffer; 792 793 entry->strarray_value = NULL; 794 entry->array_type = DBUS_TYPE_STRING; 795 796 buffer = os_zalloc(STR_ARRAY_ITEM_SIZE * STR_ARRAY_CHUNK_SIZE); 797 if (buffer == NULL) 798 return FALSE; 799 800 entry->strarray_value = buffer; 801 entry->array_len = 0; 802 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) { 803 const char *value; 804 char *str; 805 806 if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) { 807 nbuffer = os_realloc(buffer, STR_ARRAY_ITEM_SIZE * 808 (count + STR_ARRAY_CHUNK_SIZE)); 809 if (nbuffer == NULL) { 810 os_free(buffer); 811 wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_" 812 "entry_get_string_array out of " 813 "memory trying to retrieve the " 814 "string array"); 815 goto done; 816 } 817 buffer = nbuffer; 818 } 819 entry->strarray_value = buffer; 820 821 dbus_message_iter_get_basic(iter, &value); 822 str = os_strdup(value); 823 if (str == NULL) { 824 wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_entry_get_" 825 "string_array out of memory trying to " 826 "duplicate the string array"); 827 goto done; 828 } 829 entry->strarray_value[count] = str; 830 entry->array_len = ++count; 831 dbus_message_iter_next(iter); 832 } 833 834 /* Zero-length arrays are valid. */ 835 if (entry->array_len == 0) { 836 os_free(entry->strarray_value); 837 entry->strarray_value = NULL; 838 } 839 840 success = TRUE; 841 842 done: 843 return success; 844 } 845 846 847 #define BIN_ARRAY_CHUNK_SIZE 10 848 #define BIN_ARRAY_ITEM_SIZE (sizeof(struct wpabuf *)) 849 850 static dbus_bool_t _wpa_dbus_dict_entry_get_binarray( 851 DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry) 852 { 853 struct wpa_dbus_dict_entry tmpentry; 854 size_t buflen = 0; 855 int i; 856 857 if (dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE) 858 return FALSE; 859 860 entry->array_type = WPAS_DBUS_TYPE_BINARRAY; 861 entry->array_len = 0; 862 entry->binarray_value = NULL; 863 864 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) { 865 DBusMessageIter iter_array; 866 867 if (entry->array_len == buflen) { 868 struct wpabuf **newbuf; 869 870 buflen += BIN_ARRAY_CHUNK_SIZE; 871 872 newbuf = os_realloc(entry->binarray_value, 873 buflen * BIN_ARRAY_ITEM_SIZE); 874 if (!newbuf) 875 goto cleanup; 876 entry->binarray_value = newbuf; 877 } 878 879 dbus_message_iter_recurse(iter, &iter_array); 880 if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry) 881 == FALSE) 882 goto cleanup; 883 884 entry->binarray_value[entry->array_len] = 885 wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value, 886 tmpentry.array_len); 887 if (entry->binarray_value[entry->array_len] == NULL) { 888 wpa_dbus_dict_entry_clear(&tmpentry); 889 goto cleanup; 890 } 891 entry->array_len++; 892 dbus_message_iter_next(iter); 893 } 894 895 return TRUE; 896 897 cleanup: 898 for (i = 0; i < (int) entry->array_len; i++) 899 wpabuf_free(entry->binarray_value[i]); 900 os_free(entry->binarray_value); 901 entry->array_len = 0; 902 entry->binarray_value = NULL; 903 return FALSE; 904 } 905 906 907 static dbus_bool_t _wpa_dbus_dict_entry_get_array( 908 DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry) 909 { 910 int array_type = dbus_message_iter_get_element_type(iter_dict_val); 911 dbus_bool_t success = FALSE; 912 DBusMessageIter iter_array; 913 914 if (!entry) 915 return FALSE; 916 917 dbus_message_iter_recurse(iter_dict_val, &iter_array); 918 919 switch (array_type) { 920 case DBUS_TYPE_BYTE: 921 success = _wpa_dbus_dict_entry_get_byte_array(&iter_array, 922 entry); 923 break; 924 case DBUS_TYPE_STRING: 925 success = _wpa_dbus_dict_entry_get_string_array(&iter_array, 926 array_type, 927 entry); 928 break; 929 case DBUS_TYPE_ARRAY: 930 success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry); 931 default: 932 break; 933 } 934 935 return success; 936 } 937 938 939 static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant( 940 struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter) 941 { 942 const char *v; 943 944 switch (entry->type) { 945 case DBUS_TYPE_OBJECT_PATH: 946 case DBUS_TYPE_STRING: 947 dbus_message_iter_get_basic(iter, &v); 948 entry->str_value = os_strdup(v); 949 if (entry->str_value == NULL) 950 return FALSE; 951 break; 952 case DBUS_TYPE_BOOLEAN: 953 dbus_message_iter_get_basic(iter, &entry->bool_value); 954 break; 955 case DBUS_TYPE_BYTE: 956 dbus_message_iter_get_basic(iter, &entry->byte_value); 957 break; 958 case DBUS_TYPE_INT16: 959 dbus_message_iter_get_basic(iter, &entry->int16_value); 960 break; 961 case DBUS_TYPE_UINT16: 962 dbus_message_iter_get_basic(iter, &entry->uint16_value); 963 break; 964 case DBUS_TYPE_INT32: 965 dbus_message_iter_get_basic(iter, &entry->int32_value); 966 break; 967 case DBUS_TYPE_UINT32: 968 dbus_message_iter_get_basic(iter, &entry->uint32_value); 969 break; 970 case DBUS_TYPE_INT64: 971 dbus_message_iter_get_basic(iter, &entry->int64_value); 972 break; 973 case DBUS_TYPE_UINT64: 974 dbus_message_iter_get_basic(iter, &entry->uint64_value); 975 break; 976 case DBUS_TYPE_DOUBLE: 977 dbus_message_iter_get_basic(iter, &entry->double_value); 978 break; 979 case DBUS_TYPE_ARRAY: 980 return _wpa_dbus_dict_entry_get_array(iter, entry); 981 default: 982 return FALSE; 983 } 984 985 return TRUE; 986 } 987 988 989 /** 990 * Read the current key/value entry from the dict. Entries are dynamically 991 * allocated when needed and must be freed after use with the 992 * wpa_dbus_dict_entry_clear() function. 993 * 994 * The returned entry object will be filled with the type and value of the next 995 * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error 996 * occurred. 997 * 998 * @param iter_dict A valid DBusMessageIter returned from 999 * wpa_dbus_dict_open_read() 1000 * @param entry A valid dict entry object into which the dict key and value 1001 * will be placed 1002 * @return TRUE on success, FALSE on failure 1003 * 1004 */ 1005 dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict, 1006 struct wpa_dbus_dict_entry * entry) 1007 { 1008 DBusMessageIter iter_dict_entry, iter_dict_val; 1009 int type; 1010 const char *key; 1011 1012 if (!iter_dict || !entry) 1013 goto error; 1014 1015 if (dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY) 1016 goto error; 1017 1018 dbus_message_iter_recurse(iter_dict, &iter_dict_entry); 1019 dbus_message_iter_get_basic(&iter_dict_entry, &key); 1020 entry->key = key; 1021 1022 if (!dbus_message_iter_next(&iter_dict_entry)) 1023 goto error; 1024 type = dbus_message_iter_get_arg_type(&iter_dict_entry); 1025 if (type != DBUS_TYPE_VARIANT) 1026 goto error; 1027 1028 dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val); 1029 entry->type = dbus_message_iter_get_arg_type(&iter_dict_val); 1030 if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val)) 1031 goto error; 1032 1033 dbus_message_iter_next(iter_dict); 1034 return TRUE; 1035 1036 error: 1037 if (entry) { 1038 wpa_dbus_dict_entry_clear(entry); 1039 entry->type = DBUS_TYPE_INVALID; 1040 entry->array_type = DBUS_TYPE_INVALID; 1041 } 1042 1043 return FALSE; 1044 } 1045 1046 1047 /** 1048 * Return whether or not there are additional dictionary entries. 1049 * 1050 * @param iter_dict A valid DBusMessageIter returned from 1051 * wpa_dbus_dict_open_read() 1052 * @return TRUE if more dict entries exists, FALSE if no more dict entries 1053 * exist 1054 */ 1055 dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict) 1056 { 1057 if (!iter_dict) 1058 return FALSE; 1059 return dbus_message_iter_get_arg_type(iter_dict) == 1060 DBUS_TYPE_DICT_ENTRY; 1061 } 1062 1063 1064 /** 1065 * Free any memory used by the entry object. 1066 * 1067 * @param entry The entry object 1068 */ 1069 void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry) 1070 { 1071 unsigned int i; 1072 1073 if (!entry) 1074 return; 1075 switch (entry->type) { 1076 case DBUS_TYPE_OBJECT_PATH: 1077 case DBUS_TYPE_STRING: 1078 os_free(entry->str_value); 1079 break; 1080 case DBUS_TYPE_ARRAY: 1081 switch (entry->array_type) { 1082 case DBUS_TYPE_BYTE: 1083 os_free(entry->bytearray_value); 1084 break; 1085 case DBUS_TYPE_STRING: 1086 for (i = 0; i < entry->array_len; i++) 1087 os_free(entry->strarray_value[i]); 1088 os_free(entry->strarray_value); 1089 break; 1090 } 1091 break; 1092 case WPAS_DBUS_TYPE_BINARRAY: 1093 for (i = 0; i < entry->array_len; i++) 1094 wpabuf_free(entry->binarray_value[i]); 1095 os_free(entry->binarray_value); 1096 break; 1097 } 1098 1099 memset(entry, 0, sizeof(struct wpa_dbus_dict_entry)); 1100 } 1101