}
static dbus_bool_t
+set_uint_field (DBusMessage *message,
+ int field,
+ dbus_uint32_t value)
+{
+ int offset = message->header_fields[field].offset;
+
+ _dbus_assert (!message->locked);
+
+ if (offset < 0)
+ {
+ /* need to append the field */
+
+ switch (field)
+ {
+ default:
+ _dbus_assert_not_reached ("appending a uint field we don't support appending");
+ return FALSE;
+ }
+ }
+ else
+ {
+ _dbus_marshal_set_uint32 (&message->header,
+ message->byte_order,
+ offset, value);
+
+ return TRUE;
+ }
+}
+
+static dbus_bool_t
set_string_field (DBusMessage *message,
int field,
const char *value)
dbus_message_create_header (DBusMessage *message,
const char *service,
const char *name)
-{
+{
+ unsigned int flags;
+
if (!_dbus_string_append_byte (&message->header, message->byte_order))
return FALSE;
-
- if (!_dbus_string_append_len (&message->header, "\0\0\0", 3))
+
+ flags = 0;
+ if (!_dbus_string_append_byte (&message->header, flags))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
+ return FALSE;
+
+ if (!_dbus_string_append_byte (&message->header, 0))
return FALSE;
message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
- if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0))
+ if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
return FALSE;
message->header_fields[FIELD_BODY_LENGTH].offset = 8;
- if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0))
+ if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
return FALSE;
message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
if (!message->locked)
{
/* Fill in our lengths */
- set_int_field (message,
- FIELD_HEADER_LENGTH,
- _dbus_string_get_length (&message->header));
+ set_uint_field (message,
+ FIELD_HEADER_LENGTH,
+ _dbus_string_get_length (&message->header));
- set_int_field (message,
- FIELD_BODY_LENGTH,
- _dbus_string_get_length (&message->body));
+ set_uint_field (message,
+ FIELD_BODY_LENGTH,
+ _dbus_string_get_length (&message->body));
message->locked = TRUE;
}
DBusMessage *message;
const char *header_data;
int byte_order, header_len, body_len;
+ dbus_uint32_t header_len_unsigned, body_len_unsigned;
_dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
return;
}
- header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
- body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
+ header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
+ body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
- if (header_len < 16 || body_len < 0)
+ if (header_len_unsigned < 16)
{
- _dbus_verbose ("Message had broken too-small header or body len %d %d\n",
- header_len, body_len);
+ _dbus_verbose ("Message had broken too-small header length %u\n",
+ header_len_unsigned);
loader->corrupted = TRUE;
return;
}
- if (_DBUS_ALIGN_VALUE (header_len, 8) != (unsigned int) header_len)
+ if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
+ body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
+ {
+ _dbus_verbose ("Header or body length too large (%u %u)\n",
+ header_len_unsigned,
+ body_len_unsigned);
+ loader->corrupted = TRUE;
+ return;
+ }
+
+ /* Now that we know the values are in signed range, get
+ * rid of stupid unsigned, just causes bugs
+ */
+ header_len = header_len_unsigned;
+ body_len = body_len_unsigned;
+
+ if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
{
_dbus_verbose ("header length %d is not aligned to 8 bytes\n",
header_len);
return;
}
- if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
+ if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
{
HeaderField fields[FIELD_LAST];
int i;
<sect2 id="message-protocol-header-encoding">
<title>Header Encoding</title>
<para>
- [document the required header fields and how they are encoded]
+ Following the mandatory fields, there are zero or more named fields (see
+ <xref linkend="message-protocol-header-fields">), and then nul bytes
+ padding the header such that its total length in bytes is a multiple of
+ 8.
+ </para>
+ <para>
+ The header MUST begin with the following mandatory fields in the following
+ order:
+ <informaltable>
+ <tgroup cols=2>
+ <thead>
+ <row>
+ <entry>Size</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>1 byte</entry>
+ <entry>Endianness flag; ASCII 'l' for little-endian
+ or ASCII 'B' for big-endian.</entry>
+ </row>
+ <row>
+ <entry>1 byte</entry>
+ <entry>Bitwise OR of flags. Unknown flags
+ MUST be ignored. Currently-defined flags are described below.
+ </entry>
+ </row>
+ <row>
+ <entry>1 byte</entry>
+ <entry>Major protocol version of the sending application. If
+ the major protocol version of the receiving application does not
+ match, the applications will not be able to communicate and the
+ D-BUS connection MUST be disconnected. The major protocol
+ version for this version of the specification is 0.
+ </entry>
+ </row>
+ <row>
+ <entry>1 byte</entry>
+ <entry>A nul byte, reserved for future use.
+ Any value for this byte MUST be accepted.
+ </entry>
+ </row>
+ <row>
+ <entry>4 bytes</entry>
+ <entry>An unsigned 32-bit integer in the
+ message's byte order, indicating the total length in bytes of
+ the header including named fields and any alignment padding.
+ MUST be a multiple of 8.
+ </entry>
+ </row>
+ <row>
+ <entry>4 bytes</entry>
+ <entry>An unsigned 32-bit integer in the
+ message's byte order, indicating the total length in bytes of
+ the message body.
+ </entry>
+ </row>
+ <row>
+ <entry>4 bytes</entry>
+ <entry>The message's serial number, a signed 32-bit integer in
+ the message's byte order. Applications MUST NOT reuse the same
+ serial number for different messages more often than 32-bit
+ integer wraparound. Serial numbers must be greater than
+ zero.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ <para>
+ Flags that can appear in the second byte of the header:
+ <informaltable id="message-protocol-header-flags">
+ <tgroup cols=2>
+ <thead>
+ <row>
+ <entry>Hex value</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>0x1</entry>
+ <entry>This message is an error reply.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
</para>
</sect2>
invent their own header fields; only changes to
this specification may introduce new header fields.
</para>
+
</sect2>
+ <sect2 id="message-protocol-header-padding">
+ <title>Header Alignment Padding</title>
+ <para>
+ To allow implementations to keep the header and the body in a single
+ buffer while keeping data types aligned, the total length of the header
+ must be a multiple of 8 bytes. To achieve this, the header MUST be padded
+ with nul bytes to align its total length on an 8-byte boundary.
+ The minimum number of padding bytes MUST be used. Because all possible
+ named fields use at least 8 bytes, implementations can distinguish
+ padding (which must be less than 8 bytes) from additional named fields
+ (which must be at least 8 bytes).
+ </para>
+ </sect2>
+
<sect2 id="message-protocol-arguments">
<title>Message Arguments</title>
<para>