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