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 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 */ 26 dbus_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 */ 57 dbus_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 67 const 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 100 static 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 117 static 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 130 static 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 165 static 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 */ 216 dbus_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 */ 236 dbus_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 */ 254 dbus_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 */ 272 dbus_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 */ 291 dbus_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 */ 310 dbus_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 */ 329 dbus_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 */ 348 dbus_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 */ 367 dbus_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 */ 386 dbus_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 */ 404 dbus_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 */ 426 dbus_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 */ 456 dbus_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 492 dbus_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 */ 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 * 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 */ 538 dbus_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 */ 584 dbus_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 */ 614 dbus_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 */ 657 dbus_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 */ 706 dbus_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 731 static 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_calloc(BYTE_ARRAY_CHUNK_SIZE, BYTE_ARRAY_ITEM_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_array( 752 buffer, count + BYTE_ARRAY_CHUNK_SIZE, 753 BYTE_ARRAY_ITEM_SIZE); 754 if (nbuffer == NULL) { 755 os_free(buffer); 756 wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_" 757 "entry_get_byte_array out of " 758 "memory trying to retrieve the " 759 "string array"); 760 goto done; 761 } 762 buffer = nbuffer; 763 } 764 entry->bytearray_value = buffer; 765 766 dbus_message_iter_get_basic(iter, &byte); 767 entry->bytearray_value[count] = byte; 768 entry->array_len = ++count; 769 dbus_message_iter_next(iter); 770 } 771 772 /* Zero-length arrays are valid. */ 773 if (entry->array_len == 0) { 774 os_free(entry->bytearray_value); 775 entry->bytearray_value = NULL; 776 } 777 778 success = TRUE; 779 780 done: 781 return success; 782 } 783 784 785 #define STR_ARRAY_CHUNK_SIZE 8 786 #define STR_ARRAY_ITEM_SIZE (sizeof(char *)) 787 788 static dbus_bool_t _wpa_dbus_dict_entry_get_string_array( 789 DBusMessageIter *iter, int array_type, 790 struct wpa_dbus_dict_entry *entry) 791 { 792 dbus_uint32_t count = 0; 793 dbus_bool_t success = FALSE; 794 char **buffer, **nbuffer; 795 796 entry->strarray_value = NULL; 797 entry->array_type = DBUS_TYPE_STRING; 798 799 buffer = os_calloc(STR_ARRAY_CHUNK_SIZE, STR_ARRAY_ITEM_SIZE); 800 if (buffer == NULL) 801 return FALSE; 802 803 entry->strarray_value = buffer; 804 entry->array_len = 0; 805 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) { 806 const char *value; 807 char *str; 808 809 if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) { 810 nbuffer = os_realloc_array( 811 buffer, count + STR_ARRAY_CHUNK_SIZE, 812 STR_ARRAY_ITEM_SIZE); 813 if (nbuffer == NULL) { 814 os_free(buffer); 815 wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_" 816 "entry_get_string_array out of " 817 "memory trying to retrieve the " 818 "string array"); 819 goto done; 820 } 821 buffer = nbuffer; 822 } 823 entry->strarray_value = buffer; 824 825 dbus_message_iter_get_basic(iter, &value); 826 str = os_strdup(value); 827 if (str == NULL) { 828 wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_entry_get_" 829 "string_array out of memory trying to " 830 "duplicate the string array"); 831 goto done; 832 } 833 entry->strarray_value[count] = str; 834 entry->array_len = ++count; 835 dbus_message_iter_next(iter); 836 } 837 838 /* Zero-length arrays are valid. */ 839 if (entry->array_len == 0) { 840 os_free(entry->strarray_value); 841 entry->strarray_value = NULL; 842 } 843 844 success = TRUE; 845 846 done: 847 return success; 848 } 849 850 851 #define BIN_ARRAY_CHUNK_SIZE 10 852 #define BIN_ARRAY_ITEM_SIZE (sizeof(struct wpabuf *)) 853 854 static dbus_bool_t _wpa_dbus_dict_entry_get_binarray( 855 DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry) 856 { 857 struct wpa_dbus_dict_entry tmpentry; 858 size_t buflen = 0; 859 int i; 860 861 if (dbus_message_iter_get_element_type(iter) != DBUS_TYPE_BYTE) 862 return FALSE; 863 864 entry->array_type = WPAS_DBUS_TYPE_BINARRAY; 865 entry->array_len = 0; 866 entry->binarray_value = NULL; 867 868 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) { 869 DBusMessageIter iter_array; 870 871 if (entry->array_len == buflen) { 872 struct wpabuf **newbuf; 873 874 buflen += BIN_ARRAY_CHUNK_SIZE; 875 876 newbuf = os_realloc_array(entry->binarray_value, 877 buflen, BIN_ARRAY_ITEM_SIZE); 878 if (!newbuf) 879 goto cleanup; 880 entry->binarray_value = newbuf; 881 } 882 883 dbus_message_iter_recurse(iter, &iter_array); 884 if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry) 885 == FALSE) 886 goto cleanup; 887 888 entry->binarray_value[entry->array_len] = 889 wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value, 890 tmpentry.array_len); 891 if (entry->binarray_value[entry->array_len] == NULL) { 892 wpa_dbus_dict_entry_clear(&tmpentry); 893 goto cleanup; 894 } 895 entry->array_len++; 896 dbus_message_iter_next(iter); 897 } 898 899 return TRUE; 900 901 cleanup: 902 for (i = 0; i < (int) entry->array_len; i++) 903 wpabuf_free(entry->binarray_value[i]); 904 os_free(entry->binarray_value); 905 entry->array_len = 0; 906 entry->binarray_value = NULL; 907 return FALSE; 908 } 909 910 911 static dbus_bool_t _wpa_dbus_dict_entry_get_array( 912 DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry) 913 { 914 int array_type = dbus_message_iter_get_element_type(iter_dict_val); 915 dbus_bool_t success = FALSE; 916 DBusMessageIter iter_array; 917 918 if (!entry) 919 return FALSE; 920 921 dbus_message_iter_recurse(iter_dict_val, &iter_array); 922 923 switch (array_type) { 924 case DBUS_TYPE_BYTE: 925 success = _wpa_dbus_dict_entry_get_byte_array(&iter_array, 926 entry); 927 break; 928 case DBUS_TYPE_STRING: 929 success = _wpa_dbus_dict_entry_get_string_array(&iter_array, 930 array_type, 931 entry); 932 break; 933 case DBUS_TYPE_ARRAY: 934 success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry); 935 default: 936 break; 937 } 938 939 return success; 940 } 941 942 943 static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant( 944 struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter) 945 { 946 const char *v; 947 948 switch (entry->type) { 949 case DBUS_TYPE_OBJECT_PATH: 950 case DBUS_TYPE_STRING: 951 dbus_message_iter_get_basic(iter, &v); 952 entry->str_value = os_strdup(v); 953 if (entry->str_value == NULL) 954 return FALSE; 955 break; 956 case DBUS_TYPE_BOOLEAN: 957 dbus_message_iter_get_basic(iter, &entry->bool_value); 958 break; 959 case DBUS_TYPE_BYTE: 960 dbus_message_iter_get_basic(iter, &entry->byte_value); 961 break; 962 case DBUS_TYPE_INT16: 963 dbus_message_iter_get_basic(iter, &entry->int16_value); 964 break; 965 case DBUS_TYPE_UINT16: 966 dbus_message_iter_get_basic(iter, &entry->uint16_value); 967 break; 968 case DBUS_TYPE_INT32: 969 dbus_message_iter_get_basic(iter, &entry->int32_value); 970 break; 971 case DBUS_TYPE_UINT32: 972 dbus_message_iter_get_basic(iter, &entry->uint32_value); 973 break; 974 case DBUS_TYPE_INT64: 975 dbus_message_iter_get_basic(iter, &entry->int64_value); 976 break; 977 case DBUS_TYPE_UINT64: 978 dbus_message_iter_get_basic(iter, &entry->uint64_value); 979 break; 980 case DBUS_TYPE_DOUBLE: 981 dbus_message_iter_get_basic(iter, &entry->double_value); 982 break; 983 case DBUS_TYPE_ARRAY: 984 return _wpa_dbus_dict_entry_get_array(iter, entry); 985 default: 986 return FALSE; 987 } 988 989 return TRUE; 990 } 991 992 993 /** 994 * Read the current key/value entry from the dict. Entries are dynamically 995 * allocated when needed and must be freed after use with the 996 * wpa_dbus_dict_entry_clear() function. 997 * 998 * The returned entry object will be filled with the type and value of the next 999 * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error 1000 * occurred. 1001 * 1002 * @param iter_dict A valid DBusMessageIter returned from 1003 * wpa_dbus_dict_open_read() 1004 * @param entry A valid dict entry object into which the dict key and value 1005 * will be placed 1006 * @return TRUE on success, FALSE on failure 1007 * 1008 */ 1009 dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict, 1010 struct wpa_dbus_dict_entry * entry) 1011 { 1012 DBusMessageIter iter_dict_entry, iter_dict_val; 1013 int type; 1014 const char *key; 1015 1016 if (!iter_dict || !entry) 1017 goto error; 1018 1019 if (dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY) 1020 goto error; 1021 1022 dbus_message_iter_recurse(iter_dict, &iter_dict_entry); 1023 dbus_message_iter_get_basic(&iter_dict_entry, &key); 1024 entry->key = key; 1025 1026 if (!dbus_message_iter_next(&iter_dict_entry)) 1027 goto error; 1028 type = dbus_message_iter_get_arg_type(&iter_dict_entry); 1029 if (type != DBUS_TYPE_VARIANT) 1030 goto error; 1031 1032 dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val); 1033 entry->type = dbus_message_iter_get_arg_type(&iter_dict_val); 1034 if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val)) 1035 goto error; 1036 1037 dbus_message_iter_next(iter_dict); 1038 return TRUE; 1039 1040 error: 1041 if (entry) { 1042 wpa_dbus_dict_entry_clear(entry); 1043 entry->type = DBUS_TYPE_INVALID; 1044 entry->array_type = DBUS_TYPE_INVALID; 1045 } 1046 1047 return FALSE; 1048 } 1049 1050 1051 /** 1052 * Return whether or not there are additional dictionary entries. 1053 * 1054 * @param iter_dict A valid DBusMessageIter returned from 1055 * wpa_dbus_dict_open_read() 1056 * @return TRUE if more dict entries exists, FALSE if no more dict entries 1057 * exist 1058 */ 1059 dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict) 1060 { 1061 if (!iter_dict) 1062 return FALSE; 1063 return dbus_message_iter_get_arg_type(iter_dict) == 1064 DBUS_TYPE_DICT_ENTRY; 1065 } 1066 1067 1068 /** 1069 * Free any memory used by the entry object. 1070 * 1071 * @param entry The entry object 1072 */ 1073 void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry) 1074 { 1075 unsigned int i; 1076 1077 if (!entry) 1078 return; 1079 switch (entry->type) { 1080 case DBUS_TYPE_OBJECT_PATH: 1081 case DBUS_TYPE_STRING: 1082 os_free(entry->str_value); 1083 break; 1084 case DBUS_TYPE_ARRAY: 1085 switch (entry->array_type) { 1086 case DBUS_TYPE_BYTE: 1087 os_free(entry->bytearray_value); 1088 break; 1089 case DBUS_TYPE_STRING: 1090 for (i = 0; i < entry->array_len; i++) 1091 os_free(entry->strarray_value[i]); 1092 os_free(entry->strarray_value); 1093 break; 1094 case WPAS_DBUS_TYPE_BINARRAY: 1095 for (i = 0; i < entry->array_len; i++) 1096 wpabuf_free(entry->binarray_value[i]); 1097 os_free(entry->binarray_value); 1098 break; 1099 } 1100 break; 1101 } 1102 1103 os_memset(entry, 0, sizeof(struct wpa_dbus_dict_entry)); 1104 } 1105