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