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