dbus-marshal-header.c
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* dbus-marshal-header.c Managing marshaling/demarshaling of message headers
*
* Copyright (C) 2005 Red Hat, Inc.
*
* SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <config.h>
#include "dbus/dbus-shared.h"
#include "dbus-marshal-header.h"
#include "dbus-marshal-recursive.h"
#include "dbus-marshal-byteswap.h"
/* Not thread locked, but strictly const/read-only so should be OK
*/
_DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
_DBUS_STRING_DEFINE_STATIC(_dbus_local_interface_str, DBUS_INTERFACE_LOCAL);
_DBUS_STRING_DEFINE_STATIC(_dbus_local_path_str, DBUS_PATH_LOCAL);
#define FIELDS_ARRAY_SIGNATURE_OFFSET 6
#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET 7
#define BYTE_ORDER_OFFSET 0
#define TYPE_OFFSET 1
#define FLAGS_OFFSET 2
#define VERSION_OFFSET 3
#define BODY_LENGTH_OFFSET 4
#define SERIAL_OFFSET 8
#define FIELDS_ARRAY_LENGTH_OFFSET 12
#define FIRST_FIELD_OFFSET 16
typedef struct
{
unsigned char code;
unsigned char type;
} HeaderFieldType;
static const HeaderFieldType
_dbus_header_field_types[DBUS_HEADER_FIELD_LAST+1] = {
{ DBUS_HEADER_FIELD_INVALID, DBUS_TYPE_INVALID },
{ DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH },
{ DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING },
{ DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING },
{ DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING },
{ DBUS_HEADER_FIELD_REPLY_SERIAL, DBUS_TYPE_UINT32 },
{ DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING },
{ DBUS_HEADER_FIELD_SENDER, DBUS_TYPE_STRING },
{ DBUS_HEADER_FIELD_SIGNATURE, DBUS_TYPE_SIGNATURE },
{ DBUS_HEADER_FIELD_UNIX_FDS, DBUS_TYPE_UINT32 },
{ DBUS_HEADER_FIELD_CONTAINER_INSTANCE, DBUS_TYPE_OBJECT_PATH }
};
#define EXPECTED_TYPE_OF_FIELD(field) (_dbus_header_field_types[field].type)
#define MAX_POSSIBLE_HEADER_PADDING 7
static dbus_bool_t
reserve_header_padding (DBusHeader *header)
{
_dbus_assert (header->padding <= MAX_POSSIBLE_HEADER_PADDING);
if (!_dbus_string_lengthen (&header->data,
MAX_POSSIBLE_HEADER_PADDING - header->padding))
return FALSE;
header->padding = MAX_POSSIBLE_HEADER_PADDING;
return TRUE;
}
static void
correct_header_padding (DBusHeader *header)
{
int unpadded_len;
_dbus_assert (header->padding == 7);
_dbus_string_shorten (&header->data, header->padding);
unpadded_len = _dbus_string_get_length (&header->data);
if (!_dbus_string_align_length (&header->data, 8))
_dbus_assert_not_reached ("couldn't pad header though enough padding was preallocated");
header->padding = _dbus_string_get_length (&header->data) - unpadded_len;
}
#define HEADER_END_BEFORE_PADDING(header) \
(_dbus_string_get_length (&(header)->data) - (header)->padding)
static void
_dbus_header_cache_invalidate_all (DBusHeader *header)
{
int i;
i = 0;
while (i <= DBUS_HEADER_FIELD_LAST)
{
header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN;
++i;
}
}
static void
_dbus_header_cache_one (DBusHeader *header,
int field_code,
DBusTypeReader *variant_reader)
{
header->fields[field_code].value_pos =
_dbus_type_reader_get_value_pos (variant_reader);
#if 0
_dbus_verbose ("cached value_pos %d for field %d\n",
header->fields[field_code].value_pos, field_code)
#endif
}
char
_dbus_header_get_byte_order (const DBusHeader *header)
{
_dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET);
return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
}
static void
_dbus_header_cache_revalidate (DBusHeader *header)
{
DBusTypeReader array;
DBusTypeReader reader;
int i;
i = 0;
while (i <= DBUS_HEADER_FIELD_LAST)
{
header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
++i;
}
_dbus_type_reader_init (&reader,
_dbus_header_get_byte_order (header),
&_dbus_header_signature_str,
FIELDS_ARRAY_SIGNATURE_OFFSET,
&header->data,
FIELDS_ARRAY_LENGTH_OFFSET);
_dbus_type_reader_recurse (&reader, &array);
while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
{
DBusTypeReader sub;
DBusTypeReader variant;
unsigned char field_code;
_dbus_type_reader_recurse (&array, &sub);
_dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
_dbus_type_reader_read_basic (&sub, &field_code);
/* Unknown fields should be ignored */
if (field_code > DBUS_HEADER_FIELD_LAST)
goto next_field;
_dbus_type_reader_next (&sub);
_dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_VARIANT);
_dbus_type_reader_recurse (&sub, &variant);
_dbus_header_cache_one (header, field_code, &variant);
next_field:
_dbus_type_reader_next (&array);
}
}
static dbus_bool_t
_dbus_header_cache_check (DBusHeader *header,
int field)
{
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
_dbus_header_cache_revalidate (header);
if (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT)
return FALSE;
return TRUE;
}
static dbus_bool_t
_dbus_header_cache_known_nonexistent (DBusHeader *header,
int field)
{
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
return (header->fields[field].value_pos == _DBUS_HEADER_FIELD_VALUE_NONEXISTENT);
}
static dbus_bool_t
write_basic_field (DBusTypeWriter *writer,
int field,
int type,
const void *value)
{
DBusTypeWriter sub;
DBusTypeWriter variant;
int start;
int padding;
unsigned char field_byte;
DBusString contained_type;
char buf[2];
start = writer->value_pos;
padding = _dbus_string_get_length (writer->value_str) - start;
if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
NULL, 0, &sub))
goto append_failed;
field_byte = field;
if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
&field_byte))
goto append_failed;
buf[0] = type;
buf[1] = '\0';
_dbus_string_init_const_len (&contained_type, buf, 1);
if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
&contained_type, 0, &variant))
goto append_failed;
if (!_dbus_type_writer_write_basic (&variant, type, value))
goto append_failed;
if (!_dbus_type_writer_unrecurse (&sub, &variant))
goto append_failed;
if (!_dbus_type_writer_unrecurse (writer, &sub))
goto append_failed;
return TRUE;
append_failed:
_dbus_string_delete (writer->value_str,
start,
_dbus_string_get_length (writer->value_str) - start - padding);
return FALSE;
}
static dbus_bool_t
set_basic_field (DBusTypeReader *reader,
int field,
int type,
const void *value,
const DBusTypeReader *realign_root)
{
DBusTypeReader sub;
DBusTypeReader variant;
_dbus_type_reader_recurse (reader, &sub);
_dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
#ifndef DBUS_DISABLE_ASSERT
{
unsigned char v_BYTE;
_dbus_type_reader_read_basic (&sub, &v_BYTE);
_dbus_assert (((int) v_BYTE) == field);
}
#endif
if (!_dbus_type_reader_next (&sub))
_dbus_assert_not_reached ("no variant field?");
_dbus_type_reader_recurse (&sub, &variant);
_dbus_assert (_dbus_type_reader_get_current_type (&variant) == type);
if (!_dbus_type_reader_set_basic (&variant, value, realign_root))
return FALSE;
return TRUE;
}
int
_dbus_header_get_message_type (DBusHeader *header)
{
int type;
type = _dbus_string_get_byte (&header->data, TYPE_OFFSET);
_dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
return type;
}
void
_dbus_header_set_serial (DBusHeader *header,
dbus_uint32_t serial)
{
/* we use this function to set the serial on outgoing
* messages, and to reset the serial in dbus_message_copy;
* this assertion should catch a double-set on outgoing.
*/
_dbus_assert (_dbus_header_get_serial (header) == 0 ||
serial == 0);
_dbus_marshal_set_uint32 (&header->data,
SERIAL_OFFSET,
serial,
_dbus_header_get_byte_order (header));
}
dbus_uint32_t
_dbus_header_get_serial (DBusHeader *header)
{
return _dbus_marshal_read_uint32 (&header->data,
SERIAL_OFFSET,
_dbus_header_get_byte_order (header),
NULL);
}
void
_dbus_header_reinit (DBusHeader *header)
{
_dbus_string_set_length (&header->data, 0);
header->padding = 0;
_dbus_header_cache_invalidate_all (header);
}
dbus_bool_t
_dbus_header_init (DBusHeader *header)
{
if (!_dbus_string_init_preallocated (&header->data, 32))
return FALSE;
_dbus_header_reinit (header);
return TRUE;
}
void
_dbus_header_free (DBusHeader *header)
{
_dbus_string_free (&header->data);
}
dbus_bool_t
_dbus_header_copy (const DBusHeader *header,
DBusHeader *dest)
{
*dest = *header;
if (!_dbus_string_init_preallocated (&dest->data,
_dbus_string_get_length (&header->data)))
return FALSE;
if (!_dbus_string_copy (&header->data, 0, &dest->data, 0))
{
_dbus_string_free (&dest->data);
return FALSE;
}
/* Reset the serial */
_dbus_header_set_serial (dest, 0);
return TRUE;
}
dbus_bool_t
_dbus_header_create (DBusHeader *header,
int byte_order,
int message_type,
const char *destination,
const char *path,
const char *interface,
const char *member,
const char *error_name)
{
unsigned char v_BYTE;
dbus_uint32_t v_UINT32;
DBusTypeWriter writer;
DBusTypeWriter array;
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
byte_order == DBUS_BIG_ENDIAN);
_dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
(error_name) ||
!(interface || member || error_name));
_dbus_assert (_dbus_string_get_length (&header->data) == 0);
if (!reserve_header_padding (header))
return FALSE;
_dbus_type_writer_init_values_only (&writer, byte_order,
&_dbus_header_signature_str, 0,
&header->data,
HEADER_END_BEFORE_PADDING (header));
v_BYTE = byte_order;
if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
&v_BYTE))
goto oom;
v_BYTE = message_type;
if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
&v_BYTE))
goto oom;
v_BYTE = 0; /* flags */
if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
&v_BYTE))
goto oom;
v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
&v_BYTE))
goto oom;
v_UINT32 = 0; /* body length */
if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
&v_UINT32))
goto oom;
v_UINT32 = 0; /* serial */
if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32,
&v_UINT32))
goto oom;
if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
&_dbus_header_signature_str,
FIELDS_ARRAY_SIGNATURE_OFFSET,
&array))
goto oom;
/* Marshal all the fields (Marshall Fields?) */
if (path != NULL)
{
if (!write_basic_field (&array,
DBUS_HEADER_FIELD_PATH,
DBUS_TYPE_OBJECT_PATH,
&path))
goto oom;
}
if (destination != NULL)
{
if (!write_basic_field (&array,
DBUS_HEADER_FIELD_DESTINATION,
DBUS_TYPE_STRING,
&destination))
goto oom;
}
/* Note that test/message.c relies on this being in the middle of the
* message: if you change the order of serialization here (but why
* would you?), please find some other way to retain test coverage. */
if (interface != NULL)
{
if (!write_basic_field (&array,
DBUS_HEADER_FIELD_INTERFACE,
DBUS_TYPE_STRING,
&interface))
goto oom;
}
if (member != NULL)
{
if (!write_basic_field (&array,
DBUS_HEADER_FIELD_MEMBER,
DBUS_TYPE_STRING,
&member))
goto oom;
}
if (error_name != NULL)
{
if (!write_basic_field (&array,
DBUS_HEADER_FIELD_ERROR_NAME,
DBUS_TYPE_STRING,
&error_name))
goto oom;
}
if (!_dbus_type_writer_unrecurse (&writer, &array))
goto oom;
correct_header_padding (header);
return TRUE;
oom:
_dbus_string_delete (&header->data, 0,
_dbus_string_get_length (&header->data) - header->padding);
correct_header_padding (header);
return FALSE;
}
dbus_bool_t
_dbus_header_have_message_untrusted (int max_message_length,
DBusValidity *validity,
int *byte_order,
int *fields_array_len,
int *header_len,
int *body_len,
const DBusString *str,
int start,
int len)
{
dbus_uint32_t header_len_unsigned;
dbus_uint32_t fields_array_len_unsigned;
dbus_uint32_t body_len_unsigned;
_dbus_assert (start >= 0);
_dbus_assert (start < _DBUS_INT32_MAX / 2);
_dbus_assert (len >= 0);
_dbus_assert (start == (int) _DBUS_ALIGN_VALUE (start, 8));
*byte_order = _dbus_string_get_byte (str, start + BYTE_ORDER_OFFSET);
if (*byte_order != DBUS_LITTLE_ENDIAN && *byte_order != DBUS_BIG_ENDIAN)
{
*validity = DBUS_INVALID_BAD_BYTE_ORDER;
return FALSE;
}
_dbus_assert (FIELDS_ARRAY_LENGTH_OFFSET + 4 <= len);
fields_array_len_unsigned = _dbus_marshal_read_uint32 (str, start + FIELDS_ARRAY_LENGTH_OFFSET,
*byte_order, NULL);
if (fields_array_len_unsigned > (unsigned) max_message_length)
{
*validity = DBUS_INVALID_INSANE_FIELDS_ARRAY_LENGTH;
return FALSE;
}
_dbus_assert (BODY_LENGTH_OFFSET + 4 < len);
body_len_unsigned = _dbus_marshal_read_uint32 (str, start + BODY_LENGTH_OFFSET,
*byte_order, NULL);
if (body_len_unsigned > (unsigned) max_message_length)
{
*validity = DBUS_INVALID_INSANE_BODY_LENGTH;
return FALSE;
}
header_len_unsigned = FIRST_FIELD_OFFSET + fields_array_len_unsigned;
header_len_unsigned = _DBUS_ALIGN_VALUE (header_len_unsigned, 8);
/* overflow should be impossible since the lengths aren't allowed to
* be huge.
*/
_dbus_assert (max_message_length < _DBUS_INT32_MAX / 2);
if (body_len_unsigned + header_len_unsigned > (unsigned) max_message_length)
{
*validity = DBUS_INVALID_MESSAGE_TOO_LONG;
return FALSE;
}
_dbus_assert (body_len_unsigned < (unsigned) _DBUS_INT32_MAX);
_dbus_assert (fields_array_len_unsigned < (unsigned) _DBUS_INT32_MAX);
_dbus_assert (header_len_unsigned < (unsigned) _DBUS_INT32_MAX);
*body_len = body_len_unsigned;
*fields_array_len = fields_array_len_unsigned;
*header_len = header_len_unsigned;
*validity = DBUS_VALID;
_dbus_verbose ("have %d bytes, need body %u + header %u = %u\n",
len, body_len_unsigned, header_len_unsigned,
body_len_unsigned + header_len_unsigned);
return (body_len_unsigned + header_len_unsigned) <= (unsigned) len;
}
static DBusValidity
check_mandatory_fields (DBusHeader *header)
{
#define REQUIRE_FIELD(name) do { if (header->fields[DBUS_HEADER_FIELD_##name].value_pos < 0) return DBUS_INVALID_MISSING_##name; } while (0)
switch (_dbus_header_get_message_type (header))
{
case DBUS_MESSAGE_TYPE_SIGNAL:
REQUIRE_FIELD (INTERFACE);
/* FALL THRU - signals also require the path and member */
case DBUS_MESSAGE_TYPE_METHOD_CALL:
REQUIRE_FIELD (PATH);
REQUIRE_FIELD (MEMBER);
break;
case DBUS_MESSAGE_TYPE_ERROR:
REQUIRE_FIELD (ERROR_NAME);
REQUIRE_FIELD (REPLY_SERIAL);
break;
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
REQUIRE_FIELD (REPLY_SERIAL);
break;
default:
/* other message types allowed but ignored */
break;
}
return DBUS_VALID;
}
static DBusValidity
load_and_validate_field (DBusHeader *header,
int field,
DBusTypeReader *variant_reader)
{
int type;
int expected_type;
const DBusString *value_str;
int value_pos;
int str_data_pos;
dbus_uint32_t v_UINT32;
int bad_string_code;
dbus_bool_t (* string_validation_func) (const DBusString *str,
int start, int len);
/* Supposed to have been checked already */
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
_dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
/* Before we can cache a field, we need to know it has the right type */
type = _dbus_type_reader_get_current_type (variant_reader);
_dbus_assert (_dbus_header_field_types[field].code == field);
expected_type = EXPECTED_TYPE_OF_FIELD (field);
if (type != expected_type)
{
_dbus_verbose ("Field %d should have type %d but has %d\n",
field, expected_type, type);
return DBUS_INVALID_HEADER_FIELD_HAS_WRONG_TYPE;
}
/* If the field was provided twice, we aren't happy */
if (header->fields[field].value_pos >= 0)
{
_dbus_verbose ("Header field %d seen a second time\n", field);
return DBUS_INVALID_HEADER_FIELD_APPEARS_TWICE;
}
/* Now we can cache and look at the field content */
_dbus_verbose ("initially caching field %d\n", field);
_dbus_header_cache_one (header, field, variant_reader);
string_validation_func = NULL;
/* make compiler happy that all this is initialized */
v_UINT32 = 0;
value_str = NULL;
value_pos = -1;
str_data_pos = -1;
bad_string_code = DBUS_VALID;
if (expected_type == DBUS_TYPE_UINT32)
{
_dbus_header_get_field_basic (header, field, expected_type,
&v_UINT32);
}
else if (expected_type == DBUS_TYPE_STRING ||
expected_type == DBUS_TYPE_OBJECT_PATH ||
expected_type == DBUS_TYPE_SIGNATURE)
{
_dbus_header_get_field_raw (header, field,
&value_str, &value_pos);
str_data_pos = _DBUS_ALIGN_VALUE (value_pos, 4) + 4;
}
else
{
_dbus_assert_not_reached ("none of the known fields should have this type");
}
switch (field)
{
case DBUS_HEADER_FIELD_DESTINATION:
string_validation_func = _dbus_validate_bus_name;
bad_string_code = DBUS_INVALID_BAD_DESTINATION;
break;
case DBUS_HEADER_FIELD_INTERFACE:
string_validation_func = _dbus_validate_interface;
bad_string_code = DBUS_INVALID_BAD_INTERFACE;
if (_dbus_string_equal_substring (&_dbus_local_interface_str,
0,
_dbus_string_get_length (&_dbus_local_interface_str),
value_str, str_data_pos))
{
_dbus_verbose ("Message is on the local interface\n");
return DBUS_INVALID_USES_LOCAL_INTERFACE;
}
break;
case DBUS_HEADER_FIELD_MEMBER:
string_validation_func = _dbus_validate_member;
bad_string_code = DBUS_INVALID_BAD_MEMBER;
break;
case DBUS_HEADER_FIELD_ERROR_NAME:
string_validation_func = _dbus_validate_error_name;
bad_string_code = DBUS_INVALID_BAD_ERROR_NAME;
break;
case DBUS_HEADER_FIELD_SENDER:
string_validation_func = _dbus_validate_bus_name;
bad_string_code = DBUS_INVALID_BAD_SENDER;
break;
case DBUS_HEADER_FIELD_PATH:
/* OBJECT_PATH was validated generically due to its type */
string_validation_func = NULL;
if (_dbus_string_equal_substring (&_dbus_local_path_str,
0,
_dbus_string_get_length (&_dbus_local_path_str),
value_str, str_data_pos))
{
_dbus_verbose ("Message is from the local path\n");
return DBUS_INVALID_USES_LOCAL_PATH;
}
break;
case DBUS_HEADER_FIELD_REPLY_SERIAL:
/* Can't be 0 */
if (v_UINT32 == 0)
{
return DBUS_INVALID_BAD_SERIAL;
}
break;
case DBUS_HEADER_FIELD_UNIX_FDS:
/* Every value makes sense */
break;
case DBUS_HEADER_FIELD_SIGNATURE:
/* SIGNATURE validated generically due to its type */
string_validation_func = NULL;
break;
case DBUS_HEADER_FIELD_CONTAINER_INSTANCE:
/* OBJECT_PATH was validated generically due to its type */
string_validation_func = NULL;
break;
default:
_dbus_assert_not_reached ("unknown field shouldn't be seen here");
break;
}
if (string_validation_func)
{
dbus_uint32_t len;
_dbus_assert (bad_string_code != DBUS_VALID);
len = _dbus_marshal_read_uint32 (value_str, value_pos,
_dbus_header_get_byte_order (header),
NULL);
#if 0
_dbus_verbose ("Validating string header field; code %d if fails\n",
bad_string_code);
#endif
if (!(*string_validation_func) (value_str, str_data_pos, len))
return bad_string_code;
}
return DBUS_VALID;
}
dbus_bool_t
_dbus_header_load (DBusHeader *header,
DBusValidationMode mode,
DBusValidity *validity,
int byte_order,
int fields_array_len,
int header_len,
int body_len,
const DBusString *str)
{
int leftover;
DBusValidity v;
DBusTypeReader reader;
DBusTypeReader array_reader;
unsigned char v_byte;
dbus_uint32_t v_uint32;
dbus_uint32_t serial;
int padding_start;
int padding_len;
int i;
int len;
len = _dbus_string_get_length (str);
_dbus_assert (header_len <= len);
_dbus_assert (_dbus_string_get_length (&header->data) == 0);
if (!_dbus_string_copy_len (str, 0, header_len, &header->data, 0))
{
_dbus_verbose ("Failed to copy buffer into new header\n");
*validity = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
return FALSE;
}
if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
{
leftover = len - header_len - body_len;
}
else
{
v = _dbus_validate_body_with_reason (&_dbus_header_signature_str, 0,
byte_order,
&leftover,
str, 0, len);
if (v != DBUS_VALID)
{
*validity = v;
goto invalid;
}
}
_dbus_assert (leftover < len);
padding_len = header_len - (FIRST_FIELD_OFFSET + fields_array_len);
padding_start = FIRST_FIELD_OFFSET + fields_array_len;
_dbus_assert (header_len == (int) _DBUS_ALIGN_VALUE (padding_start, 8));
_dbus_assert (header_len == padding_start + padding_len);
if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
{
if (!_dbus_string_validate_nul (str, padding_start, padding_len))
{
*validity = DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
goto invalid;
}
}
header->padding = padding_len;
if (mode == DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
{
*validity = DBUS_VALID;
return TRUE;
}
/* We now know the data is well-formed, but we have to check that
* it's valid.
*/
_dbus_type_reader_init (&reader,
byte_order,
&_dbus_header_signature_str, 0,
str, 0);
/* BYTE ORDER */
_dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
_dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BYTE_ORDER_OFFSET);
_dbus_type_reader_read_basic (&reader, &v_byte);
_dbus_type_reader_next (&reader);
_dbus_assert (v_byte == byte_order);
/* MESSAGE TYPE */
_dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
_dbus_assert (_dbus_type_reader_get_value_pos (&reader) == TYPE_OFFSET);
_dbus_type_reader_read_basic (&reader, &v_byte);
_dbus_type_reader_next (&reader);
/* unknown message types are supposed to be ignored, so only validation here is
* that it isn't invalid
*/
if (v_byte == DBUS_MESSAGE_TYPE_INVALID)
{
*validity = DBUS_INVALID_BAD_MESSAGE_TYPE;
goto invalid;
}
/* FLAGS */
_dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
_dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FLAGS_OFFSET);
_dbus_type_reader_read_basic (&reader, &v_byte);
_dbus_type_reader_next (&reader);
/* unknown flags should be ignored */
/* PROTOCOL VERSION */
_dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
_dbus_assert (_dbus_type_reader_get_value_pos (&reader) == VERSION_OFFSET);
_dbus_type_reader_read_basic (&reader, &v_byte);
_dbus_type_reader_next (&reader);
if (v_byte != DBUS_MAJOR_PROTOCOL_VERSION)
{
*validity = DBUS_INVALID_BAD_PROTOCOL_VERSION;
goto invalid;
}
/* BODY LENGTH */
_dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
_dbus_assert (_dbus_type_reader_get_value_pos (&reader) == BODY_LENGTH_OFFSET);
_dbus_type_reader_read_basic (&reader, &v_uint32);
_dbus_type_reader_next (&reader);
_dbus_assert (body_len == (signed) v_uint32);
/* SERIAL */
_dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_UINT32);
_dbus_assert (_dbus_type_reader_get_value_pos (&reader) == SERIAL_OFFSET);
_dbus_type_reader_read_basic (&reader, &serial);
_dbus_type_reader_next (&reader);
if (serial == 0)
{
*validity = DBUS_INVALID_BAD_SERIAL;
goto invalid;
}
_dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_ARRAY);
_dbus_assert (_dbus_type_reader_get_value_pos (&reader) == FIELDS_ARRAY_LENGTH_OFFSET);
_dbus_type_reader_recurse (&reader, &array_reader);
while (_dbus_type_reader_get_current_type (&array_reader) != DBUS_TYPE_INVALID)
{
DBusTypeReader struct_reader;
DBusTypeReader variant_reader;
unsigned char field_code;
_dbus_assert (_dbus_type_reader_get_current_type (&array_reader) == DBUS_TYPE_STRUCT);
_dbus_type_reader_recurse (&array_reader, &struct_reader);
_dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_BYTE);
_dbus_type_reader_read_basic (&struct_reader, &field_code);
_dbus_type_reader_next (&struct_reader);
if (field_code == DBUS_HEADER_FIELD_INVALID)
{
_dbus_verbose ("invalid header field code\n");
*validity = DBUS_INVALID_HEADER_FIELD_CODE;
goto invalid;
}
if (field_code > DBUS_HEADER_FIELD_LAST)
{
_dbus_verbose ("unknown header field code %d, skipping\n",
field_code);
goto next_field;
}
_dbus_assert (_dbus_type_reader_get_current_type (&struct_reader) == DBUS_TYPE_VARIANT);
_dbus_type_reader_recurse (&struct_reader, &variant_reader);
v = load_and_validate_field (header, field_code, &variant_reader);
if (v != DBUS_VALID)
{
_dbus_verbose ("Field %d was invalid\n", field_code);
*validity = v;
goto invalid;
}
next_field:
_dbus_type_reader_next (&array_reader);
}
/* Anything we didn't fill in is now known not to exist */
i = 0;
while (i <= DBUS_HEADER_FIELD_LAST)
{
if (header->fields[i].value_pos == _DBUS_HEADER_FIELD_VALUE_UNKNOWN)
header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_NONEXISTENT;
++i;
}
v = check_mandatory_fields (header);
if (v != DBUS_VALID)
{
_dbus_verbose ("Mandatory fields were missing, code %d\n", v);
*validity = v;
goto invalid;
}
*validity = DBUS_VALID;
return TRUE;
invalid:
_dbus_string_set_length (&header->data, 0);
return FALSE;
}
void
_dbus_header_update_lengths (DBusHeader *header,
int body_len)
{
_dbus_marshal_set_uint32 (&header->data,
BODY_LENGTH_OFFSET,
body_len,
_dbus_header_get_byte_order (header));
}
static dbus_bool_t
find_field_for_modification (DBusHeader *header,
int field,
DBusTypeReader *reader,
DBusTypeReader *realign_root)
{
dbus_bool_t retval;
retval = FALSE;
_dbus_type_reader_init (realign_root,
_dbus_header_get_byte_order (header),
&_dbus_header_signature_str,
FIELDS_ARRAY_SIGNATURE_OFFSET,
&header->data,
FIELDS_ARRAY_LENGTH_OFFSET);
_dbus_type_reader_recurse (realign_root, reader);
while (_dbus_type_reader_get_current_type (reader) != DBUS_TYPE_INVALID)
{
DBusTypeReader sub;
unsigned char field_code;
_dbus_type_reader_recurse (reader, &sub);
_dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
_dbus_type_reader_read_basic (&sub, &field_code);
if (field_code == (unsigned) field)
{
_dbus_assert (_dbus_type_reader_get_current_type (reader) == DBUS_TYPE_STRUCT);
retval = TRUE;
goto done;
}
_dbus_type_reader_next (reader);
}
done:
return retval;
}
dbus_bool_t
_dbus_header_set_field_basic (DBusHeader *header,
int field,
int type,
const void *value)
{
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
if (!reserve_header_padding (header))
return FALSE;
/* If the field exists we set, otherwise we append */
if (_dbus_header_cache_check (header, field))
{
DBusTypeReader reader;
DBusTypeReader realign_root;
if (!find_field_for_modification (header, field,
&reader, &realign_root))
_dbus_assert_not_reached ("field was marked present in cache but wasn't found");
if (!set_basic_field (&reader, field, type, value, &realign_root))
return FALSE;
}
else
{
DBusTypeWriter writer;
DBusTypeWriter array;
_dbus_type_writer_init_values_only (&writer,
_dbus_header_get_byte_order (header),
&_dbus_header_signature_str,
FIELDS_ARRAY_SIGNATURE_OFFSET,
&header->data,
FIELDS_ARRAY_LENGTH_OFFSET);
/* recurse into array without creating a new length, and jump to
* end of array.
*/
if (!_dbus_type_writer_append_array (&writer,
&_dbus_header_signature_str,
FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET,
&array))
_dbus_assert_not_reached ("recurse into ARRAY should not have used memory");
_dbus_assert (array.u.array.len_pos == FIELDS_ARRAY_LENGTH_OFFSET);
_dbus_assert (array.u.array.start_pos == FIRST_FIELD_OFFSET);
_dbus_assert (array.value_pos == HEADER_END_BEFORE_PADDING (header));
if (!write_basic_field (&array,
field, type, value))
return FALSE;
if (!_dbus_type_writer_unrecurse (&writer, &array))
_dbus_assert_not_reached ("unrecurse from ARRAY should not have used memory");
}
correct_header_padding (header);
/* We could be smarter about this (only invalidate fields after the
* one we modified, or even only if the one we modified changed
* length). But this hack is a start.
*/
_dbus_header_cache_invalidate_all (header);
return TRUE;
}
dbus_bool_t
_dbus_header_get_field_basic (DBusHeader *header,
int field,
int type,
void *value)
{
_dbus_assert (field != DBUS_HEADER_FIELD_INVALID);
_dbus_assert (field <= DBUS_HEADER_FIELD_LAST);
_dbus_assert (_dbus_header_field_types[field].code == field);
/* in light of this you might ask why the type is passed in;
* the only rationale I can think of is so the caller has
* to specify its expectation and breaks if we change it
*/
_dbus_assert (type == EXPECTED_TYPE_OF_FIELD (field));
if (!_dbus_header_cache_check (header, field))
return FALSE;
_dbus_assert (header->fields[field].value_pos >= 0);
_dbus_marshal_read_basic (&header->data,
header->fields[field].value_pos,
type, value, _dbus_header_get_byte_order (header),
NULL);
return TRUE;
}
dbus_bool_t
_dbus_header_get_field_raw (DBusHeader *header,
int field,
const DBusString **str,
int *pos)
{
if (!_dbus_header_cache_check (header, field))
return FALSE;
if (str)
*str = &header->data;
if (pos)
*pos = header->fields[field].value_pos;
return TRUE;
}
dbus_bool_t
_dbus_header_delete_field (DBusHeader *header,
int field)
{
DBusTypeReader reader;
DBusTypeReader realign_root;
if (_dbus_header_cache_known_nonexistent (header, field))
return TRUE; /* nothing to do */
/* Scan to the field we want, delete and realign, reappend
* padding. Field may turn out not to exist.
*/
if (!find_field_for_modification (header, field,
&reader, &realign_root))
return TRUE; /* nothing to do */
if (!reserve_header_padding (header))
return FALSE;
if (!_dbus_type_reader_delete (&reader,
&realign_root))
return FALSE;
correct_header_padding (header);
_dbus_header_cache_invalidate_all (header);
_dbus_assert (!_dbus_header_cache_check (header, field)); /* Expensive assertion ... */
return TRUE;
}
void
_dbus_header_toggle_flag (DBusHeader *header,
dbus_uint32_t flag,
dbus_bool_t value)
{
unsigned char *flags_p;
flags_p = _dbus_string_get_udata_len (&header->data, FLAGS_OFFSET, 1);
if (value)
*flags_p |= flag;
else
*flags_p &= ~flag;
}
dbus_bool_t
_dbus_header_get_flag (DBusHeader *header,
dbus_uint32_t flag)
{
const unsigned char *flags_p;
flags_p = _dbus_string_get_const_udata_len (&header->data, FLAGS_OFFSET, 1);
return (*flags_p & flag) != 0;
}
void
_dbus_header_byteswap (DBusHeader *header,
int new_order)
{
char byte_order;
byte_order = _dbus_header_get_byte_order (header);
if (byte_order == new_order)
return;
_dbus_marshal_byteswap (&_dbus_header_signature_str,
0, byte_order,
new_order,
&header->data, 0);
_dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order);
}
dbus_bool_t
_dbus_header_remove_unknown_fields (DBusHeader *header)
{
DBusTypeReader array;
DBusTypeReader fields_reader;
_dbus_type_reader_init (&fields_reader,
_dbus_header_get_byte_order (header),
&_dbus_header_signature_str,
FIELDS_ARRAY_SIGNATURE_OFFSET,
&header->data,
FIELDS_ARRAY_LENGTH_OFFSET);
_dbus_type_reader_recurse (&fields_reader, &array);
while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
{
DBusTypeReader sub;
unsigned char field_code;
_dbus_type_reader_recurse (&array, &sub);
_dbus_assert (_dbus_type_reader_get_current_type (&sub) == DBUS_TYPE_BYTE);
_dbus_type_reader_read_basic (&sub, &field_code);
if (field_code > DBUS_HEADER_FIELD_LAST)
{
if (!reserve_header_padding (header))
return FALSE;
if (!_dbus_type_reader_delete (&array, &fields_reader))
return FALSE;
correct_header_padding (header);
_dbus_header_cache_invalidate_all (header);
}
else
{
_dbus_type_reader_next (&array);
}
}
return TRUE;
}
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Definition dbus-internals.h:164
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition dbus-internals.h:153
_DBUS_INT32_MAX
#define _DBUS_INT32_MAX
Maximum value of type "int32".
Definition dbus-internals.h:323
NULL
#define NULL
A null pointer, defined appropriately for C or C++.
Definition dbus-macros.h:51
TRUE
#define TRUE
Expands to "1".
Definition dbus-macros.h:41
FALSE
#define FALSE
Expands to "0".
Definition dbus-macros.h:44
_dbus_type_writer_write_basic
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
Definition dbus-marshal-recursive.c:2310
_dbus_type_reader_recurse
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
Definition dbus-marshal-recursive.c:987
DBusValidity
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
Definition dbus-marshal-validate.h:54
_dbus_header_update_lengths
void _dbus_header_update_lengths(DBusHeader *header, int body_len)
Fills in the correct body length.
Definition dbus-marshal-header.c:1207
_dbus_header_copy
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given header.
Definition dbus-marshal-header.c:495
BODY_LENGTH_OFFSET
#define BODY_LENGTH_OFFSET
Offset to body length from start of header.
Definition dbus-marshal-header.c:63
_dbus_type_writer_init_values_only
void _dbus_type_writer_init_values_only(DBusTypeWriter *writer, int byte_order, const DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Like _dbus_type_writer_init(), except the type string passed in should correspond to an existing sign...
Definition dbus-marshal-recursive.c:1583
_dbus_type_reader_get_value_pos
int _dbus_type_reader_get_value_pos(const DBusTypeReader *reader)
Gets the current position in the value block.
Definition dbus-marshal-recursive.c:837
_dbus_type_reader_init
void _dbus_type_reader_init(DBusTypeReader *reader, int byte_order, const DBusString *type_str, int type_pos, const DBusString *value_str, int value_pos)
Initializes a type reader.
Definition dbus-marshal-recursive.c:732
EXPECTED_TYPE_OF_FIELD
#define EXPECTED_TYPE_OF_FIELD(field)
Macro to look up the correct type for a field.
Definition dbus-marshal-header.c:93
_dbus_validate_error_name
dbus_bool_t _dbus_validate_error_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid error name in the D-Bus protocol.
Definition dbus-marshal-validate.c:1124
_dbus_header_set_field_basic
dbus_bool_t _dbus_header_set_field_basic(DBusHeader *header, int field, int type, const void *value)
Sets the value of a field with basic type.
Definition dbus-marshal-header.c:1284
_dbus_header_get_message_type
int _dbus_header_get_message_type(DBusHeader *header)
Gets the type of the message.
Definition dbus-marshal-header.c:391
_dbus_header_get_field_basic
dbus_bool_t _dbus_header_get_field_basic(DBusHeader *header, int field, int type, void *value)
Gets the value of a field with basic type.
Definition dbus-marshal-header.c:1362
SERIAL_OFFSET
#define SERIAL_OFFSET
Offset to client serial from start of header.
Definition dbus-marshal-header.c:65
_dbus_marshal_set_uint32
void _dbus_marshal_set_uint32(DBusString *str, int pos, dbus_uint32_t value, int byte_order)
Sets the 4 bytes at the given offset to a marshaled unsigned integer, replacing anything found there ...
Definition dbus-marshal-basic.c:260
_dbus_type_writer_recurse
dbus_bool_t _dbus_type_writer_recurse(DBusTypeWriter *writer, int container_type, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Opens a new container and writes out the initial information for that container.
Definition dbus-marshal-recursive.c:2108
VERSION_OFFSET
#define VERSION_OFFSET
Offset to version from start of header.
Definition dbus-marshal-header.c:61
_dbus_header_get_flag
dbus_bool_t _dbus_header_get_flag(DBusHeader *header, dbus_uint32_t flag)
Gets a message flag bit, returning TRUE if the bit is set.
Definition dbus-marshal-header.c:1490
_dbus_marshal_byteswap
void _dbus_marshal_byteswap(const DBusString *signature, int signature_start, int old_byte_order, int new_byte_order, DBusString *value_str, int value_pos)
Byteswaps the marshaled data in the given value_str.
Definition dbus-marshal-byteswap.c:224
_dbus_header_get_byte_order
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
Definition dbus-marshal-header.c:179
_dbus_header_have_message_untrusted
dbus_bool_t _dbus_header_have_message_untrusted(int max_message_length, DBusValidity *validity, int *byte_order, int *fields_array_len, int *header_len, int *body_len, const DBusString *str, int start, int len)
Given data long enough to contain the length of the message body and the fields array,...
Definition dbus-marshal-header.c:681
_dbus_header_reinit
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
Definition dbus-marshal-header.c:448
_dbus_marshal_read_uint32
dbus_uint32_t _dbus_marshal_read_uint32(const DBusString *str, int pos, int byte_order, int *new_pos)
Convenience function to demarshal a 32 bit unsigned integer.
Definition dbus-marshal-basic.c:476
_dbus_validate_member
dbus_bool_t _dbus_validate_member(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid member name in the D-Bus protocol.
Definition dbus-marshal-validate.c:1063
_dbus_type_reader_next
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
Definition dbus-marshal-recursive.c:1053
_dbus_header_delete_field
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
Definition dbus-marshal-header.c:1427
_dbus_header_remove_unknown_fields
dbus_bool_t _dbus_header_remove_unknown_fields(DBusHeader *header)
Remove every header field not known to this version of dbus.
Definition dbus-marshal-header.c:1532
_dbus_header_get_serial
dbus_uint32_t _dbus_header_get_serial(DBusHeader *header)
See dbus_message_get_serial().
Definition dbus-marshal-header.c:432
FLAGS_OFFSET
#define FLAGS_OFFSET
Offset to flags from start of header.
Definition dbus-marshal-header.c:59
FIELDS_ARRAY_SIGNATURE_OFFSET
#define FIELDS_ARRAY_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of the fields array.
Definition dbus-marshal-header.c:49
MAX_POSSIBLE_HEADER_PADDING
#define MAX_POSSIBLE_HEADER_PADDING
The most padding we could ever need for a header.
Definition dbus-marshal-header.c:96
_dbus_type_reader_delete
dbus_bool_t _dbus_type_reader_delete(DBusTypeReader *reader, const DBusTypeReader *realign_root)
Recursively deletes any value pointed to by the reader, leaving the reader valid to continue reading.
Definition dbus-marshal-recursive.c:1419
_dbus_type_reader_read_basic
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
Definition dbus-marshal-recursive.c:869
BYTE_ORDER_OFFSET
#define BYTE_ORDER_OFFSET
Offset to byte order from start of header.
Definition dbus-marshal-header.c:55
FIRST_FIELD_OFFSET
#define FIRST_FIELD_OFFSET
Offset to first field in header.
Definition dbus-marshal-header.c:69
_dbus_validate_interface
dbus_bool_t _dbus_validate_interface(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid interface name in the D-Bus protocol.
Definition dbus-marshal-validate.c:987
_dbus_type_reader_set_basic
dbus_bool_t _dbus_type_reader_set_basic(DBusTypeReader *reader, const void *value, const DBusTypeReader *realign_root)
Sets a new value for the basic type value pointed to by the reader, leaving the reader valid to conti...
Definition dbus-marshal-recursive.c:1362
_dbus_validate_body_with_reason
DBusValidity _dbus_validate_body_with_reason(const DBusString *expected_signature, int expected_signature_start, int byte_order, int *bytes_remaining, const DBusString *value_str, int value_pos, int len)
Verifies that the range of value_str from value_pos to value_end is a legitimate value of type expect...
Definition dbus-marshal-validate.c:767
_dbus_marshal_read_basic
void _dbus_marshal_read_basic(const DBusString *str, int pos, int type, void *value, int byte_order, int *new_pos)
Demarshals a basic-typed value.
Definition dbus-marshal-basic.c:514
_DBUS_STRING_DEFINE_STATIC
_DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE)
Static DBusString containing the signature of a message header.
_dbus_type_reader_get_current_type
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
Definition dbus-marshal-recursive.c:785
_dbus_header_free
void _dbus_header_free(DBusHeader *header)
Frees a header.
Definition dbus-marshal-header.c:481
_dbus_validate_bus_name
dbus_bool_t _dbus_validate_bus_name(const DBusString *str, int start, int len)
Checks that the given range of the string is a valid bus name in the D-Bus protocol.
Definition dbus-marshal-validate.c:1253
_dbus_header_init
dbus_bool_t _dbus_header_init(DBusHeader *header)
Initializes a header, but doesn't prepare it for use; to make the header valid, you have to call _dbu...
Definition dbus-marshal-header.c:465
_dbus_header_create
dbus_bool_t _dbus_header_create(DBusHeader *header, int byte_order, int message_type, const char *destination, const char *path, const char *interface, const char *member, const char *error_name)
Fills in the primary fields of the header, so the header is ready for use.
Definition dbus-marshal-header.c:533
FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET
#define FIELDS_ARRAY_ELEMENT_SIGNATURE_OFFSET
Offset from start of _dbus_header_signature_str to the signature of an element of the fields array.
Definition dbus-marshal-header.c:51
_dbus_type_writer_unrecurse
dbus_bool_t _dbus_type_writer_unrecurse(DBusTypeWriter *writer, DBusTypeWriter *sub)
Closes a container created by _dbus_type_writer_recurse() and writes any additional information to th...
Definition dbus-marshal-recursive.c:2178
_dbus_type_writer_append_array
dbus_bool_t _dbus_type_writer_append_array(DBusTypeWriter *writer, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Append to an existing array.
Definition dbus-marshal-recursive.c:2142
_dbus_header_toggle_flag
void _dbus_header_toggle_flag(DBusHeader *header, dbus_uint32_t flag, dbus_bool_t value)
Toggles a message flag bit, turning on the bit if value = TRUE and flipping it off if value = FALSE.
Definition dbus-marshal-header.c:1468
_dbus_header_set_serial
void _dbus_header_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
Definition dbus-marshal-header.c:409
_dbus_header_load
dbus_bool_t _dbus_header_load(DBusHeader *header, DBusValidationMode mode, DBusValidity *validity, int byte_order, int fields_array_len, int header_len, int body_len, const DBusString *str)
Creates a message header from potentially-untrusted data.
Definition dbus-marshal-header.c:981
_dbus_header_byteswap
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
Definition dbus-marshal-header.c:1507
FIELDS_ARRAY_LENGTH_OFFSET
#define FIELDS_ARRAY_LENGTH_OFFSET
Offset to fields array length from start of header.
Definition dbus-marshal-header.c:67
HEADER_END_BEFORE_PADDING
#define HEADER_END_BEFORE_PADDING(header)
Compute the end of the header, ignoring padding.
Definition dbus-marshal-header.c:128
_dbus_header_get_field_raw
dbus_bool_t _dbus_header_get_field_raw(DBusHeader *header, int field, const DBusString **str, int *pos)
Gets the raw marshaled data for a field.
Definition dbus-marshal-header.c:1403
TYPE_OFFSET
#define TYPE_OFFSET
Offset to type from start of header.
Definition dbus-marshal-header.c:57
DBusValidationMode
DBusValidationMode
This is used rather than a bool for high visibility.
Definition dbus-marshal-validate.h:41
DBUS_VALIDITY_UNKNOWN_OOM_ERROR
@ DBUS_VALIDITY_UNKNOWN_OOM_ERROR
can't determine validity due to OOM
Definition dbus-marshal-validate.h:56
DBUS_VALID
@ DBUS_VALID
the data is valid
Definition dbus-marshal-validate.h:60
DBUS_HEADER_FIELD_UNIX_FDS
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
Definition dbus-protocol.h:304
DBUS_HEADER_FIELD_INVALID
#define DBUS_HEADER_FIELD_INVALID
Not equal to any valid header field code.
Definition dbus-protocol.h:268
DBUS_MESSAGE_TYPE_METHOD_CALL
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type().
Definition dbus-protocol.h:236
DBUS_HEADER_FIELD_PATH
#define DBUS_HEADER_FIELD_PATH
Header field code for the path - the path is the object emitting a signal or the object receiving a m...
Definition dbus-protocol.h:272
DBUS_HEADER_FIELD_REPLY_SERIAL
#define DBUS_HEADER_FIELD_REPLY_SERIAL
Header field code for a reply serial, used to match a DBUS_MESSAGE_TYPE_METHOD_RETURN message with th...
Definition dbus-protocol.h:286
DBUS_HEADER_FIELD_CONTAINER_INSTANCE
#define DBUS_HEADER_FIELD_CONTAINER_INSTANCE
Header field code for the container instance that sent this message.
Definition dbus-protocol.h:308
DBUS_TYPE_SIGNATURE
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
Definition dbus-protocol.h:112
DBUS_HEADER_FIELD_INTERFACE
#define DBUS_HEADER_FIELD_INTERFACE
Header field code for the interface containing a member (method or signal).
Definition dbus-protocol.h:276
DBUS_HEADER_FIELD_MEMBER
#define DBUS_HEADER_FIELD_MEMBER
Header field code for a member (method or signal).
Definition dbus-protocol.h:278
DBUS_MESSAGE_TYPE_ERROR
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type().
Definition dbus-protocol.h:240
DBUS_TYPE_OBJECT_PATH
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
Definition dbus-protocol.h:108
DBUS_TYPE_BYTE
#define DBUS_TYPE_BYTE
Type code marking an 8-bit unsigned integer.
Definition dbus-protocol.h:68
DBUS_HEADER_FIELD_SENDER
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus.
Definition dbus-protocol.h:295
DBUS_HEADER_FIELD_SIGNATURE
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
Definition dbus-protocol.h:299
DBUS_MESSAGE_TYPE_METHOD_RETURN
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type().
Definition dbus-protocol.h:238
DBUS_TYPE_VARIANT
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
Definition dbus-protocol.h:126
DBUS_MESSAGE_TYPE_SIGNAL
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type().
Definition dbus-protocol.h:242
DBUS_TYPE_STRING
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
Definition dbus-protocol.h:104
DBUS_HEADER_SIGNATURE
#define DBUS_HEADER_SIGNATURE
Header format is defined as a signature: byte byte order byte message type ID byte flags byte protoco...
Definition dbus-protocol.h:332
DBUS_TYPE_ARRAY
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
Definition dbus-protocol.h:122
DBUS_HEADER_FIELD_LAST
#define DBUS_HEADER_FIELD_LAST
Value of the highest-numbered header field code, can be used to determine the size of an array indexe...
Definition dbus-protocol.h:317
DBUS_TYPE_INVALID
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition dbus-protocol.h:62
DBUS_LITTLE_ENDIAN
#define DBUS_LITTLE_ENDIAN
Code marking LSB-first byte order in the wire protocol.
Definition dbus-protocol.h:55
DBUS_HEADER_FIELD_ERROR_NAME
#define DBUS_HEADER_FIELD_ERROR_NAME
Header field code for an error name (found in DBUS_MESSAGE_TYPE_ERROR messages).
Definition dbus-protocol.h:282
DBUS_MESSAGE_TYPE_INVALID
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type().
Definition dbus-protocol.h:234
DBUS_HEADER_FIELD_DESTINATION
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
Definition dbus-protocol.h:290
DBUS_MAJOR_PROTOCOL_VERSION
#define DBUS_MAJOR_PROTOCOL_VERSION
Protocol version.
Definition dbus-protocol.h:59
DBUS_TYPE_STRUCT
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
Definition dbus-protocol.h:138
DBUS_BIG_ENDIAN
#define DBUS_BIG_ENDIAN
Code marking MSB-first byte order in the wire protocol.
Definition dbus-protocol.h:56
DBUS_TYPE_UINT32
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition dbus-protocol.h:88
DBUS_PATH_LOCAL
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition dbus-shared.h:84
DBUS_INTERFACE_LOCAL
#define DBUS_INTERFACE_LOCAL
This is a special interface whose methods can only be invoked by the local implementation (messages f...
Definition dbus-shared.h:107
_dbus_string_set_length
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition dbus-string.c:847
_dbus_string_validate_nul
dbus_bool_t _dbus_string_validate_nul(const DBusString *str, int start, int len)
Checks that the given range of the string is all nul bytes.
Definition dbus-string.c:2776
_dbus_string_equal_substring
dbus_bool_t _dbus_string_equal_substring(const DBusString *a, int a_start, int a_len, const DBusString *b, int b_start)
Tests two sub-parts of two DBusString for equality.
Definition dbus-string.c:2166
_dbus_string_copy
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition dbus-string.c:1345
_dbus_string_init_preallocated
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition dbus-string.c:139
_dbus_string_init_const_len
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition dbus-string.c:217
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as _DBUS_STRING_IN...
Definition dbus-string.c:278
_dbus_string_shorten
void _dbus_string_shorten(DBusString *str, int length_to_remove)
Makes a string shorter by the given number of bytes.
Definition dbus-string.c:825
_dbus_string_delete
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition dbus-string.c:1255
_dbus_string_lengthen
dbus_bool_t _dbus_string_lengthen(DBusString *str, int additional_length)
Makes a string longer by the given number of bytes.
Definition dbus-string.c:805
_dbus_string_align_length
dbus_bool_t _dbus_string_align_length(DBusString *str, int alignment)
Align the length of a string to a specific alignment (typically 4 or 8) by appending nul bytes to the...
Definition dbus-string.c:928
_dbus_string_copy_len
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition dbus-string.c:1437
dbus_uint32_t
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
Definition dbus-arch-deps.h:45
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition dbus-types.h:37
DBusHeaderField::value_pos
int value_pos
Position of field value, or -1/-2.
Definition dbus-marshal-header.h:43
DBusHeader
Message header data and some cached details of it.
Definition dbus-marshal-header.h:90
DBusHeader::data
DBusString data
Header network data, stored separately from body so we can independently realloc it.
Definition dbus-marshal-header.h:91
DBusHeader::padding
dbus_uint32_t padding
0-7 bytes of alignment in header, the distance from [B] to [C]
Definition dbus-marshal-header.h:106
DBusHeader::fields
DBusHeaderField fields[DBUS_HEADER_FIELD_LAST+1]
Track the location of each field in header.
Definition dbus-marshal-header.h:102
DBusString
Definition dbus-string.h:47
DBusTypeReader
The type reader is an iterator for reading values from a block of values.
Definition dbus-marshal-recursive.h:42
DBusTypeWriter
The type writer is an iterator for writing to a block of values.
Definition dbus-marshal-recursive.h:68
DBusTypeWriter::start_pos
int start_pos
position of first element in the array
Definition dbus-marshal-recursive.h:85
DBusTypeWriter::value_pos
int value_pos
next position to write
Definition dbus-marshal-recursive.h:80
DBusTypeWriter::len_pos
int len_pos
position of length of the array
Definition dbus-marshal-recursive.h:86
DBusTypeWriter::u
union DBusTypeWriter::@161371303007024032033326337102255054154347022341 u
class-specific data
DBusTypeWriter::value_str
DBusString * value_str
where to write values
Definition dbus-marshal-recursive.h:70
HeaderFieldType
Definition dbus-marshal-header.c:72
HeaderFieldType::type
unsigned char type
the value type
Definition dbus-marshal-header.c:74
HeaderFieldType::code
unsigned char code
the field code
Definition dbus-marshal-header.c:73