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