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