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