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