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 os_memset(&tmpentry, 0, sizeof(tmpentry)); 885 tmpentry.type = DBUS_TYPE_ARRAY; 886 if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry) 887 == FALSE) 888 goto cleanup; 889 890 entry->binarray_value[entry->array_len] = 891 wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value, 892 tmpentry.array_len); 893 if (entry->binarray_value[entry->array_len] == NULL) { 894 wpa_dbus_dict_entry_clear(&tmpentry); 895 goto cleanup; 896 } 897 entry->array_len++; 898 dbus_message_iter_next(iter); 899 } 900 901 return TRUE; 902 903 cleanup: 904 for (i = 0; i < (int) entry->array_len; i++) 905 wpabuf_free(entry->binarray_value[i]); 906 os_free(entry->binarray_value); 907 entry->array_len = 0; 908 entry->binarray_value = NULL; 909 return FALSE; 910 } 911 912 913 static dbus_bool_t _wpa_dbus_dict_entry_get_array( 914 DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry) 915 { 916 int array_type = dbus_message_iter_get_element_type(iter_dict_val); 917 dbus_bool_t success = FALSE; 918 DBusMessageIter iter_array; 919 920 if (!entry) 921 return FALSE; 922 923 dbus_message_iter_recurse(iter_dict_val, &iter_array); 924 925 switch (array_type) { 926 case DBUS_TYPE_BYTE: 927 success = _wpa_dbus_dict_entry_get_byte_array(&iter_array, 928 entry); 929 break; 930 case DBUS_TYPE_STRING: 931 success = _wpa_dbus_dict_entry_get_string_array(&iter_array, 932 array_type, 933 entry); 934 break; 935 case DBUS_TYPE_ARRAY: 936 success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry); 937 break; 938 default: 939 break; 940 } 941 942 return success; 943 } 944 945 946 static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant( 947 struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter) 948 { 949 const char *v; 950 951 switch (entry->type) { 952 case DBUS_TYPE_OBJECT_PATH: 953 case DBUS_TYPE_STRING: 954 dbus_message_iter_get_basic(iter, &v); 955 entry->str_value = os_strdup(v); 956 if (entry->str_value == NULL) 957 return FALSE; 958 break; 959 case DBUS_TYPE_BOOLEAN: 960 dbus_message_iter_get_basic(iter, &entry->bool_value); 961 break; 962 case DBUS_TYPE_BYTE: 963 dbus_message_iter_get_basic(iter, &entry->byte_value); 964 break; 965 case DBUS_TYPE_INT16: 966 dbus_message_iter_get_basic(iter, &entry->int16_value); 967 break; 968 case DBUS_TYPE_UINT16: 969 dbus_message_iter_get_basic(iter, &entry->uint16_value); 970 break; 971 case DBUS_TYPE_INT32: 972 dbus_message_iter_get_basic(iter, &entry->int32_value); 973 break; 974 case DBUS_TYPE_UINT32: 975 dbus_message_iter_get_basic(iter, &entry->uint32_value); 976 break; 977 case DBUS_TYPE_INT64: 978 dbus_message_iter_get_basic(iter, &entry->int64_value); 979 break; 980 case DBUS_TYPE_UINT64: 981 dbus_message_iter_get_basic(iter, &entry->uint64_value); 982 break; 983 case DBUS_TYPE_DOUBLE: 984 dbus_message_iter_get_basic(iter, &entry->double_value); 985 break; 986 case DBUS_TYPE_ARRAY: 987 return _wpa_dbus_dict_entry_get_array(iter, entry); 988 default: 989 return FALSE; 990 } 991 992 return TRUE; 993 } 994 995 996 /** 997 * Read the current key/value entry from the dict. Entries are dynamically 998 * allocated when needed and must be freed after use with the 999 * wpa_dbus_dict_entry_clear() function. 1000 * 1001 * The returned entry object will be filled with the type and value of the next 1002 * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error 1003 * occurred. 1004 * 1005 * @param iter_dict A valid DBusMessageIter returned from 1006 * wpa_dbus_dict_open_read() 1007 * @param entry A valid dict entry object into which the dict key and value 1008 * will be placed 1009 * @return TRUE on success, FALSE on failure 1010 * 1011 */ 1012 dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict, 1013 struct wpa_dbus_dict_entry * entry) 1014 { 1015 DBusMessageIter iter_dict_entry, iter_dict_val; 1016 int type; 1017 const char *key; 1018 1019 if (!iter_dict || !entry) 1020 goto error; 1021 1022 if (dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY) 1023 goto error; 1024 1025 dbus_message_iter_recurse(iter_dict, &iter_dict_entry); 1026 dbus_message_iter_get_basic(&iter_dict_entry, &key); 1027 entry->key = key; 1028 1029 if (!dbus_message_iter_next(&iter_dict_entry)) 1030 goto error; 1031 type = dbus_message_iter_get_arg_type(&iter_dict_entry); 1032 if (type != DBUS_TYPE_VARIANT) 1033 goto error; 1034 1035 dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val); 1036 entry->type = dbus_message_iter_get_arg_type(&iter_dict_val); 1037 if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val)) 1038 goto error; 1039 1040 dbus_message_iter_next(iter_dict); 1041 return TRUE; 1042 1043 error: 1044 if (entry) { 1045 wpa_dbus_dict_entry_clear(entry); 1046 entry->type = DBUS_TYPE_INVALID; 1047 entry->array_type = DBUS_TYPE_INVALID; 1048 } 1049 1050 return FALSE; 1051 } 1052 1053 1054 /** 1055 * Return whether or not there are additional dictionary entries. 1056 * 1057 * @param iter_dict A valid DBusMessageIter returned from 1058 * wpa_dbus_dict_open_read() 1059 * @return TRUE if more dict entries exists, FALSE if no more dict entries 1060 * exist 1061 */ 1062 dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict) 1063 { 1064 if (!iter_dict) 1065 return FALSE; 1066 return dbus_message_iter_get_arg_type(iter_dict) == 1067 DBUS_TYPE_DICT_ENTRY; 1068 } 1069 1070 1071 /** 1072 * Free any memory used by the entry object. 1073 * 1074 * @param entry The entry object 1075 */ 1076 void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry) 1077 { 1078 unsigned int i; 1079 1080 if (!entry) 1081 return; 1082 switch (entry->type) { 1083 case DBUS_TYPE_OBJECT_PATH: 1084 case DBUS_TYPE_STRING: 1085 os_free(entry->str_value); 1086 break; 1087 case DBUS_TYPE_ARRAY: 1088 switch (entry->array_type) { 1089 case DBUS_TYPE_BYTE: 1090 os_free(entry->bytearray_value); 1091 break; 1092 case DBUS_TYPE_STRING: 1093 for (i = 0; i < entry->array_len; i++) 1094 os_free(entry->strarray_value[i]); 1095 os_free(entry->strarray_value); 1096 break; 1097 case WPAS_DBUS_TYPE_BINARRAY: 1098 for (i = 0; i < entry->array_len; i++) 1099 wpabuf_free(entry->binarray_value[i]); 1100 os_free(entry->binarray_value); 1101 break; 1102 } 1103 break; 1104 } 1105 1106 os_memset(entry, 0, sizeof(struct wpa_dbus_dict_entry)); 1107 } 1108