1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2/* dbus-marshal-header.c Managing marshaling/demarshaling of message headers 3 * 4 * Copyright (C) 2005 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24#include <config.h> 25#include "dbus/dbus-shared.h" 26#include "dbus-marshal-header.h" 27#include "dbus-marshal-recursive.h" 28#include "dbus-marshal-byteswap.h" 29 30/** 31 * @addtogroup DBusMarshal 32 * 33 * @{ 34 */ 35 36 37/* Not thread locked, but strictly const/read-only so should be OK 38 */ 39/** Static #DBusString containing the signature of a message header */ 40_DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE); 41/** Static #DBusString containing the local interface */ 42_DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str, DBUS_INTERFACE_LOCAL); 43/** Static #DBusString containing the local path */ 44_DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str, DBUS_PATH_LOCAL); 45 46/** Offset from start of _dbus_header_signature_str to the signature of the fields array */ 47#define FIELDS_ARRAY_SIGNATURE_OFFSET 6 48/** Offset from start of _dbus_header_signature_str to the signature of an element of the fields array */ 49#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7 50 51 52/** Offset to byte order from start of header */ 53#define BYTE_ORDER_OFFSET 0 54/** Offset to type from start of header */ 55#define TYPE_OFFSET 1 56/** Offset to flags from start of header */ 57#define FLAGS_OFFSET 2 58/** Offset to version from start of header */ 59#define VERSION_OFFSET 3 60/** Offset to body length from start of header */ 61#define BODY_LENGTH_OFFSET 4 62/** Offset to client serial from start of header */ 63#define SERIAL_OFFSET 8 64/** Offset to fields array length from start of header */ 65#define FIELDS_ARRAY_LENGTH_OFFSET 12 66/** Offset to first field in header */ 67#define FIRST_FIELD_OFFSET 16 68 69typedef struct 70{ 71 unsigned char code; /**< the field code */ 72 unsigned char type; /**< the value type */ 73} HeaderFieldType; 74 75static const HeaderFieldType 76_dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = { 77 { DBUS_HEADER_FIELD_INVALID, DBUS_TYPE_INVALID }, 78 { DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH }, 79 { DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING }, 80 { DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING }, 81 { DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING }, 82 { DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 }, 83 { DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING }, 84 { DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING }, 85 { DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE }, 86 { DBUS_HEADER_FIELD_UNIX_FDS, DBUS_TYPE_UINT32 } 87}; 88 89/** Macro to look up the correct type for a field */ 90#define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type) 91 92/** The most padding we could ever need for a header */ 93#define MAX_POSSIBLE_HEADER_PADDING 7 94static dbus_bool_t 95reserve_header_padding (DBusHeader *header) 96{ 97 _dbus_assert (header->padding <= MAX_POSSIBLE_HEADER_PADDING); 98 99 if (!_dbus_string_lengthen (&header->data, 100 MAX_POSSIBLE_HEADER_PADDING - header->padding)) 101 return FALSE; 102 header->padding = MAX_POSSIBLE_HEADER_PADDING; 103 return TRUE; 104} 105 106static void 107correct_header_padding (DBusHeader *header) 108{ 109 int unpadded_len; 110 111 _dbus_assert (header->padding == 7); 112 113 _dbus_string_shorten (&header->data, header->padding); 114 unpadded_len = _dbus_string_get_length (&header->data); 115 116 if (!_dbus_string_align_length (&header->data, 8)) 117 _dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated"); 118 119 header->padding = _dbus_string_get_length (&header->data) - unpadded_len; 120} 121 122/** Compute the end of the header, ignoring padding */ 123#define HEADER_END_BEFORE_PADDING(header) \ 124 (_dbus_string_get_length (&(header)->data) - (header)->padding) 125 126/** 127 * Invalidates all fields in the cache. This may be used when the 128 * cache is totally uninitialized (contains junk) so should not 129 * look at what's in there now. 130 * 131 * @param header the header 132 */ 133static void 134_dbus_header_cache_invalidate_all (DBusHeader *header) 135{ 136 int i; 137 138 i = 0; 139 while (i <= DBUS_HEADER_FIELD_LAST) 140 { 141 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN; 142 ++i; 143 } 144} 145 146/** 147 * Caches one field 148 * 149 * @param header the header 150 * @param field_code the field 151 * @param variant_reader the reader for the variant in the field 152 */ 153static void 154_dbus_header_cache_one (DBusHeader *header, 155 int field_code, 156 DBusTypeReader *variant_reader) 157{ 158 header->fields[field_code].value_pos = 159 _dbus_type_reader_get_value_pos (variant_reader); 160 161#if 0 162 _dbus_verbose ("cached value_pos %d for field %d\n", 163 header->fields[field_code].value_pos, field_code) 164#endif 165} 166 167/** 168 * Returns the header's byte order. 169 * 170 * @param header the header 171 * @returns the byte order 172 */ 173char 174_dbus_header_get_byte_order (const DBusHeader *header) 175{ 176 _dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET); 177 178 return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET); 179} 180 181/** 182 * Revalidates the fields cache 183 * 184 * @param header the header 185 */ 186static void 187_dbus_header_cache_revalidate (DBusHeader *header) 188{ 189 DBusTypeReader array; 190 DBusTypeReader reader; 191 int i; 192 193 i = 0; 194 while (i <= DBUS_HEADER_FIELD_LAST) 195 { 196 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT; 197 ++i; 198 } 199 200 _dbus_type_reader_init (&reader, 201 _dbus_header_get_byte_order (header), 202 &_dbus_header_signature_str, 203 FIELDS_ARRAY_SIGNATURE_OFFSET, 204 &header->data, 205 FIELDS_ARRAY_LENGTH_OFFSET); 206 207 _dbus_type_reader_recurse (&reader, &array); 208 209 while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID) 210 { 211 DBusTypeReader sub; 212 DBusTypeReader variant; 213 unsigned char field_code; 214 215 _dbus_type_reader_recurse (&array, &sub); 216 217 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE); 218 _dbus_type_reader_read_basic (&sub, &field_code); 219 220 /* Unknown fields should be ignored */ 221 if (field_code > DBUS_HEADER_FIELD_LAST) 222 goto next_field; 223 224 _dbus_type_reader_next (&sub); 225 226 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT); 227 _dbus_type_reader_recurse (&sub, &variant); 228 229 _dbus_header_cache_one (header, field_code, &variant); 230 231 next_field: 232 _dbus_type_reader_next (&array); 233 } 234} 235 236/** 237 * Checks for a field, updating the cache if required. 238 * 239 * @param header the header 240 * @param field the field to check 241 * @returns #FALSE if the field doesn't exist 242 */ 243static dbus_bool_t 244_dbus_header_cache_check (DBusHeader *header, 245 int field) 246{ 247 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST); 248 249 if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN) 250 _dbus_header_cache_revalidate (header); 251 252 if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT) 253 return FALSE; 254 255 return TRUE; 256} 257 258/** 259 * Checks whether a field is known not to exist. It may exist 260 * even if it's not known to exist. 261 * 262 * @param header the header 263 * @param field the field to check 264 * @returns #FALSE if the field definitely doesn't exist 265 */ 266static dbus_bool_t 267_dbus_header_cache_known_nonexistent (DBusHeader *header, 268 int field) 269{ 270 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST); 271 272 return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT); 273} 274 275/** 276 * Writes a struct of { byte, variant } with the given basic type. 277 * 278 * @param writer the writer (should be ready to write a struct) 279 * @param type the type of the value 280 * @param value the value as for _dbus_marshal_set_basic() 281 * @returns #FALSE if no memory 282 */ 283static dbus_bool_t 284write_basic_field (DBusTypeWriter *writer, 285 int field, 286 int type, 287 const void *value) 288{ 289 DBusTypeWriter sub; 290 DBusTypeWriter variant; 291 int start; 292 int padding; 293 unsigned char field_byte; 294 DBusString contained_type; 295 char buf[2]; 296 297 start = writer->value_pos; 298 padding = _dbus_string_get_length (writer->value_str) - start; 299 300 if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT, 301 NULL, 0, &sub)) 302 goto append_failed; 303 304 field_byte = field; 305 if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE, 306 &field_byte)) 307 goto append_failed; 308 309 buf[0] = type; 310 buf[1] = '\0'; 311 _dbus_string_init_const_len (&contained_type, buf, 1); 312 313 if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT, 314 &contained_type, 0, &variant)) 315 goto append_failed; 316 317 if (!_dbus_type_writer_write_basic (&variant, type, value)) 318 goto append_failed; 319 320 if (!_dbus_type_writer_unrecurse (&sub, &variant)) 321 goto append_failed; 322 323 if (!_dbus_type_writer_unrecurse (writer, &sub)) 324 goto append_failed; 325 326 return TRUE; 327 328 append_failed: 329 _dbus_string_delete (writer->value_str, 330 start, 331 _dbus_string_get_length (writer->value_str) - start - padding); 332 return FALSE; 333} 334 335/** 336 * Sets a struct of { byte, variant } with the given basic type. 337 * 338 * @param reader the reader (should be iterating over the array pointing at the field to set) 339 * @param type the type of the value 340 * @param value the value as for _dbus_marshal_set_basic() 341 * @param realign_root where to realign from 342 * @returns #FALSE if no memory 343 */ 344static dbus_bool_t 345set_basic_field (DBusTypeReader *reader, 346 int field, 347 int type, 348 const void *value, 349 const DBusTypeReader *realign_root) 350{ 351 DBusTypeReader sub; 352 DBusTypeReader variant; 353 354 _dbus_type_reader_recurse (reader, &sub); 355 356 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE); 357#ifndef DBUS_DISABLE_ASSERT 358 { 359 unsigned char v_BYTE; 360 _dbus_type_reader_read_basic (&sub, &v_BYTE); 361 _dbus_assert (((int) v_BYTE) == field); 362 } 363#endif 364 365 if (!_dbus_type_reader_next (&sub)) 366 _dbus_assert_not_reached ("no variant field?"); 367 368 _dbus_type_reader_recurse (&sub, &variant); 369 _dbus_assert (_dbus_type_reader_get_current_type (&variant) == type); 370 371 if (!_dbus_type_reader_set_basic (&variant, value, realign_root)) 372 return FALSE; 373 374 return TRUE; 375} 376 377/** 378 * Gets the type of the message. 379 * 380 * @param header the header 381 * @returns the type 382 */ 383int 384_dbus_header_get_message_type (DBusHeader *header) 385{ 386 int type; 387 388 type = _dbus_string_get_byte (&header->data, TYPE_OFFSET); 389 _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID); 390 391 return type; 392} 393 394/** 395 * Sets the serial number of a header. This can only be done once on 396 * a header. 397 * 398 * @param header the header 399 * @param serial the serial 400 */ 401void 402_dbus_header_set_serial (DBusHeader *header, 403 dbus_uint32_t serial) 404{ 405 /* we use this function to set the serial on outgoing 406 * messages, and to reset the serial in dbus_message_copy; 407 * this assertion should catch a double-set on outgoing. 408 */ 409 _dbus_assert (_dbus_header_get_serial (header) == 0 || 410 serial == 0); 411 412 _dbus_marshal_set_uint32 (&header->data, 413 SERIAL_OFFSET, 414 serial, 415 _dbus_header_get_byte_order (header)); 416} 417 418/** 419 * See dbus_message_get_serial() 420 * 421 * @param header the header 422 * @returns the client serial 423 */ 424dbus_uint32_t 425_dbus_header_get_serial (DBusHeader *header) 426{ 427 return _dbus_marshal_read_uint32 (&header->data, 428 SERIAL_OFFSET, 429 _dbus_header_get_byte_order (header), 430 NULL); 431} 432 433/** 434 * Re-initializes a header that was previously initialized and never 435 * freed. After this, to make the header valid you have to call 436 * _dbus_header_create(). 437 * 438 * @param header header to re-initialize 439 */ 440void 441_dbus_header_reinit (DBusHeader *header) 442{ 443 _dbus_string_set_length (&header->data, 0); 444 445 header->padding = 0; 446 447 _dbus_header_cache_invalidate_all (header); 448} 449 450/** 451 * Initializes a header, but doesn't prepare it for use; 452 * to make the header valid, you have to call _dbus_header_create(). 453 * 454 * @param header header to initialize 455 * @param byte_order byte order of the header 456 * @returns #FALSE if not enough memory 457 */ 458dbus_bool_t 459_dbus_header_init (DBusHeader *header) 460{ 461 if (!_dbus_string_init_preallocated (&header->data, 32)) 462 return FALSE; 463 464 _dbus_header_reinit (header); 465 466 return TRUE; 467} 468 469/** 470 * Frees a header. 471 * 472 * @param header the header 473 */ 474void 475_dbus_header_free (DBusHeader *header) 476{ 477 _dbus_string_free (&header->data); 478} 479 480/** 481 * Initializes dest with a copy of the given header. 482 * Resets the message serial to 0 on the copy. 483 * 484 * @param header header to copy 485 * @param dest destination for copy 486 * @returns #FALSE if not enough memory 487 */ 488dbus_bool_t 489_dbus_header_copy (const DBusHeader *header, 490 DBusHeader *dest) 491{ 492 *dest = *header; 493 494 if (!_dbus_string_init_preallocated (&dest->data, 495 _dbus_string_get_length (&header->data))) 496 return FALSE; 497 498 if (!_dbus_string_copy (&header->data, 0, &dest->data, 0)) 499 { 500 _dbus_string_free (&dest->data); 501 return FALSE; 502 } 503 504 /* Reset the serial */ 505 _dbus_header_set_serial (dest, 0); 506 507 return TRUE; 508} 509 510/** 511 * Fills in the primary fields of the header, so the header is ready 512 * for use. #NULL may be specified for some or all of the fields to 513 * avoid adding those fields. Some combinations of fields don't make 514 * sense, and passing them in will trigger an assertion failure. 515 * 516 * @param header the header 517 * @param message_type the message type 518 * @param destination destination field or #NULL 519 * @param path path field or #NULL 520 * @param interface interface field or #NULL 521 * @param member member field or #NULL 522 * @param error_name error name or #NULL 523 * @returns #FALSE if not enough memory 524 */ 525dbus_bool_t 526_dbus_header_create (DBusHeader *header, 527 int byte_order, 528 int message_type, 529 const char *destination, 530 const char *path, 531 const char *interface, 532 const char *member, 533 const char *error_name) 534{ 535 unsigned char v_BYTE; 536 dbus_uint32_t v_UINT32; 537 DBusTypeWriter writer; 538 DBusTypeWriter array; 539 540 _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || 541 byte_order == DBUS_BIG_ENDIAN); 542 _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) || 543 (error_name) || 544 !(interface || member || error_name)); 545 _dbus_assert (_dbus_string_get_length (&header->data) == 0); 546 547 if (!reserve_header_padding (header)) 548 return FALSE; 549 550 _dbus_type_writer_init_values_only (&writer, byte_order, 551 &_dbus_header_signature_str, 0, 552 &header->data, 553 HEADER_END_BEFORE_PADDING (header)); 554 555 v_BYTE = byte_order; 556 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, 557 &v_BYTE)) 558 goto oom; 559 560 v_BYTE = message_type; 561 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, 562 &v_BYTE)) 563 goto oom; 564 565 v_BYTE = 0; /* flags */ 566 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, 567 &v_BYTE)) 568 goto oom; 569 570 v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION; 571 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, 572 &v_BYTE)) 573 goto oom; 574 575 v_UINT32 = 0; /* body length */ 576 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32, 577 &v_UINT32)) 578 goto oom; 579 580 v_UINT32 = 0; /* serial */ 581 if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32, 582 &v_UINT32)) 583 goto oom; 584 585 if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY, 586 &_dbus_header_signature_str, 587 FIELDS_ARRAY_SIGNATURE_OFFSET, 588 &array)) 589 goto oom; 590 591 /* Marshal all the fields (Marshall Fields?) */ 592 593 if (path != NULL) 594 { 595 if (!write_basic_field (&array, 596 DBUS_HEADER_FIELD_PATH, 597 DBUS_TYPE_OBJECT_PATH, 598 &path)) 599 goto oom; 600 } 601 602 if (destination != NULL) 603 { 604 if (!write_basic_field (&array, 605 DBUS_HEADER_FIELD_DESTINATION, 606 DBUS_TYPE_STRING, 607 &destination)) 608 goto oom; 609 } 610 611 if (interface != NULL) 612 { 613 if (!write_basic_field (&array, 614 DBUS_HEADER_FIELD_INTERFACE, 615 DBUS_TYPE_STRING, 616 &interface)) 617 goto oom; 618 } 619 620 if (member != NULL) 621 { 622 if (!write_basic_field (&array, 623 DBUS_HEADER_FIELD_MEMBER, 624 DBUS_TYPE_STRING, 625 &member)) 626 goto oom; 627 } 628 629 if (error_name != NULL) 630 { 631 if (!write_basic_field (&array, 632 DBUS_HEADER_FIELD_ERROR_NAME, 633 DBUS_TYPE_STRING, 634 &error_name)) 635 goto oom; 636 } 637 638 if (!_dbus_type_writer_unrecurse (&writer, &array)) 639 goto oom; 640 641 correct_header_padding (header); 642 643 return TRUE; 644 645 oom: 646 _dbus_string_delete (&header->data, 0, 647 _dbus_string_get_length (&header->data) - header->padding); 648 correct_header_padding (header); 649 650 return FALSE; 651} 652 653/** 654 * Given data long enough to contain the length of the message body 655 * and the fields array, check whether the data is long enough to 656 * contain the entire message (assuming the claimed lengths are 657 * accurate). Also checks that the lengths are in sanity parameters. 658 * 659 * @param max_message_length maximum length of a valid message 660 * @param validity return location for why the data is invalid if it is 661 * @param byte_order return location for byte order 662 * @param fields_array_len return location for claimed fields array length 663 * @param header_len return location for claimed header length 664 * @param body_len return location for claimed body length 665 * @param str the data 666 * @param start start of data, 8-aligned 667 * @param len length of data 668 * @returns #TRUE if the data is long enough for the claimed length, and the lengths were valid 669 */ 670dbus_bool_t 671_dbus_header_have_message_untrusted (int max_message_length, 672 DBusValidity *validity, 673 int *byte_order, 674 int *fields_array_len, 675 int *header_len, 676 int *body_len, 677 const DBusString *str, 678 int start, 679 int len) 680 681{ 682 dbus_uint32_t header_len_unsigned; 683 dbus_uint32_t fields_array_len_unsigned; 684 dbus_uint32_t body_len_unsigned; 685 686 _dbus_assert (start >= 0); 687 _dbus_assert (start < _DBUS_INT32_MAX / 2); 688 _dbus_assert (len >= 0); 689 690 _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8)); 691 692 *byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET); 693 694 if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN) 695 { 696 *validity = DBUS_INVALID_BAD_BYTE_ORDER; 697 return FALSE; 698 } 699 700 _dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len); 701 fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET, 702 *byte_order, NULL); 703 704 if (fields_array_len_unsigned > (unsigned) max_message_length) 705 { 706 *validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH; 707 return FALSE; 708 } 709 710 _dbus_assert (BODY_LENGTH_OFFSET + 4 < len); 711 body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET, 712 *byte_order, NULL); 713 714 if (body_len_unsigned > (unsigned) max_message_length) 715 { 716 *validity = DBUS_INVALID_INSANE_BODY_LENGTH; 717 return FALSE; 718 } 719 720 header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned; 721 header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8); 722 723 /* overflow should be impossible since the lengths aren't allowed to 724 * be huge. 725 */ 726 _dbus_assert (max_message_length < _DBUS_INT32_MAX / 2); 727 if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length) 728 { 729 *validity = DBUS_INVALID_MESSAGE_TOO_LONG; 730 return FALSE; 731 } 732 733 _dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX); 734 _dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX); 735 _dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX); 736 737 *body_len = body_len_unsigned; 738 *fields_array_len = fields_array_len_unsigned; 739 *header_len = header_len_unsigned; 740 741 *validity = DBUS_VALID; 742 743 _dbus_verbose ("have %d bytes, need body %u + header %u = %u\n", 744 len, body_len_unsigned, header_len_unsigned, 745 body_len_unsigned + header_len_unsigned); 746 747 return (body_len_unsigned + header_len_unsigned) <= (unsigned) len; 748} 749 750static DBusValidity 751check_mandatory_fields (DBusHeader *header) 752{ 753#define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0) 754 755 switch (_dbus_header_get_message_type (header)) 756 { 757 case DBUS_MESSAGE_TYPE_SIGNAL: 758 REQUIRE_FIELD (INTERFACE); 759 /* FALL THRU - signals also require the path and member */ 760 case DBUS_MESSAGE_TYPE_METHOD_CALL: 761 REQUIRE_FIELD (PATH); 762 REQUIRE_FIELD (MEMBER); 763 break; 764 case DBUS_MESSAGE_TYPE_ERROR: 765 REQUIRE_FIELD (ERROR_NAME); 766 REQUIRE_FIELD (REPLY_SERIAL); 767 break; 768 case DBUS_MESSAGE_TYPE_METHOD_RETURN: 769 REQUIRE_FIELD (REPLY_SERIAL); 770 break; 771 default: 772 /* other message types allowed but ignored */ 773 break; 774 } 775 776 return DBUS_VALID; 777} 778 779static DBusValidity 780load_and_validate_field (DBusHeader *header, 781 int field, 782 DBusTypeReader *variant_reader) 783{ 784 int type; 785 int expected_type; 786 const DBusString *value_str; 787 int value_pos; 788 int str_data_pos; 789 dbus_uint32_t v_UINT32; 790 int bad_string_code; 791 dbus_bool_t (* string_validation_func) (const DBusString *str, 792 int start, int len); 793 794 /* Supposed to have been checked already */ 795 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST); 796 _dbus_assert (field != DBUS_HEADER_FIELD_INVALID); 797 798 /* Before we can cache a field, we need to know it has the right type */ 799 type = _dbus_type_reader_get_current_type (variant_reader); 800 801 _dbus_assert (_dbus_header_field_types[field].code == field); 802 803 expected_type = EXPECTED_TYPE_OF_FIELD (field); 804 if (type != expected_type) 805 { 806 _dbus_verbose ("Field %d should have type %d but has %d\n", 807 field, expected_type, type); 808 return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE; 809 } 810 811 /* If the field was provided twice, we aren't happy */ 812 if (header->fields[field].value_pos >= 0) 813 { 814 _dbus_verbose ("Header field %d seen a second time\n", field); 815 return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE; 816 } 817 818 /* Now we can cache and look at the field content */ 819 _dbus_verbose ("initially caching field %d\n", field); 820 _dbus_header_cache_one (header, field, variant_reader); 821 822 string_validation_func = NULL; 823 824 /* make compiler happy that all this is initialized */ 825 v_UINT32 = 0; 826 value_str = NULL; 827 value_pos = -1; 828 str_data_pos = -1; 829 bad_string_code = DBUS_VALID; 830 831 if (expected_type == DBUS_TYPE_UINT32) 832 { 833 _dbus_header_get_field_basic (header, field, expected_type, 834 &v_UINT32); 835 } 836 else if (expected_type == DBUS_TYPE_STRING || 837 expected_type == DBUS_TYPE_OBJECT_PATH || 838 expected_type == DBUS_TYPE_SIGNATURE) 839 { 840 _dbus_header_get_field_raw (header, field, 841 &value_str, &value_pos); 842 str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4; 843 } 844 else 845 { 846 _dbus_assert_not_reached ("none of the known fields should have this type"); 847 } 848 849 switch (field) 850 { 851 case DBUS_HEADER_FIELD_DESTINATION: 852 string_validation_func = _dbus_validate_bus_name; 853 bad_string_code = DBUS_INVALID_BAD_DESTINATION; 854 break; 855 case DBUS_HEADER_FIELD_INTERFACE: 856 string_validation_func = _dbus_validate_interface; 857 bad_string_code = DBUS_INVALID_BAD_INTERFACE; 858 859 if (_dbus_string_equal_substring (&_dbus_local_interface_str, 860 0, 861 _dbus_string_get_length (&_dbus_local_interface_str), 862 value_str, str_data_pos)) 863 { 864 _dbus_verbose ("Message is on the local interface\n"); 865 return DBUS_INVALID_USES_LOCAL_INTERFACE; 866 } 867 break; 868 869 case DBUS_HEADER_FIELD_MEMBER: 870 string_validation_func = _dbus_validate_member; 871 bad_string_code = DBUS_INVALID_BAD_MEMBER; 872 break; 873 874 case DBUS_HEADER_FIELD_ERROR_NAME: 875 string_validation_func = _dbus_validate_error_name; 876 bad_string_code = DBUS_INVALID_BAD_ERROR_NAME; 877 break; 878 879 case DBUS_HEADER_FIELD_SENDER: 880 string_validation_func = _dbus_validate_bus_name; 881 bad_string_code = DBUS_INVALID_BAD_SENDER; 882 break; 883 884 case DBUS_HEADER_FIELD_PATH: 885 /* OBJECT_PATH was validated generically due to its type */ 886 string_validation_func = NULL; 887 888 if (_dbus_string_equal_substring (&_dbus_local_path_str, 889 0, 890 _dbus_string_get_length (&_dbus_local_path_str), 891 value_str, str_data_pos)) 892 { 893 _dbus_verbose ("Message is from the local path\n"); 894 return DBUS_INVALID_USES_LOCAL_PATH; 895 } 896 break; 897 898 case DBUS_HEADER_FIELD_REPLY_SERIAL: 899 /* Can't be 0 */ 900 if (v_UINT32 == 0) 901 { 902 return DBUS_INVALID_BAD_SERIAL; 903 } 904 break; 905 906 case DBUS_HEADER_FIELD_UNIX_FDS: 907 /* Every value makes sense */ 908 break; 909 910 case DBUS_HEADER_FIELD_SIGNATURE: 911 /* SIGNATURE validated generically due to its type */ 912 string_validation_func = NULL; 913 break; 914 915 default: 916 _dbus_assert_not_reached ("unknown field shouldn't be seen here"); 917 break; 918 } 919 920 if (string_validation_func) 921 { 922 dbus_uint32_t len; 923 924 _dbus_assert (bad_string_code != DBUS_VALID); 925 926 len = _dbus_marshal_read_uint32 (value_str, value_pos, 927 _dbus_header_get_byte_order (header), 928 NULL); 929 930#if 0 931 _dbus_verbose ("Validating string header field; code %d if fails\n", 932 bad_string_code); 933#endif 934 if (!(*string_validation_func) (value_str, str_data_pos, len)) 935 return bad_string_code; 936 } 937 938 return DBUS_VALID; 939} 940 941/** 942 * Creates a message header from potentially-untrusted data. The 943 * return value is #TRUE if there was enough memory and the data was 944 * valid. If it returns #TRUE, the header will be created. If it 945 * returns #FALSE and *validity == #DBUS_VALIDITY_UNKNOWN_OOM_ERROR, 946 * then there wasn't enough memory. If it returns #FALSE 947 * and *validity != #DBUS_VALIDITY_UNKNOWN_OOM_ERROR then the data was 948 * invalid. 949 * 950 * The byte_order, fields_array_len, and body_len args should be from 951 * _dbus_header_have_message_untrusted(). Validation performed in 952 * _dbus_header_have_message_untrusted() is assumed to have been 953 * already done. 954 * 955 * @param header the header (must be initialized) 956 * @param mode whether to do validation 957 * @param validity return location for invalidity reason 958 * @param byte_order byte order from header 959 * @param fields_array_len claimed length of fields array 960 * @param body_len claimed length of body 961 * @param header_len claimed length of header 962 * @param str a string 963 * @param start start of header, 8-aligned 964 * @param len length of string to look at 965 * @returns #FALSE if no memory or data was invalid, #TRUE otherwise 966 */ 967dbus_bool_t 968_dbus_header_load (DBusHeader *header, 969 DBusValidationMode mode, 970 DBusValidity *validity, 971 int byte_order, 972 int fields_array_len, 973 int header_len, 974 int body_len, 975 const DBusString *str, 976 int start, 977 int len) 978{ 979 int leftover; 980 DBusValidity v; 981 DBusTypeReader reader; 982 DBusTypeReader array_reader; 983 unsigned char v_byte; 984 dbus_uint32_t v_uint32; 985 dbus_uint32_t serial; 986 int padding_start; 987 int padding_len; 988 int i; 989 990 _dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8)); 991 _dbus_assert (header_len <= len); 992 _dbus_assert (_dbus_string_get_length (&header->data) == 0); 993 994 if (!_dbus_string_copy_len (str, start, header_len, &header->data, 0)) 995 { 996 _dbus_verbose ("Failed to copy buffer into new header\n"); 997 *validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR; 998 return FALSE; 999 } 1000 1001 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 1002 { 1003 leftover = len - header_len - body_len - start; 1004 } 1005 else 1006 { 1007 v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0, 1008 byte_order, 1009 &leftover, 1010 str, start, len); 1011 1012 if (v != DBUS_VALID) 1013 { 1014 *validity = v; 1015 goto invalid; 1016 } 1017 } 1018 1019 _dbus_assert (leftover < len); 1020 1021 padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len); 1022 padding_start = start + FIRST_FIELD_OFFSET + fields_array_len; 1023 _dbus_assert (start + header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8)); 1024 _dbus_assert (start + header_len == padding_start + padding_len); 1025 1026 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 1027 { 1028 if (!_dbus_string_validate_nul (str, padding_start, padding_len)) 1029 { 1030 *validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL; 1031 goto invalid; 1032 } 1033 } 1034 1035 header->padding = padding_len; 1036 1037 if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY) 1038 { 1039 *validity = DBUS_VALID; 1040 return TRUE; 1041 } 1042 1043 /* We now know the data is well-formed, but we have to check that 1044 * it's valid. 1045 */ 1046 1047 _dbus_type_reader_init (&reader, 1048 byte_order, 1049 &_dbus_header_signature_str, 0, 1050 str, start); 1051 1052 /* BYTE ORDER */ 1053 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE); 1054 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET); 1055 _dbus_type_reader_read_basic (&reader, &v_byte); 1056 _dbus_type_reader_next (&reader); 1057 1058 _dbus_assert (v_byte == byte_order); 1059 1060 /* MESSAGE TYPE */ 1061 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE); 1062 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET); 1063 _dbus_type_reader_read_basic (&reader, &v_byte); 1064 _dbus_type_reader_next (&reader); 1065 1066 /* unknown message types are supposed to be ignored, so only validation here is 1067 * that it isn't invalid 1068 */ 1069 if (v_byte == DBUS_MESSAGE_TYPE_INVALID) 1070 { 1071 *validity = DBUS_INVALID_BAD_MESSAGE_TYPE; 1072 goto invalid; 1073 } 1074 1075 /* FLAGS */ 1076 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE); 1077 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET); 1078 _dbus_type_reader_read_basic (&reader, &v_byte); 1079 _dbus_type_reader_next (&reader); 1080 1081 /* unknown flags should be ignored */ 1082 1083 /* PROTOCOL VERSION */ 1084 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE); 1085 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET); 1086 _dbus_type_reader_read_basic (&reader, &v_byte); 1087 _dbus_type_reader_next (&reader); 1088 1089 if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION) 1090 { 1091 *validity = DBUS_INVALID_BAD_PROTOCOL_VERSION; 1092 goto invalid; 1093 } 1094 1095 /* BODY LENGTH */ 1096 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32); 1097 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET); 1098 _dbus_type_reader_read_basic (&reader, &v_uint32); 1099 _dbus_type_reader_next (&reader); 1100 1101 _dbus_assert (body_len == (signed) v_uint32); 1102 1103 /* SERIAL */ 1104 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32); 1105 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET); 1106 _dbus_type_reader_read_basic (&reader, &serial); 1107 _dbus_type_reader_next (&reader); 1108 1109 if (serial == 0) 1110 { 1111 *validity = DBUS_INVALID_BAD_SERIAL; 1112 goto invalid; 1113 } 1114 1115 _dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY); 1116 _dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET); 1117 1118 _dbus_type_reader_recurse (&reader, &array_reader); 1119 while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID) 1120 { 1121 DBusTypeReader struct_reader; 1122 DBusTypeReader variant_reader; 1123 unsigned char field_code; 1124 1125 _dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT); 1126 1127 _dbus_type_reader_recurse (&array_reader, &struct_reader); 1128 1129 _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE); 1130 _dbus_type_reader_read_basic (&struct_reader, &field_code); 1131 _dbus_type_reader_next (&struct_reader); 1132 1133 if (field_code == DBUS_HEADER_FIELD_INVALID) 1134 { 1135 _dbus_verbose ("invalid header field code\n"); 1136 *validity = DBUS_INVALID_HEADER_FIELD_CODE; 1137 goto invalid; 1138 } 1139 1140 if (field_code > DBUS_HEADER_FIELD_LAST) 1141 { 1142 _dbus_verbose ("unknown header field code %d, skipping\n", 1143 field_code); 1144 goto next_field; 1145 } 1146 1147 _dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT); 1148 _dbus_type_reader_recurse (&struct_reader, &variant_reader); 1149 1150 v = load_and_validate_field (header, field_code, &variant_reader); 1151 if (v != DBUS_VALID) 1152 { 1153 _dbus_verbose ("Field %d was invalid\n", field_code); 1154 *validity = v; 1155 goto invalid; 1156 } 1157 1158 next_field: 1159 _dbus_type_reader_next (&array_reader); 1160 } 1161 1162 /* Anything we didn't fill in is now known not to exist */ 1163 i = 0; 1164 while (i <= DBUS_HEADER_FIELD_LAST) 1165 { 1166 if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN) 1167 header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT; 1168 ++i; 1169 } 1170 1171 v = check_mandatory_fields (header); 1172 if (v != DBUS_VALID) 1173 { 1174 _dbus_verbose ("Mandatory fields were missing, code %d\n", v); 1175 *validity = v; 1176 goto invalid; 1177 } 1178 1179 *validity = DBUS_VALID; 1180 return TRUE; 1181 1182 invalid: 1183 _dbus_string_set_length (&header->data, 0); 1184 return FALSE; 1185} 1186 1187/** 1188 * Fills in the correct body length. 1189 * 1190 * @param header the header 1191 * @param body_len the length of the body 1192 */ 1193void 1194_dbus_header_update_lengths (DBusHeader *header, 1195 int body_len) 1196{ 1197 _dbus_marshal_set_uint32 (&header->data, 1198 BODY_LENGTH_OFFSET, 1199 body_len, 1200 _dbus_header_get_byte_order (header)); 1201} 1202 1203/** 1204 * Try to find the given field. 1205 * 1206 * @param header the header 1207 * @param field the field code 1208 * @param reader a type reader; on success this is left pointing at the struct 1209 * (uv) for the field, while on failure it is left pointing into empty space 1210 * at the end of the header fields 1211 * @param realign_root another type reader; on success or failure it is left 1212 * pointing to the beginning of the array of fields (i.e. the thing that might 1213 * need realigning) 1214 * @returns #TRUE on success 1215 */ 1216static dbus_bool_t 1217find_field_for_modification (DBusHeader *header, 1218 int field, 1219 DBusTypeReader *reader, 1220 DBusTypeReader *realign_root) 1221{ 1222 dbus_bool_t retval; 1223 1224 retval = FALSE; 1225 1226 _dbus_type_reader_init (realign_root, 1227 _dbus_header_get_byte_order (header), 1228 &_dbus_header_signature_str, 1229 FIELDS_ARRAY_SIGNATURE_OFFSET, 1230 &header->data, 1231 FIELDS_ARRAY_LENGTH_OFFSET); 1232 1233 _dbus_type_reader_recurse (realign_root, reader); 1234 1235 while (_dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID) 1236 { 1237 DBusTypeReader sub; 1238 unsigned char field_code; 1239 1240 _dbus_type_reader_recurse (reader, &sub); 1241 1242 _dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE); 1243 _dbus_type_reader_read_basic (&sub, &field_code); 1244 1245 if (field_code == (unsigned) field) 1246 { 1247 _dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_STRUCT); 1248 retval = TRUE; 1249 goto done; 1250 } 1251 1252 _dbus_type_reader_next (reader); 1253 } 1254 1255 done: 1256 return retval; 1257} 1258 1259/** 1260 * Sets the value of a field with basic type. If the value is a string 1261 * value, it isn't allowed to be #NULL. If the field doesn't exist, 1262 * it will be created. 1263 * 1264 * @param header the header 1265 * @param field the field to set 1266 * @param type the type of the value 1267 * @param value the value as for _dbus_marshal_set_basic() 1268 * @returns #FALSE if no memory 1269 */ 1270dbus_bool_t 1271_dbus_header_set_field_basic (DBusHeader *header, 1272 int field, 1273 int type, 1274 const void *value) 1275{ 1276 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST); 1277 1278 if (!reserve_header_padding (header)) 1279 return FALSE; 1280 1281 /* If the field exists we set, otherwise we append */ 1282 if (_dbus_header_cache_check (header, field)) 1283 { 1284 DBusTypeReader reader; 1285 DBusTypeReader realign_root; 1286 1287 if (!find_field_for_modification (header, field, 1288 &reader, &realign_root)) 1289 _dbus_assert_not_reached ("field was marked present in cache but wasn't found"); 1290 1291 if (!set_basic_field (&reader, field, type, value, &realign_root)) 1292 return FALSE; 1293 } 1294 else 1295 { 1296 DBusTypeWriter writer; 1297 DBusTypeWriter array; 1298 1299 _dbus_type_writer_init_values_only (&writer, 1300 _dbus_header_get_byte_order (header), 1301 &_dbus_header_signature_str, 1302 FIELDS_ARRAY_SIGNATURE_OFFSET, 1303 &header->data, 1304 FIELDS_ARRAY_LENGTH_OFFSET); 1305 1306 /* recurse into array without creating a new length, and jump to 1307 * end of array. 1308 */ 1309 if (!_dbus_type_writer_append_array (&writer, 1310 &_dbus_header_signature_str, 1311 FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET, 1312 &array)) 1313 _dbus_assert_not_reached ("recurse into ARRAY should not have used memory"); 1314 1315 _dbus_assert (array.u.array.len_pos == FIELDS_ARRAY_LENGTH_OFFSET); 1316 _dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET); 1317 _dbus_assert (array.value_pos == HEADER_END_BEFORE_PADDING (header)); 1318 1319 if (!write_basic_field (&array, 1320 field, type, value)) 1321 return FALSE; 1322 1323 if (!_dbus_type_writer_unrecurse (&writer, &array)) 1324 _dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory"); 1325 } 1326 1327 correct_header_padding (header); 1328 1329 /* We could be smarter about this (only invalidate fields after the 1330 * one we modified, or even only if the one we modified changed 1331 * length). But this hack is a start. 1332 */ 1333 _dbus_header_cache_invalidate_all (header); 1334 1335 return TRUE; 1336} 1337 1338/** 1339 * Gets the value of a field with basic type. If the field 1340 * doesn't exist, returns #FALSE, otherwise returns #TRUE. 1341 * 1342 * @param header the header 1343 * @param field the field to get 1344 * @param type the type of the value 1345 * @param value the value as for _dbus_marshal_read_basic() 1346 * @returns #FALSE if the field doesn't exist 1347 */ 1348dbus_bool_t 1349_dbus_header_get_field_basic (DBusHeader *header, 1350 int field, 1351 int type, 1352 void *value) 1353{ 1354 _dbus_assert (field != DBUS_HEADER_FIELD_INVALID); 1355 _dbus_assert (field <= DBUS_HEADER_FIELD_LAST); 1356 _dbus_assert (_dbus_header_field_types[field].code == field); 1357 /* in light of this you might ask why the type is passed in; 1358 * the only rationale I can think of is so the caller has 1359 * to specify its expectation and breaks if we change it 1360 */ 1361 _dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field)); 1362 1363 if (!_dbus_header_cache_check (header, field)) 1364 return FALSE; 1365 1366 _dbus_assert (header->fields[field].value_pos >= 0); 1367 1368 _dbus_marshal_read_basic (&header->data, 1369 header->fields[field].value_pos, 1370 type, value, _dbus_header_get_byte_order (header), 1371 NULL); 1372 1373 return TRUE; 1374} 1375 1376/** 1377 * Gets the raw marshaled data for a field. If the field doesn't 1378 * exist, returns #FALSE, otherwise returns #TRUE. Returns the start 1379 * of the marshaled data, i.e. usually the byte where the length 1380 * starts (for strings and arrays) or for basic types just the value 1381 * itself. 1382 * 1383 * @param header the header 1384 * @param field the field to get 1385 * @param str return location for the data string 1386 * @param pos return location for start of field value 1387 * @returns #FALSE if the field doesn't exist 1388 */ 1389dbus_bool_t 1390_dbus_header_get_field_raw (DBusHeader *header, 1391 int field, 1392 const DBusString **str, 1393 int *pos) 1394{ 1395 if (!_dbus_header_cache_check (header, field)) 1396 return FALSE; 1397 1398 if (str) 1399 *str = &header->data; 1400 if (pos) 1401 *pos = header->fields[field].value_pos; 1402 1403 return TRUE; 1404} 1405 1406/** 1407 * Deletes a field, if it exists. 1408 * 1409 * @param header the header 1410 * @param field the field to delete 1411 * @returns #FALSE if no memory 1412 */ 1413dbus_bool_t 1414_dbus_header_delete_field (DBusHeader *header, 1415 int field) 1416{ 1417 DBusTypeReader reader; 1418 DBusTypeReader realign_root; 1419 1420 if (_dbus_header_cache_known_nonexistent (header, field)) 1421 return TRUE; /* nothing to do */ 1422 1423 /* Scan to the field we want, delete and realign, reappend 1424 * padding. Field may turn out not to exist. 1425 */ 1426 if (!find_field_for_modification (header, field, 1427 &reader, &realign_root)) 1428 return TRUE; /* nothing to do */ 1429 1430 if (!reserve_header_padding (header)) 1431 return FALSE; 1432 1433 if (!_dbus_type_reader_delete (&reader, 1434 &realign_root)) 1435 return FALSE; 1436 1437 correct_header_padding (header); 1438 1439 _dbus_header_cache_invalidate_all (header); 1440 1441 _dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */ 1442 1443 return TRUE; 1444} 1445 1446/** 1447 * Toggles a message flag bit, turning on the bit if value = TRUE and 1448 * flipping it off if value = FALSE. 1449 * 1450 * @param header the header 1451 * @param flag the message flag to toggle 1452 * @param value toggle on or off 1453 */ 1454void 1455_dbus_header_toggle_flag (DBusHeader *header, 1456 dbus_uint32_t flag, 1457 dbus_bool_t value) 1458{ 1459 unsigned char *flags_p; 1460 1461 flags_p = _dbus_string_get_data_len (&header->data, FLAGS_OFFSET, 1); 1462 1463 if (value) 1464 *flags_p |= flag; 1465 else 1466 *flags_p &= ~flag; 1467} 1468 1469/** 1470 * Gets a message flag bit, returning TRUE if the bit is set. 1471 * 1472 * @param header the header 1473 * @param flag the message flag to get 1474 * @returns #TRUE if the flag is set 1475 */ 1476dbus_bool_t 1477_dbus_header_get_flag (DBusHeader *header, 1478 dbus_uint32_t flag) 1479{ 1480 const unsigned char *flags_p; 1481 1482 flags_p = _dbus_string_get_const_data_len (&header->data, FLAGS_OFFSET, 1); 1483 1484 return (*flags_p & flag) != 0; 1485} 1486 1487/** 1488 * Swaps the header into the given order if required. 1489 * 1490 * @param header the header 1491 * @param new_order the new byte order 1492 */ 1493void 1494_dbus_header_byteswap (DBusHeader *header, 1495 int new_order) 1496{ 1497 char byte_order; 1498 1499 byte_order = _dbus_header_get_byte_order (header); 1500 1501 if (byte_order == new_order) 1502 return; 1503 1504 _dbus_marshal_byteswap (&_dbus_header_signature_str, 1505 0, byte_order, 1506 new_order, 1507 &header->data, 0); 1508 1509 _dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order); 1510} 1511 1512/** @} */ 1513