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