aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-dbus.c
diff options
context:
space:
mode:
authorSimon Holesch <simon@holesch.de>2020-11-29 00:22:24 +0100
committerWireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2020-12-01 10:54:45 +0000
commit6a0feb8d0a51fcb950591b1cfa0cb00cf83f3394 (patch)
treea1110c32f8f782336dc3de14fef5c5401ba9d55b /epan/dissectors/packet-dbus.c
parent2158ff241f4d7930bf626c5d52f55ddf93604ebf (diff)
D-Bus: Dissect complete messages
Improve the D-Bus dissector to support all types, including containers (arrays, structs, dict entries, variants). Add new protocol fields for D-Bus header fields like `dbus.destination` or `dbus.path` to make filtering for specific messages possible. Add lots of expert infos for possible errors. Update Info column to include method / signal name and path.
Diffstat (limited to 'epan/dissectors/packet-dbus.c')
-rw-r--r--epan/dissectors/packet-dbus.c1622
1 files changed, 1137 insertions, 485 deletions
diff --git a/epan/dissectors/packet-dbus.c b/epan/dissectors/packet-dbus.c
index 4c6b1149c5..4fd951c90f 100644
--- a/epan/dissectors/packet-dbus.c
+++ b/epan/dissectors/packet-dbus.c
@@ -1,6 +1,7 @@
/* packet-dbus.c
* Routines for D-Bus dissection
* Copyright 2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ * Copyright 2020, Simon Holesch <simon@holesch.de>
*
* Protocol specification available at http://dbus.freedesktop.org/doc/dbus-specification.html
*
@@ -11,18 +12,44 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-#define NEW_PROTO_TREE_API
-
#include "config.h"
#include <epan/packet.h>
#include <wiretap/wtap.h>
#include <epan/expert.h>
+#include <epan/ptvcursor.h>
#include "packet-tcp.h"
+#define DBUS_MAX_ARRAY_LEN (64 * 1024 * 1024)
+#define DBUS_MAX_NAME_LENGTH 255
+#define DBUS_MAX_SIGNATURE_LENGTH 255
+#define DBUS_MAX_TYPE_NESTING_LEVEL 32
+#define DBUS_MAX_TOTAL_NESTING_LEVEL (2 * DBUS_MAX_TYPE_NESTING_LEVEL)
+
+#define SIG_CODE_BYTE ('y')
+#define SIG_CODE_BOOLEAN ('b')
+#define SIG_CODE_INT16 ('n')
+#define SIG_CODE_UINT16 ('q')
+#define SIG_CODE_INT32 ('i')
+#define SIG_CODE_UINT32 ('u')
+#define SIG_CODE_INT64 ('x')
+#define SIG_CODE_UINT64 ('t')
+#define SIG_CODE_DOUBLE ('d')
+#define SIG_CODE_STRING ('s')
+#define SIG_CODE_OBJECT_PATH ('o')
+#define SIG_CODE_SIGNATURE ('g')
+#define SIG_CODE_ARRAY ('a')
+#define SIG_CODE_STRUCT_OPEN ('(')
+#define SIG_CODE_STRUCT_CLOSE (')')
+#define SIG_CODE_VARIANT ('v')
+#define SIG_CODE_DICT_ENTRY_OPEN ('{')
+#define SIG_CODE_DICT_ENTRY_CLOSE ('}')
+#define SIG_CODE_UNIX_FD ('h')
+
void proto_register_dbus(void);
void proto_reg_handoff_dbus(void);
+static int proto_dbus = -1;
static gboolean dbus_desegment = TRUE;
static dissector_handle_t dbus_handle;
@@ -55,550 +82,1080 @@ static const value_string message_type_vals[] = {
#define DBUS_HEADER_FIELD_UNIX_FDS 9
static const value_string field_code_vals[] = {
- { DBUS_HEADER_FIELD_INVALID, "INVALID" },
- { DBUS_HEADER_FIELD_PATH, "PATH" },
- { DBUS_HEADER_FIELD_INTERFACE, "INTERFACE" },
- { DBUS_HEADER_FIELD_MEMBER, "MEMBER" },
- { DBUS_HEADER_FIELD_ERROR_NAME, "ERROR_NAME" },
- { DBUS_HEADER_FIELD_REPLY_SERIAL, "REPLY_SERIAL" },
- { DBUS_HEADER_FIELD_DESTINATION, "DESTINATION" },
- { DBUS_HEADER_FIELD_SENDER, "SENDER" },
- { DBUS_HEADER_FIELD_SIGNATURE, "SIGNATURE" },
- { DBUS_HEADER_FIELD_UNIX_FDS, "UNIX_FDS" },
+ { DBUS_HEADER_FIELD_INVALID, "Invalid" },
+ { DBUS_HEADER_FIELD_PATH, "Path" },
+ { DBUS_HEADER_FIELD_INTERFACE, "Interface" },
+ { DBUS_HEADER_FIELD_MEMBER, "Member" },
+ { DBUS_HEADER_FIELD_ERROR_NAME, "Error name" },
+ { DBUS_HEADER_FIELD_REPLY_SERIAL, "Reply serial" },
+ { DBUS_HEADER_FIELD_DESTINATION, "Destination" },
+ { DBUS_HEADER_FIELD_SENDER, "Sender" },
+ { DBUS_HEADER_FIELD_SIGNATURE, "Signature" },
+ { DBUS_HEADER_FIELD_UNIX_FDS, "Unix FDs" },
{ 0, NULL }
};
-static header_field_info *hfi_dbus = NULL;
-
-#define DBUS_HFI_INIT HFI_INIT(proto_dbus)
-
-/* XXX, FT_NONE -> FT_BYTES? */
-
-/* Header */
-static header_field_info hfi_dbus_hdr DBUS_HFI_INIT =
- { "Header", "dbus.header", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL };
+static const value_string endianness_vals[] = {
+ { 'l', "little-endian" },
+ { 'B', "big-endian" },
+ { 0, NULL }
+};
+const true_false_string allow_vals = { "Allow", "Don't allow" };
+const true_false_string no_start_vals = { "Don't start", "Start" };
+const true_false_string not_expected_vals = { "Not expected", "Expected" };
+
+static int hf_dbus_endianness = -1;
+static int hf_dbus_message_type = -1;
+static int hf_dbus_flags = -1;
+static int hf_dbus_flags_no_reply_expected = -1;
+static int hf_dbus_flags_no_auto_start = -1;
+static int hf_dbus_flags_allow_interactive_authorization = -1;
+static int hf_dbus_version = -1;
+static int hf_dbus_body_length = -1;
+static int hf_dbus_serial = -1;
+static int hf_dbus_field_code = -1;
+static int hf_dbus_padding = -1;
+static int hf_dbus_path = -1;
+static int hf_dbus_interface = -1;
+static int hf_dbus_member = -1;
+static int hf_dbus_error_name = -1;
+static int hf_dbus_reply_serial = -1;
+static int hf_dbus_destination = -1;
+static int hf_dbus_sender = -1;
+static int hf_dbus_signature = -1;
+static int hf_dbus_unix_fds = -1;
+static int hf_dbus_body = -1;
+static int hf_dbus_type_byte = -1;
+static int hf_dbus_type_boolean = -1;
+static int hf_dbus_type_int16 = -1;
+static int hf_dbus_type_uint16 = -1;
+static int hf_dbus_type_int32 = -1;
+static int hf_dbus_type_uint32 = -1;
+static int hf_dbus_type_int64 = -1;
+static int hf_dbus_type_uint64 = -1;
+static int hf_dbus_type_double = -1;
+static int hf_dbus_type_string = -1;
+static int hf_dbus_type_object_path = -1;
+static int hf_dbus_type_signature = -1;
+static int hf_dbus_type_array = -1;
+static int hf_dbus_type_array_length = -1;
+static int hf_dbus_type_struct = -1;
+static int hf_dbus_type_variant = -1;
+static int hf_dbus_type_variant_signature = -1;
+static int hf_dbus_type_dict_entry = -1;
+static int hf_dbus_type_dict_entry_key = -1;
+static int hf_dbus_type_unix_fd = -1;
-static header_field_info hfi_dbus_hdr_endianness DBUS_HFI_INIT =
- { "Endianness Flag", "dbus.endianness", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL };
+static int ett_dbus = -1;
+static int ett_dbus_flags = -1;
+static int ett_dbus_header_field_array = -1;
+static int ett_dbus_header_field = -1;
+static int ett_dbus_body = -1;
+static int ett_dbus_type_array = -1;
+static int ett_dbus_type_struct = -1;
+static int ett_dbus_type_variant = -1;
+static int ett_dbus_type_dict_entry = -1;
+
+static expert_field ei_dbus_endianness_invalid = EI_INIT;
+static expert_field ei_dbus_message_type_invalid = EI_INIT;
+static expert_field ei_dbus_message_type_unknown = EI_INIT;
+static expert_field ei_dbus_version_invalid = EI_INIT;
+static expert_field ei_dbus_serial_invalid = EI_INIT;
+static expert_field ei_dbus_field_code_invalid = EI_INIT;
+static expert_field ei_dbus_required_header_field_missing = EI_INIT;
+static expert_field ei_dbus_padding_invalid = EI_INIT;
+static expert_field ei_dbus_field_signature_wrong = EI_INIT;
+static expert_field ei_dbus_interface_invalid = EI_INIT;
+static expert_field ei_dbus_member_invalid = EI_INIT;
+static expert_field ei_dbus_error_name_invalid = EI_INIT;
+static expert_field ei_dbus_bus_name_invalid = EI_INIT;
+static expert_field ei_dbus_type_boolean_invalid = EI_INIT;
+static expert_field ei_dbus_string_invalid = EI_INIT;
+static expert_field ei_dbus_type_signature_invalid = EI_INIT;
+static expert_field ei_dbus_type_array_too_long = EI_INIT;
+static expert_field ei_dbus_type_array_content_out_of_bounds = EI_INIT;
+static expert_field ei_dbus_type_object_path_invalid = EI_INIT;
+static expert_field ei_dbus_type_variant_signature_invalid = EI_INIT;
+static expert_field ei_dbus_nested_too_deeply = EI_INIT;
-static header_field_info hfi_dbus_hdr_type DBUS_HFI_INIT =
- { "Message Type", "dbus.type", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x00, NULL, HFILL };
+typedef struct {
+ ptvcursor_t *cursor;
+ packet_info *pinfo;
+ guint enc;
+ guint32 message_type;
+ guint32 body_len;
+ guint32 serial;
+
+ proto_item *current_pi;
+ const char *path;
+ const char *interface;
+ const char *member;
+ const char *error_name;
+ guint32 reply_serial;
+ const char *destination;
+ const char *sender;
+ const char *signature;
+ guint32 unix_fds;
+} dbus_packet_t;
+
+typedef struct _dbus_type_reader_t {
+ dbus_packet_t *packet;
+ const char *signature;
+ guint32 level;
+ guint32 array_level;
+ guint32 struct_level;
+ guint32 dict_entry_level;
+ const char *array_type_start;
+ int array_end_offset;
+ gboolean is_in_variant;
+ gboolean is_basic_variant;
+ gboolean is_in_dict_entry;
+ gboolean is_basic_dict_entry;
+ proto_item *container;
+ struct _dbus_type_reader_t *parent;
+} dbus_type_reader_t;
-static header_field_info hfi_dbus_hdr_flags DBUS_HFI_INIT =
- { "Message Flags", "dbus.flags", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL };
+typedef union {
+ gboolean bool_;
+ guint32 uint;
+ gint32 int_;
+ guint64 uint64;
+ gint64 int64;
+ double double_;
+ const char *string;
+} dbus_val_t;
-static header_field_info hfi_dbus_hdr_version DBUS_HFI_INIT =
- { "Protocol Version", "dbus.version", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL };
+static gboolean
+is_ascii_digit(char c) {
+ return (guint)c - '0' < 10;
+}
-static header_field_info hfi_dbus_hdr_body_length DBUS_HFI_INIT =
- { "Message body Length", "dbus.length", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
+static gboolean
+is_ascii_alpha(char c) {
+ return ((guint)c | 0x20) - 'a' <= 'z' - 'a';
+}
-static header_field_info hfi_dbus_hdr_serial DBUS_HFI_INIT =
- { "Message Serial (cookie)", "dbus.serial", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
+static gboolean
+is_dbus_object_path_valid(const char *path) {
+ // - The path may be of any length.
+ // - The path must begin with an ASCII '/' (integer 47) character, and must consist of elements separated by
+ // slash characters.
+ // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
+ // - No element may be the empty string.
+ // - Multiple '/' characters cannot occur in sequence.
+ // - A trailing '/' character is not allowed unless the path is the root path (a single '/' character).
+ if (*path == '/' && *(path + 1) == '\0') {
+ return TRUE;
+ }
-static header_field_info hfi_dbus_hdr_fields_length DBUS_HFI_INIT =
- { "Header fields Length", "dbus.fields_length", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
+ while (*path == '/') {
+ path++;
-/* Header field */
-static header_field_info hfi_dbus_hdr_field DBUS_HFI_INIT =
- { "Header Field", "dbus.field", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL };
+ if (*path == '/') {
+ return FALSE;
+ }
-static header_field_info hfi_dbus_hdr_field_code DBUS_HFI_INIT =
- { "Field code", "dbus.field.code", FT_UINT8, BASE_DEC, VALS(field_code_vals), 0x00, NULL, HFILL };
+ while (is_ascii_alpha(*path) || is_ascii_digit(*path) || *path == '_') {
+ path++;
+ }
-static header_field_info hfi_dbus_type_signature DBUS_HFI_INIT =
- { "Type signature", "dbus.type_signature", FT_STRINGZ, BASE_NONE, NULL, 0x00, NULL, HFILL };
+ if (*path == '\0') {
+ return *(path - 1) != '/';
+ }
+ }
-static header_field_info hfi_dbus_body DBUS_HFI_INIT =
- { "Body", "dbus.body", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL };
+ return FALSE;
+}
-/* Values */
-static header_field_info hfi_dbus_value_bool DBUS_HFI_INIT =
- { "Value", "dbus.value.bool", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL };
+static gboolean
+is_dbus_interface_valid(const char *interface) {
+ // - Interface names are composed of 2 or more elements separated by a period ('.') character. All elements
+ // must contain at least one character.
+ // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_" and must not begin with a digit.
+ // - Interface names must not exceed the maximum name length.
+ gint elements = 0;
+ const char *p = interface;
+ do {
+ if (!(is_ascii_alpha(*p) || *p == '_')) {
+ return FALSE;
+ }
+ p++;
+ elements++;
-static header_field_info hfi_dbus_value_int DBUS_HFI_INIT =
- { "Value", "dbus.value.int", FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
+ while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_') {
+ p++;
+ }
-static header_field_info hfi_dbus_value_uint DBUS_HFI_INIT =
- { "Value", "dbus.value.uint", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL };
+ if (*p == '\0') {
+ size_t length = p - interface;
+ return elements >= 2 && length <= DBUS_MAX_NAME_LENGTH;
+ }
+ } while (*p++ == '.');
-static header_field_info hfi_dbus_value_str DBUS_HFI_INIT =
- { "Value", "dbus.value.str", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL };
+ return FALSE;
+}
-static header_field_info hfi_dbus_value_double DBUS_HFI_INIT =
- { "DOUBLE", "dbus.value.double", FT_DOUBLE, BASE_NONE, NULL, 0x00, NULL, HFILL };
+static gboolean
+is_dbus_member_name_valid(const char *member_name) {
+ // - Must only contain the ASCII characters "[A-Z][a-z][0-9]_" and may not begin with a digit.
+ // - Must not contain the '.' (period) character.
+ // - Must not exceed the maximum name length.
+ // - Must be at least 1 byte in length.
+ const char *p = member_name;
+
+ if (!(is_ascii_alpha(*p) || *p == '_')) {
+ return FALSE;
+ }
+ do {
+ p++;
+ } while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_');
-static int ett_dbus = -1;
-static int ett_dbus_hdr = -1;
-static int ett_dbus_body = -1;
-static int ett_dbus_field = -1;
+ if (*p == '\0') {
+ size_t length = p - member_name;
+ return length <= DBUS_MAX_NAME_LENGTH;
+ }
-static expert_field ei_dbus_value_bool_invalid = EI_INIT;
-static expert_field ei_dbus_value_str_invalid = EI_INIT;
-static expert_field ei_dbus_invalid_object_path = EI_INIT;
-static expert_field ei_dbus_invalid_signature = EI_INIT;
+ return FALSE;
+}
-typedef struct {
- packet_info *pinfo;
+static gboolean
+is_dbus_bus_name_valid(const char *bus_name) {
+ // - Bus names that start with a colon (':') character are unique connection names. Other bus names are called
+ // well-known bus names.
+ // - Bus names are composed of 1 or more elements separated by a period ('.') character. All elements must
+ // contain at least one character.
+ // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-", with "-" discouraged in new bus
+ // names. Only elements that are part of a unique connection name may begin with a digit, elements in other
+ // bus names must not begin with a digit.
+ // - Bus names must contain at least one '.' (period) character (and thus at least two elements).
+ // - Bus names must not begin with a '.' (period) character.
+ // - Bus names must not exceed the maximum name length.
+ gint elements = 0;
+ const char *p = bus_name;
+ gboolean is_unique_name = FALSE;
+
+ if (*p == ':') {
+ is_unique_name = TRUE;
+ p++;
+ }
- guint16 (*get16)(tvbuff_t *, const gint);
- guint32 (*get32)(tvbuff_t *, const gint);
- gdouble (*getdouble)(tvbuff_t *, const gint);
- int enc;
+ do {
+ if (!(is_ascii_alpha(*p) || *p == '_' || *p == '-' || (is_unique_name && is_ascii_digit(*p)))) {
+ return FALSE;
+ }
+ p++;
+ elements++;
- guint32 body_len;
- guint32 fields_len;
- const char *body_sig;
-} dbus_info_t;
+ while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_' || *p == '-') {
+ p++;
+ }
-typedef union {
- char *str;
- guint uint;
+ if (*p == '\0') {
+ size_t length = p - bus_name;
+ return elements >= 2 && length <= DBUS_MAX_NAME_LENGTH;
+ }
+ } while (*p++ == '.');
-} dbus_val_t;
+ return FALSE;
+}
static gboolean
-dbus_validate_object_path(const char *path)
-{
- /* XXX check */
- if (*path != '/')
+is_basic_type(char sig_code) {
+ switch (sig_code) {
+ case SIG_CODE_BYTE:
+ case SIG_CODE_BOOLEAN:
+ case SIG_CODE_INT16:
+ case SIG_CODE_UINT16:
+ case SIG_CODE_INT32:
+ case SIG_CODE_UINT32:
+ case SIG_CODE_INT64:
+ case SIG_CODE_UINT64:
+ case SIG_CODE_DOUBLE:
+ case SIG_CODE_STRING:
+ case SIG_CODE_OBJECT_PATH:
+ case SIG_CODE_SIGNATURE:
+ case SIG_CODE_UNIX_FD:
+ return TRUE;
+ default:
return FALSE;
+ }
+}
- do {
- path++;
+static gboolean
+is_dbus_signature_valid(const char *signature) {
+ char sig_code;
+ size_t length = 0;
+ wmem_stack_t *expected_chars = wmem_stack_new(wmem_packet_scope());
- if (*path == '/')
+ while ((sig_code = *signature++) != '\0') {
+ if (++length >= DBUS_MAX_SIGNATURE_LENGTH) {
return FALSE;
+ }
- while ((*path >= 'A' && *path <= 'Z') || (*path >= 'a' && *path <= 'z') || (*path >= '0' && *path <= '9') || *path == '_')
- path++;
-
- if (*path == '\0')
- return TRUE;
+ switch (sig_code) {
+ case SIG_CODE_BYTE:
+ case SIG_CODE_SIGNATURE:
+ case SIG_CODE_VARIANT:
+ case SIG_CODE_INT16:
+ case SIG_CODE_UINT16:
+ case SIG_CODE_INT32:
+ case SIG_CODE_UINT32:
+ case SIG_CODE_BOOLEAN:
+ case SIG_CODE_OBJECT_PATH:
+ case SIG_CODE_STRING:
+ case SIG_CODE_UNIX_FD:
+ case SIG_CODE_INT64:
+ case SIG_CODE_UINT64:
+ case SIG_CODE_DOUBLE:
+ break;
+ case SIG_CODE_ARRAY:
+ if (*signature == '\0') {
+ // arrays must be followed by a single complete type
+ return FALSE;
+ }
+ break;
+ case SIG_CODE_STRUCT_OPEN:
+ wmem_stack_push(expected_chars, (void *)SIG_CODE_STRUCT_CLOSE);
+ break;
+ case SIG_CODE_DICT_ENTRY_OPEN:
+ if (!is_basic_type(*signature)) {
+ // key of dict entry must be a basic type
+ return FALSE;
+ }
+ wmem_stack_push(expected_chars, (void *)SIG_CODE_DICT_ENTRY_CLOSE);
+ break;
+ case SIG_CODE_STRUCT_CLOSE:
+ case SIG_CODE_DICT_ENTRY_CLOSE:
+ if (wmem_stack_count(expected_chars) == 0 ||
+ (char)(guintptr)wmem_stack_pop(expected_chars) != sig_code) {
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ return wmem_stack_count(expected_chars) == 0;
+}
- } while (*path == '/');
+static void
+add_expert(dbus_packet_t *packet, expert_field *ei) {
+ expert_add_info(packet->pinfo, packet->current_pi, ei);
+}
- return FALSE;
+static guint32
+add_uint(dbus_packet_t *packet, gint hf) {
+ header_field_info *info = proto_registrar_get_nth(hf);
+ gint length;
+ guint32 value;
+ switch (info->type) {
+ case FT_UINT8:
+ length = 1;
+ break;
+ case FT_UINT32:
+ length = 4;
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ packet->current_pi = ptvcursor_add_ret_uint(packet->cursor, hf, length, packet->enc, &value);
+ return value;
}
-static gboolean
-dbus_validate_signature(const char *sig _U_)
-{
- /* XXX implement */
- return TRUE;
+static const guint8 *
+add_dbus_string(dbus_packet_t *packet, int hf, gint uint_length) {
+ const guint8 *string;
+ gint start_offset = ptvcursor_current_offset(packet->cursor);
+ proto_item *pi = ptvcursor_add_ret_string(packet->cursor, hf, uint_length,
+ packet->enc | ENC_UTF_8, wmem_packet_scope(), &string);
+ gint item_length = ptvcursor_current_offset(packet->cursor) - start_offset;
+ guint8 term_byte = tvb_get_guint8(ptvcursor_tvbuff(packet->cursor), ptvcursor_current_offset(packet->cursor));
+ proto_item_set_len(pi, item_length + 1);
+ ptvcursor_advance(packet->cursor, 1);
+ packet->current_pi = pi;
+
+ if ((strlen(string) != (size_t)(item_length - uint_length)) || (term_byte != '\0')) {
+ col_add_fstr(packet->pinfo->cinfo, COL_INFO, "%zu %zu %s", strlen(string), (size_t)(item_length - uint_length), string);
+ return NULL;
+ }
+ return string;
}
static int
-dbus_type_alignment(char sig)
-{
+calculate_padding_len(gint offset, char sig) {
+ int alignment;
switch (sig) {
- case 'y':
- case 'g':
- return 1;
- case 'n':
- case 'q':
- return 2;
- case 'i':
- case 'u':
- case 'b':
- case 'o':
- case 'a':
- case 's':
- return 4;
- case 'x':
- case 't':
- case 'd':
- return 8;
- /* ... */
- default:
- return 1;
+ case SIG_CODE_BYTE:
+ case SIG_CODE_SIGNATURE:
+ case SIG_CODE_VARIANT:
+ default:
+ alignment = 1;
+ break;
+ case SIG_CODE_INT16:
+ case SIG_CODE_UINT16:
+ alignment = 2;
+ break;
+ case SIG_CODE_INT32:
+ case SIG_CODE_UINT32:
+ case SIG_CODE_BOOLEAN:
+ case SIG_CODE_OBJECT_PATH:
+ case SIG_CODE_ARRAY:
+ case SIG_CODE_STRING:
+ case SIG_CODE_UNIX_FD:
+ alignment = 4;
+ break;
+ case SIG_CODE_INT64:
+ case SIG_CODE_UINT64:
+ case SIG_CODE_DOUBLE:
+ case SIG_CODE_STRUCT_OPEN:
+ case SIG_CODE_DICT_ENTRY_OPEN:
+ alignment = 8;
+ break;
}
+ return (alignment - (offset % alignment)) % alignment;
}
static int
-dissect_dbus_sig(tvbuff_t *tvb, dbus_info_t *dinfo, proto_tree *tree, int offset, char sig, dbus_val_t *ret)
-{
- proto_item *ti;
- const int align = dbus_type_alignment(sig);
- const int org_offset = (offset + align - 1) / align * align;
- offset = org_offset;
-
- switch (sig) {
- case 'y': /* BYTE */
- {
- guint8 val;
-
- val = tvb_get_guint8(tvb, offset);
- offset += 1;
-
- proto_tree_add_uint_format(tree, &hfi_dbus_value_uint, tvb, org_offset, offset - org_offset, val, "BYTE: %u", val);
- ret->uint = val;
- return offset;
+add_padding(dbus_packet_t *packet, char sig) {
+ guint8 value;
+ tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
+ gint offset = ptvcursor_current_offset(packet->cursor);
+ gint padding_len = calculate_padding_len(offset, sig);
+
+ if (padding_len != 0) {
+ packet->current_pi = ptvcursor_add(packet->cursor, hf_dbus_padding, padding_len, packet->enc);
+ for (gint i = offset; i < (offset + padding_len); i++) {
+ value = tvb_get_guint8(tvb, i);
+ if (value != 0) {
+ add_expert(packet, &ei_dbus_padding_invalid);
+ return 1;
+ }
}
+ proto_item_set_hidden(packet->current_pi);
+ }
+ return 0;
+}
- case 'b': /* BOOLEAN */
- {
- guint32 val;
-
- val = dinfo->get32(tvb, offset);
- offset += 4;
-
- ti = proto_tree_add_boolean_format(tree, &hfi_dbus_value_bool, tvb, org_offset, offset - org_offset, val, "BOOLEAN: %s", val ? "True" : "False");
- if (val != 0 && val != 1) {
- expert_add_info_format(dinfo->pinfo, ti, &ei_dbus_value_bool_invalid, "Invalid boolean value (must be 0 or 1 is: %u)", val);
- return -1;
+static const char *
+skip_enclosed_container(const char *signature, char open_bracket, char closed_bracket) {
+ int nested = 0;
+ for (char sig_code = *signature++; sig_code != '\0'; sig_code = *signature++) {
+ if (sig_code == closed_bracket) {
+ if (nested == 0) {
+ return signature;
}
- ret->uint = val;
- return offset;
+ nested--;
+ } else if (sig_code == open_bracket) {
+ nested++;
}
+ }
+ return NULL;
+}
- case 'n': /* INT16 */
- {
- gint16 val;
-
- val = (gint16 )dinfo->get16(tvb, offset);
- offset += 2;
-
- proto_tree_add_uint_format(tree, &hfi_dbus_value_int, tvb, org_offset, offset - org_offset, val, "INT16: %d", val);
- /* XXX ret */
- return offset;
+static const char *
+skip_single_complete_type(const char *signature) {
+ char sig_code;
+ while (1) {
+ sig_code = *signature++;
+ switch (sig_code) {
+ case SIG_CODE_BYTE:
+ case SIG_CODE_BOOLEAN:
+ case SIG_CODE_INT16:
+ case SIG_CODE_UINT16:
+ case SIG_CODE_INT32:
+ case SIG_CODE_UINT32:
+ case SIG_CODE_INT64:
+ case SIG_CODE_UINT64:
+ case SIG_CODE_DOUBLE:
+ case SIG_CODE_STRING:
+ case SIG_CODE_OBJECT_PATH:
+ case SIG_CODE_SIGNATURE:
+ case SIG_CODE_VARIANT:
+ case SIG_CODE_UNIX_FD:
+ return signature;
+ case SIG_CODE_ARRAY:
+ continue;
+ case SIG_CODE_STRUCT_OPEN:
+ return skip_enclosed_container(signature, SIG_CODE_STRUCT_OPEN, SIG_CODE_STRUCT_CLOSE);
+ case SIG_CODE_DICT_ENTRY_OPEN:
+ return skip_enclosed_container(signature, SIG_CODE_DICT_ENTRY_OPEN, SIG_CODE_DICT_ENTRY_CLOSE);
+ default:
+ return NULL;
}
+ }
+}
- case 'q': /* UINT16 */
- {
- guint16 val;
-
- val = dinfo->get16(tvb, offset);
- offset += 2;
-
- proto_tree_add_uint_format(tree, &hfi_dbus_value_uint, tvb, org_offset, offset - org_offset, val, "UINT16: %u", val);
- ret->uint = val;
- return offset;
+static dbus_type_reader_t *
+reader_next(dbus_type_reader_t *reader, int hf, int ett, dbus_val_t *value) {
+ int err = 0;
+ char sig_code = *reader->signature++;
+ dbus_packet_t *packet = reader->packet;
+ gboolean is_single_complete_type = TRUE;
+ add_padding(packet, sig_code);
+
+ switch (sig_code) {
+ case SIG_CODE_BYTE:
+ packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_byte, 1, packet->enc, &value->uint);
+ break;
+ case SIG_CODE_BOOLEAN: {
+ gint offset = ptvcursor_current_offset(packet->cursor);
+ tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
+ guint8 val = tvb_get_guint8(tvb, offset);
+ packet->current_pi = ptvcursor_add_ret_boolean(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_boolean, 4, packet->enc, &value->bool_);
+ if (val >= 2) {
+ add_expert(packet, &ei_dbus_type_boolean_invalid);
+ err = 1;
}
-
- case 'i': /* INT32 */
- {
- gint32 val;
-
- val = (gint32) dinfo->get32(tvb, offset);
- offset += 4;
-
- proto_tree_add_int_format(tree, &hfi_dbus_value_int, tvb, org_offset, offset - org_offset, val, "INT32: %d", val);
- /* XXX ret */
- return offset;
+ break;
+ }
+ case SIG_CODE_INT16:
+ packet->current_pi = ptvcursor_add_ret_int(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_int16, 2, packet->enc, &value->int_);
+ break;
+ case SIG_CODE_UINT16:
+ packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_uint16, 2, packet->enc, &value->uint);
+ break;
+ case SIG_CODE_INT32:
+ packet->current_pi = ptvcursor_add_ret_int(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_int32, 4, packet->enc, &value->int_);
+ break;
+ case SIG_CODE_UINT32:
+ packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_uint32, 4, packet->enc, &value->uint);
+ break;
+ case SIG_CODE_INT64: {
+ gint offset = ptvcursor_current_offset(packet->cursor);
+ tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
+ value->int64 = tvb_get_gint64(tvb, offset, packet->enc);
+ packet->current_pi = ptvcursor_add(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_int64, 8, packet->enc);
+ break;
+ }
+ case SIG_CODE_UINT64: {
+ gint offset = ptvcursor_current_offset(packet->cursor);
+ tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
+ value->uint64 = tvb_get_guint64(tvb, offset, packet->enc);
+ packet->current_pi = ptvcursor_add(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_uint64, 8, packet->enc);
+ break;
+ }
+ case SIG_CODE_DOUBLE: {
+ gint offset = ptvcursor_current_offset(packet->cursor);
+ tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
+ value->double_ = tvb_get_ieee_double(tvb, offset, packet->enc);
+ packet->current_pi = ptvcursor_add(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_double, 8, packet->enc);
+ break;
+ }
+ case SIG_CODE_STRING: {
+ const char *val = add_dbus_string(packet,
+ hf != -1 ? hf : hf_dbus_type_string, 4);
+ if (!val || !g_utf8_validate(val, -1, NULL)) {
+ add_expert(packet, &ei_dbus_string_invalid);
+ err = 1;
}
-
- case 'u': /* UINT32 */
- {
- guint32 val;
-
- val = dinfo->get32(tvb, offset);
- offset += 4;
-
- proto_tree_add_uint_format(tree, &hfi_dbus_value_uint, tvb, org_offset, offset - org_offset, val, "UINT32: %u", val);
- ret->uint = val;
- return offset;
+ value->string = val;
+ break;
+ }
+ case SIG_CODE_OBJECT_PATH: {
+ const char *val = add_dbus_string(packet, hf != -1 ? hf : hf_dbus_type_object_path, 4);
+ if (!val || !is_dbus_object_path_valid(val)) {
+ add_expert(packet, &ei_dbus_type_object_path_invalid);
+ err = 1;
}
-
- case 'x': /* INT64 */
- case 't': /* UINT64 */
- return -1;
-
- case 'd': /* DOUBLE */
- {
- gdouble val;
-
- val = dinfo->getdouble(tvb, offset);
- offset += 8;
-
- proto_tree_add_double(tree, &hfi_dbus_value_double, tvb, org_offset, offset - org_offset, val);
- /* XXX ret */
- return offset;
+ value->string = val;
+ break;
+ }
+ case SIG_CODE_SIGNATURE: {
+ const char *val = add_dbus_string(packet, hf != -1 ? hf : hf_dbus_type_signature, 1);
+ if (!val || !is_dbus_signature_valid(val)) {
+ add_expert(packet, &ei_dbus_type_signature_invalid);
+ err = 1;
}
+ value->string = val;
+ break;
+ }
+ case SIG_CODE_ARRAY: {
+ is_single_complete_type = FALSE;
+ proto_item *array = ptvcursor_add_with_subtree(packet->cursor, hf != -1 ? hf : hf_dbus_type_array,
+ SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_array);
+ if (*reader->signature == SIG_CODE_DICT_ENTRY_OPEN) {
+ proto_item_append_text(array, " (Dict)");
+ }
+ guint32 array_len = add_uint(packet, hf_dbus_type_array_length);
+ value->uint = array_len;
+ add_padding(packet, *reader->signature);
+ if (array_len == 0) {
+ reader->signature = skip_single_complete_type(reader->signature);
+ if (reader->signature == NULL) {
+ err = 1;
+ }
+ ptvcursor_pop_subtree(packet->cursor);
+ is_single_complete_type = TRUE;
+ } else if (array_len <= DBUS_MAX_ARRAY_LEN) {
+ int end_offset = ptvcursor_current_offset(packet->cursor) + array_len;
+ dbus_type_reader_t *child = (dbus_type_reader_t *)wmem_alloc(
+ wmem_packet_scope(), sizeof(dbus_type_reader_t));
+ *child = (dbus_type_reader_t){
+ .packet = reader->packet,
+ .signature = reader->signature,
+ .level = reader->level + 1,
+ .array_level = reader->array_level + 1,
+ .array_type_start = reader->signature,
+ .array_end_offset = end_offset,
+ .container = array,
+ .parent = reader,
+ };
+ reader = child;
+ } else {
+ add_expert(packet, &ei_dbus_type_array_too_long);
+ err = 1;
+ ptvcursor_pop_subtree(packet->cursor);
+ }
+ break;
+ }
+ case SIG_CODE_STRUCT_OPEN: {
+ is_single_complete_type = FALSE;
+ ptvcursor_add_with_subtree(packet->cursor, hf != -1 ? hf : hf_dbus_type_struct,
+ SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_struct);
+ dbus_type_reader_t *child = (dbus_type_reader_t *)wmem_alloc(
+ wmem_packet_scope(), sizeof(dbus_type_reader_t));
+ *child = (dbus_type_reader_t){
+ .packet = reader->packet,
+ .signature = reader->signature,
+ .level = reader->level + 1,
+ .struct_level = reader->struct_level + 1,
+ .parent = reader,
+ };
+ reader = child;
+ break;
+ }
+ case SIG_CODE_VARIANT: {
+ is_single_complete_type = FALSE;
+ proto_item *variant = ptvcursor_add_with_subtree(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_variant,
+ SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_variant);
+ const char *variant_signature = add_dbus_string(packet, hf_dbus_type_variant_signature, 1);
+ value->string = variant_signature;
+ if (variant_signature && is_dbus_signature_valid(variant_signature)) {
+ dbus_type_reader_t *child = (dbus_type_reader_t *)wmem_alloc(
+ wmem_packet_scope(), sizeof(dbus_type_reader_t));
+ *child = (dbus_type_reader_t){
+ .packet = reader->packet,
+ .signature = variant_signature,
+ .level = reader->level + 1,
+ .is_in_variant = TRUE,
+ .is_basic_variant = is_basic_type(*variant_signature)
+ && *(variant_signature + 1) == '\0',
+ .container = variant,
+ .parent = reader,
+ };
+ if (reader->is_in_dict_entry && child->is_basic_variant) {
+ reader->is_basic_dict_entry = TRUE;
+ }
+ reader = child;
+ } else {
+ add_expert(packet, &ei_dbus_type_variant_signature_invalid);
+ err = 1;
+ ptvcursor_pop_subtree(packet->cursor);
+ }
+ break;
+ }
+ case SIG_CODE_DICT_ENTRY_OPEN: {
+ is_single_complete_type = FALSE;
+ proto_item *dict_entry = ptvcursor_add_with_subtree(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_dict_entry,
+ SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_dict_entry);
+ dbus_type_reader_t *child = (dbus_type_reader_t *)wmem_alloc(
+ wmem_packet_scope(), sizeof(dbus_type_reader_t));
+ *child = (dbus_type_reader_t){
+ .packet = reader->packet,
+ .signature = reader->signature,
+ .level = reader->level + 1,
+ .dict_entry_level = reader->dict_entry_level + 1,
+ .is_in_dict_entry = TRUE,
+ .is_basic_dict_entry = is_basic_type(*(reader->signature + 1)),
+ .container = dict_entry,
+ .parent = reader,
+ };
+ reader = child;
+ break;
+ }
+ case SIG_CODE_STRUCT_CLOSE:
+ case SIG_CODE_DICT_ENTRY_CLOSE:
+ ptvcursor_pop_subtree(packet->cursor);
+ reader->parent->signature = reader->signature;
+ reader = reader->parent;
+ break;
+ case SIG_CODE_UNIX_FD:
+ packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
+ hf != -1 ? hf : hf_dbus_type_unix_fd, 4, packet->enc, &value->uint);
+ break;
+ default:
+ // all signatures are validated
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
- case 's': /* STRING */
- case 'o': /* OBJECT_PATH */
- {
- guint32 len;
- char *val;
-
- len = dinfo->get32(tvb, offset);
- offset += 4;
-
- val = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_ASCII);
- offset += (len + 1 /* NUL-byte */);
-
- if (sig == 's') {
- ti = proto_tree_add_string_format(tree, &hfi_dbus_value_str, tvb, org_offset, offset - org_offset, val, "STRING: %s", val);
- if (!g_utf8_validate(val, -1, NULL)) {
- expert_add_info(dinfo->pinfo, ti, &ei_dbus_value_str_invalid);
- return -1;
+ if (reader->level > DBUS_MAX_TOTAL_NESTING_LEVEL ||
+ reader->array_level > DBUS_MAX_TYPE_NESTING_LEVEL ||
+ reader->struct_level > DBUS_MAX_TYPE_NESTING_LEVEL ||
+ reader->dict_entry_level > DBUS_MAX_TYPE_NESTING_LEVEL) {
+ add_expert(packet, &ei_dbus_nested_too_deeply);
+ err= 1;
+ } else if (is_single_complete_type) {
+ // Arrays and variants don't have a closing signature code, but they end after a single complete type.
+ // Close them here recursively, e.g. "aav"
+ while (1) {
+ if (reader->array_type_start) { // inside array
+ gint offset = ptvcursor_current_offset(packet->cursor);
+
+ if (offset < reader->array_end_offset) {
+ // parse next array element -> reset signature
+ reader->signature = reader->array_type_start;
+ break;
+ } else if (offset == reader->array_end_offset) {
+ // all array elements parsed
+ ptvcursor_pop_subtree(packet->cursor);
+ reader->parent->signature = reader->signature;
+ reader = reader->parent;
+ } else {
+ // array elements don't fit into array
+ expert_add_info(packet->pinfo, reader->container,
+ &ei_dbus_type_array_content_out_of_bounds);
+ err = 1;
+ break;
}
- } else {
- ti = proto_tree_add_string_format(tree, &hfi_dbus_value_str, tvb, org_offset, offset - org_offset, val, "OBJECT_PATH: %s", val);
- if (!dbus_validate_object_path(val)) {
- expert_add_info(dinfo->pinfo, ti, &ei_dbus_invalid_object_path);
- return -1;
+ } else if (reader->is_in_variant) {
+ if (reader->is_basic_variant) {
+ proto_item_append_text(reader->container, ": %s",
+ proto_item_get_display_repr(wmem_packet_scope(), packet->current_pi));
}
+ ptvcursor_pop_subtree(packet->cursor);
+ reader = reader->parent;
+ } else {
+ break;
}
- ret->str = val;
- return offset;
}
-
- case 'g': /* SIGNATURE */
- {
- guint8 len;
- char *val;
-
- len = tvb_get_guint8(tvb, offset);
- offset += 1;
-
- val = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_ASCII);
- offset += (len + 1);
-
- ti = proto_tree_add_string_format(tree, &hfi_dbus_value_str, tvb, org_offset, offset - org_offset, val, "SIGNATURE: %s", val);
- if (!dbus_validate_signature(val)) {
- expert_add_info(dinfo->pinfo, ti, &ei_dbus_invalid_signature);
- return -1;
+ if (reader->is_in_dict_entry) {
+ // add "key: value" to dict entry item to make it readable without expanding the tree
+ if (*(reader->signature - 2) == SIG_CODE_DICT_ENTRY_OPEN) { // == key
+ // key is always a basic type
+ proto_item_append_text(reader->container, ", %s",
+ proto_item_get_display_repr(wmem_packet_scope(), packet->current_pi));
+ } else if (reader->is_basic_dict_entry) { // == value
+ proto_item_append_text(reader->container, ": %s",
+ proto_item_get_display_repr(wmem_packet_scope(), packet->current_pi));
}
- ret->str = val;
- return offset;
}
+ }
- /* ... */
+ if (err) {
+ for (dbus_type_reader_t *r = reader; r->parent; r = r->parent) {
+ ptvcursor_pop_subtree(packet->cursor);
+ }
}
- return -1;
+ return !err ? reader : NULL;
}
-static int
-dissect_dbus_field_signature(tvbuff_t *tvb, packet_info *pinfo, dbus_info_t *dinfo, proto_tree *tree, int offset, int field_code)
-{
- const int org_offset = offset;
-
- proto_item *ti;
- guint sig_len;
- char *sig;
+static gboolean reader_is_finished(dbus_type_reader_t *reader) {
+ return *reader->signature == '\0' && reader->parent == NULL;
+}
- sig_len = tvb_get_guint8(tvb, offset);
- offset += 1;
+static int
+dissect_dbus_signature(dbus_packet_t *packet, const char *signature) {
+ dbus_type_reader_t root_reader = {
+ .packet = packet,
+ .signature = signature,
+ };
+ dbus_type_reader_t *reader = &root_reader;
+ dbus_val_t value;
+ while (!reader_is_finished(reader)) {
+ reader = reader_next(reader, -1, -1, &value);
+ if (!reader) {
+ return 1;
+ }
+ }
+ return 0;
+}
- /* sig_len = tvb_strsize(tvb, offset); */
+static int
+dissect_dbus_body(dbus_packet_t *packet) {
+ int err = 0;
+ if (packet->signature[0]) {
+ ptvcursor_add_with_subtree(packet->cursor, hf_dbus_body,
+ SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett_dbus_body);
+ err = dissect_dbus_signature(packet, packet->signature);
+ ptvcursor_pop_subtree(packet->cursor);
+ }
+ return err;
+}
- sig = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, sig_len, ENC_ASCII);
- offset += (sig_len + 1);
+static int
+dissect_dbus_header_fields(dbus_packet_t *packet) {
+ dbus_type_reader_t root_reader = {
+ .packet = packet,
+ .signature = "a{yv}",
+ };
+ dbus_type_reader_t *reader = &root_reader;
+ dbus_val_t value;
+#define NEXT_OR_RETURN(hf, ett) if (!(reader = reader_next(reader, hf, ett, &value))) return 1;
+
+ // Header Field Array
+ NEXT_OR_RETURN(-1, ett_dbus_header_field_array);
+ proto_item *header_field_array_pi = reader->container;
+ proto_item_set_text(header_field_array_pi, "Header Field Array");
+ while (reader->level > 0) {
+ // Header Field (Dict)
+ NEXT_OR_RETURN(-1, ett_dbus_header_field);
+ // Field Code
+ NEXT_OR_RETURN(hf_dbus_field_code, -1);
+ guint32 field_code = value.uint;
+ const gchar *field_code_str = val_to_str_const(field_code, field_code_vals, "Unknown field code");
+ proto_item_append_text(reader->container, ", %s", field_code_str);
+ if (field_code == DBUS_HEADER_FIELD_INVALID) {
+ add_expert(packet, &ei_dbus_field_code_invalid);
+ return 1;
+ }
- ti = proto_tree_add_string(tree, &hfi_dbus_type_signature, tvb, org_offset, offset - org_offset, sig);
- if (!dbus_validate_signature(sig)) {
- expert_add_info(dinfo->pinfo, ti, &ei_dbus_invalid_signature);
- return -1;
- }
+ // Header Field Value (Variant)
+ NEXT_OR_RETURN(-1, -1);
+ const char *header_field_signature = value.string;
- switch (field_code) {
+ const char *expected_signature;
+ switch (field_code) {
+ case DBUS_HEADER_FIELD_PATH:
+ expected_signature = "o";
+ break;
+ case DBUS_HEADER_FIELD_INTERFACE:
+ case DBUS_HEADER_FIELD_MEMBER:
+ case DBUS_HEADER_FIELD_ERROR_NAME:
+ case DBUS_HEADER_FIELD_DESTINATION:
+ case DBUS_HEADER_FIELD_SENDER:
+ expected_signature = "s";
+ break;
case DBUS_HEADER_FIELD_REPLY_SERIAL:
- if (!strcmp(sig, "u")) { /* UINT32 */
- dbus_val_t serial_val;
+ expected_signature = "u";
+ break;
+ case DBUS_HEADER_FIELD_UNIX_FDS:
+ expected_signature = "u";
+ break;
+ case DBUS_HEADER_FIELD_SIGNATURE:
+ expected_signature = "g";
+ break;
+ default:
+ expected_signature = NULL;
+ }
- offset = dissect_dbus_sig(tvb, dinfo, tree, offset, 'u', &serial_val);
- if (offset != -1)
- { /* XXX link with sending frame (serial_val.uint) */ }
- return offset;
+ if (expected_signature && strcmp(header_field_signature, expected_signature) != 0) {
+ add_expert(packet, &ei_dbus_field_signature_wrong);
+ return 1;
+ }
+
+ // Variant Value
+ switch (field_code) {
+ case DBUS_HEADER_FIELD_PATH:
+ NEXT_OR_RETURN(hf_dbus_path, -1);
+ packet->path = value.string;
+ break;
+ case DBUS_HEADER_FIELD_INTERFACE:
+ NEXT_OR_RETURN(hf_dbus_interface, -1);
+ packet->interface = value.string;
+ if (!is_dbus_interface_valid(packet->interface)) {
+ add_expert(packet, &ei_dbus_interface_invalid);
+ return 1;
+ }
+ break;
+ case DBUS_HEADER_FIELD_MEMBER:
+ NEXT_OR_RETURN(hf_dbus_member, -1);
+ packet->member = value.string;
+ if (!is_dbus_member_name_valid(packet->member)) {
+ add_expert(packet, &ei_dbus_member_invalid);
+ return 1;
+ }
+ break;
+ case DBUS_HEADER_FIELD_ERROR_NAME:
+ NEXT_OR_RETURN(hf_dbus_error_name, -1);
+ packet->error_name = value.string;
+ if (!is_dbus_interface_valid(packet->error_name)) {
+ add_expert(packet, &ei_dbus_error_name_invalid);
+ return 1;
}
break;
-
case DBUS_HEADER_FIELD_DESTINATION:
+ NEXT_OR_RETURN(hf_dbus_destination, -1);
+ packet->destination = value.string;
+ if (!is_dbus_bus_name_valid(packet->destination)) {
+ add_expert(packet, &ei_dbus_bus_name_invalid);
+ return 1;
+ }
+ set_address(&packet->pinfo->dst, AT_STRINGZ, (int)strlen(packet->destination)+1,
+ wmem_strdup(packet->pinfo->pool, packet->destination));
+ break;
case DBUS_HEADER_FIELD_SENDER:
- if (!strcmp(sig, "s")) { /* STRING */
- dbus_val_t addr_val;
-
- offset = dissect_dbus_sig(tvb, dinfo, tree, offset, 's', &addr_val);
- if (offset != -1)
- set_address((field_code == DBUS_HEADER_FIELD_DESTINATION) ? &dinfo->pinfo->dst : &dinfo->pinfo->src,
- AT_STRINGZ, (int)strlen(addr_val.str)+1, wmem_strdup(pinfo->pool, addr_val.str));
- return offset;
+ NEXT_OR_RETURN(hf_dbus_sender, -1);
+ packet->sender = value.string;
+ if (!is_dbus_bus_name_valid(packet->sender)) {
+ add_expert(packet, &ei_dbus_bus_name_invalid);
+ return 1;
}
+ set_address(&packet->pinfo->src, AT_STRINGZ, (int)strlen(packet->sender)+1,
+ wmem_strdup(packet->pinfo->pool, packet->sender));
break;
-
case DBUS_HEADER_FIELD_SIGNATURE:
- if (!strcmp(sig, "g")) { /* SIGNATURE */
- dbus_val_t sig_val;
-
- offset = dissect_dbus_sig(tvb, dinfo, tree, offset, 'g', &sig_val);
- if (offset != -1)
- dinfo->body_sig = sig_val.str;
- return offset;
+ NEXT_OR_RETURN(hf_dbus_signature, -1);
+ packet->signature = value.string;
+ break;
+ case DBUS_HEADER_FIELD_REPLY_SERIAL:
+ NEXT_OR_RETURN(hf_dbus_reply_serial, -1);
+ packet->reply_serial = value.uint;
+ if (packet->reply_serial == 0) {
+ add_expert(packet, &ei_dbus_serial_invalid);
+ return 1;
}
break;
+ case DBUS_HEADER_FIELD_UNIX_FDS:
+ NEXT_OR_RETURN(hf_dbus_unix_fds, -1);
+ packet->unix_fds = value.uint;
+ break;
+ default:
+ // Unknown Field code must be skipped without error
+ do {
+ NEXT_OR_RETURN(-1, -1);
+ // Skip while inside Header Field Array -> Header Field Dict -> Variant
+ } while (reader->level >= 3);
+ }
+ // end of dict
+ NEXT_OR_RETURN(-1, -1);
}
- while (*sig) {
- dbus_val_t val;
-
- offset = dissect_dbus_sig(tvb, dinfo, tree, offset, *sig, &val);
- if (offset == -1)
- return -1;
- sig++;
+ gboolean is_field_missing = FALSE;
+ switch (packet->message_type) {
+ case DBUS_MESSAGE_TYPE_METHOD_CALL:
+ is_field_missing = !packet->path || !packet->member;
+ break;
+ case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+ is_field_missing = !packet->reply_serial;
+ break;
+ case DBUS_MESSAGE_TYPE_ERROR:
+ is_field_missing = !packet->error_name || !packet->reply_serial;
+ break;
+ case DBUS_MESSAGE_TYPE_SIGNAL:
+ is_field_missing = !packet->path || !packet->interface || !packet->member;
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ break;
}
- return offset;
-}
-
-static int
-dissect_dbus_hdr_fields(tvbuff_t *tvb, packet_info *pinfo, dbus_info_t *dinfo, proto_tree *tree, int offset)
-{
- int end_offset;
-
- end_offset = offset + dinfo->fields_len;
-
- while (offset < end_offset) {
- proto_tree *field_tree;
- proto_item *ti;
-
- guint8 field_code;
-
- ti = proto_tree_add_item(tree, &hfi_dbus_hdr_field, tvb, offset, 0, ENC_NA);
- field_tree = proto_item_add_subtree(ti, ett_dbus_field);
-
- field_code = tvb_get_guint8(tvb, offset);
- proto_tree_add_item(field_tree, &hfi_dbus_hdr_field_code, tvb, offset, 1, dinfo->enc);
- proto_item_append_text(ti, ": %s", val_to_str(field_code, field_code_vals, "Unknown: %d"));
- offset += 1;
-
- offset = dissect_dbus_field_signature(tvb, pinfo, dinfo, field_tree, offset, field_code);
- if (offset == -1)
- break;
-
- offset = (offset + 7) & ~7; /* XXX ? */
-
- proto_item_set_end(ti, tvb, offset);
+ if (is_field_missing) {
+ expert_add_info(packet->pinfo, header_field_array_pi, &ei_dbus_required_header_field_missing);
+ return 1;
}
- /* XXX, verify if all required fields are preset */
-
- if (offset >= end_offset) {
- /* XXX expert */
+ switch(packet->message_type) {
+ case DBUS_MESSAGE_TYPE_METHOD_CALL:
+ col_add_fstr(packet->pinfo->cinfo, COL_INFO, "%s() @ %s", packet->member, packet->path);
+ break;
+ case DBUS_MESSAGE_TYPE_SIGNAL:
+ col_add_fstr(packet->pinfo->cinfo, COL_INFO, "* %s() @ %s", packet->member, packet->path);
+ break;
+ case DBUS_MESSAGE_TYPE_ERROR:
+ col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> %s", packet->error_name);
+ break;
+ case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+ col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> '%s'", packet->signature);
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ break;
}
- return end_offset;
+ // Header length must be a multiple of 8 bytes
+ return add_padding(packet, SIG_CODE_STRUCT_OPEN);
}
static int
-dissect_dbus_hdr(tvbuff_t *tvb, dbus_info_t *dinfo, proto_tree *tree, int offset)
-{
- proto_tree *hdr_tree;
- proto_item *ti;
-
- guint8 type;
-
- ti = proto_tree_add_item(tree, &hfi_dbus_hdr, tvb, offset, 0, ENC_NA);
- hdr_tree = proto_item_add_subtree(ti, ett_dbus_hdr);
-
- proto_tree_add_item(hdr_tree, &hfi_dbus_hdr_endianness, tvb, offset, 1, ENC_ASCII | ENC_NA);
- offset += 1;
-
- type = tvb_get_guint8(tvb, offset);
- col_set_str(dinfo->pinfo->cinfo, COL_INFO, val_to_str_const(type, message_type_vals, ""));
- proto_tree_add_item(hdr_tree, &hfi_dbus_hdr_type, tvb, offset, 1, dinfo->enc);
- offset += 1;
-
- proto_tree_add_item(hdr_tree, &hfi_dbus_hdr_flags, tvb, offset, 1, dinfo->enc);
- offset += 1;
-
- proto_tree_add_item(hdr_tree, &hfi_dbus_hdr_version, tvb, offset, 1, dinfo->enc);
- offset += 1;
-
- dinfo->body_len = dinfo->get32(tvb, offset);
- proto_tree_add_item(hdr_tree, &hfi_dbus_hdr_body_length, tvb, offset, 4, dinfo->enc);
- offset += 4;
-
- proto_tree_add_item(hdr_tree, &hfi_dbus_hdr_serial, tvb, offset, 4, dinfo->enc);
- offset += 4;
-
- dinfo->fields_len = dinfo->get32(tvb, offset);
- proto_tree_add_item(hdr_tree, &hfi_dbus_hdr_fields_length, tvb, offset, 4, dinfo->enc);
- offset += 4;
+dissect_dbus_header(dbus_packet_t *packet) {
+ guint32 val;
- return offset;
-}
-
-static int
-dissect_dbus_body(tvbuff_t *tvb, dbus_info_t *dinfo, proto_tree *tree, int offset)
-{
- proto_tree *body_tree;
- proto_item *ti;
-
- if (dinfo->body_len && dinfo->body_sig[0]) {
- const char *sig = dinfo->body_sig;
-
- ti = proto_tree_add_item(tree, &hfi_dbus_body, tvb, offset, 0, ENC_NA);
- body_tree = proto_item_add_subtree(ti, ett_dbus_body);
-
- while (*sig) {
- dbus_val_t val;
+ // Endianness
+ packet->current_pi = ptvcursor_add_ret_uint(packet->cursor, hf_dbus_endianness, 1, ENC_NA, &val);
+ switch (val) {
+ case 'l':
+ packet->enc = ENC_LITTLE_ENDIAN;
+ break;
+ case 'B':
+ packet->enc = ENC_BIG_ENDIAN;
+ break;
+ default:
+ add_expert(packet, &ei_dbus_endianness_invalid);
+ return 1;
+ }
- offset = dissect_dbus_sig(tvb, dinfo, body_tree, offset, *sig, &val);
- if (offset == -1)
- return -1;
- sig++;
- }
+ // Message Type
+ packet->message_type = add_uint(packet, hf_dbus_message_type);
+ const gchar *info = try_val_to_str(packet->message_type, message_type_vals);
+ if (packet->message_type == DBUS_MESSAGE_TYPE_INVALID) {
+ col_set_str(packet->pinfo->cinfo, COL_INFO, info);
+ add_expert(packet, &ei_dbus_message_type_invalid);
+ return 1;
+ } else if (!info) {
+ col_set_str(packet->pinfo->cinfo, COL_INFO, "Unknown message type");
+ add_expert(packet, &ei_dbus_message_type_unknown);
+ return 1;
+ }
+ col_set_str(packet->pinfo->cinfo, COL_INFO, info);
+
+ // Flags
+ ptvcursor_add_with_subtree(packet->cursor, hf_dbus_flags, 1, packet->enc, ett_dbus_flags);
+ ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_no_reply_expected, 1, packet->enc);
+ ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_no_auto_start, 1, packet->enc);
+ ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_allow_interactive_authorization, 1, packet->enc);
+ ptvcursor_advance(packet->cursor, 1);
+ ptvcursor_pop_subtree(packet->cursor);
+
+ // Version
+ if (add_uint(packet, hf_dbus_version) != 1) {
+ add_expert(packet, &ei_dbus_version_invalid);
+ return 1;
+ }
- proto_item_set_end(ti, tvb, offset);
+ // Body Length
+ packet->body_len = add_uint(packet, hf_dbus_body_length);
- } else if (dinfo->body_len || dinfo->body_sig[0]) {
- /* XXX smth wrong */
+ // Serial
+ packet->serial = add_uint(packet, hf_dbus_serial);
+ if (packet->serial == 0) {
+ add_expert(packet, &ei_dbus_serial_invalid);
+ return 1;
}
- return offset;
+
+ return 0;
}
static int
-dissect_dbus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
-{
- proto_tree *dbus_tree = NULL;
- dbus_info_t dinfo;
+dissect_dbus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
+ dbus_packet_t packet = { .pinfo = pinfo, .signature = "" };
- int offset;
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "D-Bus");
+ col_set_str(pinfo->cinfo, COL_INFO, "D-Bus");
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "D-BUS");
- col_clear(pinfo->cinfo, COL_INFO);
+ proto_item *pi = proto_tree_add_protocol_format(tree, proto_dbus, tvb, 0, -1, "D-Bus");
+ proto_tree *dbus_tree = proto_item_add_subtree(pi, ett_dbus);
- memset(&dinfo, 0, sizeof(dinfo));
- dinfo.pinfo = pinfo;
- switch (tvb_get_guint8(tvb, 0)) {
- case 'l':
- dinfo.enc = ENC_LITTLE_ENDIAN;
- dinfo.get16 = tvb_get_letohs;
- dinfo.get32 = tvb_get_letohl;
- dinfo.getdouble = tvb_get_letohieee_double;
- break;
- case 'B':
- dinfo.enc = ENC_BIG_ENDIAN;
- dinfo.get16 = tvb_get_ntohs;
- dinfo.get32 = tvb_get_ntohl;
- dinfo.getdouble = tvb_get_ntohieee_double;
- break;
- default: /* same as BIG_ENDIAN */
- /* XXX we should probably return 0; */
- dinfo.enc = ENC_NA;
- dinfo.get16 = tvb_get_ntohs;
- dinfo.get32 = tvb_get_ntohl;
- dinfo.getdouble = tvb_get_ntohieee_double;
- }
-
- if (tree) {
- proto_item *ti = proto_tree_add_item(tree, hfi_dbus, tvb, 0, -1, ENC_NA);
- dbus_tree = proto_item_add_subtree(ti, ett_dbus);
- }
-
- offset = 0;
- offset = dissect_dbus_hdr(tvb, &dinfo, dbus_tree, offset);
- offset = dissect_dbus_hdr_fields(tvb, pinfo, &dinfo, dbus_tree, offset);
- /* header aligned to 8B */
- offset = (offset + 7) & ~7;
+ gint offset = 0;
+ packet.cursor = ptvcursor_new(dbus_tree, tvb, offset);
- if (!dinfo.body_sig)
- dinfo.body_sig = "";
-
- offset = dissect_dbus_body(tvb, &dinfo, dbus_tree, offset);
+ (void)(dissect_dbus_header(&packet) ||
+ dissect_dbus_header_fields(&packet) ||
+ dissect_dbus_body(&packet));
+ offset = ptvcursor_current_offset(packet.cursor);
+ proto_item_set_end(pi, tvb, offset);
+ ptvcursor_free(packet.cursor);
return offset;
}
@@ -606,8 +1163,7 @@ dissect_dbus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_
static guint
get_dbus_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
- int offset, void *data _U_)
-{
+ int offset, void *data _U_) {
guint32 (*get_guint32)(tvbuff_t *, const gint);
guint32 len_body, len_hdr;
@@ -630,68 +1186,165 @@ get_dbus_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
}
static int
-dissect_dbus_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
-{
+dissect_dbus_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
return dissect_dbus(tvb, pinfo, tree, data);
}
static int
-dissect_dbus_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
-{
- tcp_dissect_pdus(tvb, pinfo, tree, dbus_desegment, DBUS_HEADER_LEN, get_dbus_message_len, dissect_dbus_pdu, data);
+dissect_dbus_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
+ tcp_dissect_pdus(tvb, pinfo, tree, dbus_desegment, DBUS_HEADER_LEN,
+ get_dbus_message_len, dissect_dbus_pdu, data);
return tvb_reported_length(tvb);
}
void
-proto_register_dbus(void)
-{
-#ifndef HAVE_HFI_SECTION_INIT
- static header_field_info *hfi[] = {
- /* Header */
- &hfi_dbus_hdr,
- &hfi_dbus_hdr_endianness,
- &hfi_dbus_hdr_type,
- &hfi_dbus_hdr_flags,
- &hfi_dbus_hdr_version,
- &hfi_dbus_hdr_body_length,
- &hfi_dbus_hdr_serial,
- &hfi_dbus_hdr_fields_length,
- /* Header field */
- &hfi_dbus_hdr_field,
- &hfi_dbus_hdr_field_code,
- &hfi_dbus_type_signature,
- &hfi_dbus_body,
- /* Values */
- &hfi_dbus_value_bool,
- &hfi_dbus_value_int,
- &hfi_dbus_value_uint,
- &hfi_dbus_value_str,
- &hfi_dbus_value_double,
+proto_register_dbus(void) {
+ static hf_register_info hf[] = {
+ { &hf_dbus_endianness, { "Endianness", "dbus.endianness",
+ FT_UINT8, BASE_NONE, VALS(endianness_vals), 0x00, NULL, HFILL }},
+ { &hf_dbus_message_type, { "Message Type", "dbus.message_type",
+ FT_UINT8, BASE_NONE, VALS(message_type_vals), 0x00, NULL, HFILL }},
+ { &hf_dbus_flags, { "Message Flags", "dbus.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_flags_no_reply_expected, { "No Reply Expected", "dbus.flags.no_reply_expected",
+ FT_BOOLEAN, 8, TFS(&not_expected_vals), 0x01, NULL, HFILL }},
+ { &hf_dbus_flags_no_auto_start, { "No Auto Start", "dbus.flags.no_auto_start",
+ FT_BOOLEAN, 8, TFS(&no_start_vals), 0x02, NULL, HFILL }},
+ { &hf_dbus_flags_allow_interactive_authorization, { "Allow Interactive Authorization", "dbus.flags.allow_interactive_authorization",
+ FT_BOOLEAN, 8, TFS(&allow_vals), 0x04, NULL, HFILL }},
+ { &hf_dbus_version, { "Protocol Version", "dbus.version",
+ FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_body_length, { "Message Body Length", "dbus.body_length",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_serial, { "Message Serial", "dbus.serial",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_field_code, { "Field Code", "dbus.field_code",
+ FT_UINT8, BASE_DEC, VALS(field_code_vals), 0x00, NULL, HFILL }},
+ { &hf_dbus_padding, { "Padding", "dbus.padding",
+ FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_path, { "Path", "dbus.path",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_interface, { "Interface", "dbus.interface",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_member, { "Member", "dbus.member",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_error_name, { "Error name", "dbus.error_name",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_reply_serial, { "Reply serial", "dbus.reply_serial",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_destination, { "Destination", "dbus.destination",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_sender, { "Sender", "dbus.sender",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_signature, { "Signature", "dbus.signature",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_unix_fds, { "Unix FDs", "dbus.unix_fds",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_body, { "Body", "dbus.body",
+ FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_byte, { "Byte", "dbus.type.byte",
+ FT_UINT8, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_boolean, { "Boolean", "dbus.type.boolean",
+ FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_int16, { "Int16", "dbus.type.int16",
+ FT_INT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_uint16, { "Uint16", "dbus.type.uint16",
+ FT_UINT16, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_int32, { "Int32", "dbus.type.int32",
+ FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_uint32, { "Uint32", "dbus.type.uint32",
+ FT_UINT32, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_int64, { "Int64", "dbus.type.int64",
+ FT_INT64, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_uint64, { "Uint64", "dbus.type.uint64",
+ FT_UINT64, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_double, { "Double", "dbus.type.double",
+ FT_DOUBLE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_string, { "String", "dbus.type.string",
+ FT_UINT_STRING, STR_UNICODE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_object_path, { "Object Path", "dbus.type.object_path",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_signature, { "Signature", "dbus.type.signature",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_array, { "Array", "dbus.type.array",
+ FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_array_length, { "Array Length", "dbus.type.array.length",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_struct, { "Struct", "dbus.type.struct",
+ FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_variant, { "Variant", "dbus.type.variant",
+ FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_variant_signature, { "Variant Signature", "dbus.type.variant.signature",
+ FT_UINT_STRING, STR_ASCII, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_dict_entry, { "Dict Entry", "dbus.type.dict_entry",
+ FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_dict_entry_key, { "Key", "dbus.type.dict_entry.key",
+ FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
+ { &hf_dbus_type_unix_fd, { "Unix FD", "dbus.type.unix_fd",
+ FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
};
-#endif
static gint *ett[] = {
&ett_dbus,
- &ett_dbus_hdr,
+ &ett_dbus_flags,
+ &ett_dbus_header_field_array,
+ &ett_dbus_header_field,
&ett_dbus_body,
- &ett_dbus_field
+ &ett_dbus_type_array,
+ &ett_dbus_type_struct,
+ &ett_dbus_type_variant,
+ &ett_dbus_type_dict_entry,
};
static ei_register_info ei[] = {
- { &ei_dbus_value_bool_invalid, { "dbus.value.bool.invalid", PI_PROTOCOL, PI_WARN, "Invalid boolean value", EXPFILL }},
- { &ei_dbus_value_str_invalid, { "dbus.value.str.invalid", PI_PROTOCOL, PI_WARN, "Invalid string (not UTF-8)", EXPFILL }},
- { &ei_dbus_invalid_object_path, { "dbus.invalid_object_path", PI_PROTOCOL, PI_WARN, "Invalid object_path", EXPFILL }},
- { &ei_dbus_invalid_signature, { "dbus.invalid_signature", PI_PROTOCOL, PI_WARN, "Invalid signature", EXPFILL }},
+ { &ei_dbus_endianness_invalid, { "dbus.endianness.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid endianness flag", EXPFILL }},
+ { &ei_dbus_message_type_invalid, { "dbus.message_type.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid message type", EXPFILL }},
+ { &ei_dbus_message_type_unknown, { "dbus.message_type.unknown",
+ PI_PROTOCOL, PI_WARN, "Unknown message type", EXPFILL }},
+ { &ei_dbus_version_invalid, { "dbus.version.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid version", EXPFILL }},
+ { &ei_dbus_serial_invalid, { "dbus.serial.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid serial", EXPFILL }},
+ { &ei_dbus_field_code_invalid, { "dbus.field_code.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid field code", EXPFILL }},
+ { &ei_dbus_required_header_field_missing, { "dbus.required_header_field_missing",
+ PI_PROTOCOL, PI_ERROR, "Required header field is missing", EXPFILL }},
+ { &ei_dbus_padding_invalid, { "dbus.padding.invalid",
+ PI_PROTOCOL, PI_ERROR, "Padding bytes must be zero", EXPFILL }},
+ { &ei_dbus_field_signature_wrong, { "dbus.field_signature_wrong",
+ PI_PROTOCOL, PI_ERROR, "Wrong header field variant signature", EXPFILL }},
+ { &ei_dbus_interface_invalid, { "dbus.interface.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid interface name", EXPFILL }},
+ { &ei_dbus_member_invalid, { "dbus.member.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid member name", EXPFILL }},
+ { &ei_dbus_error_name_invalid, { "dbus.error_name.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid error name", EXPFILL }},
+ { &ei_dbus_bus_name_invalid, { "dbus.bus_name.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid bus name", EXPFILL }},
+ { &ei_dbus_type_boolean_invalid, { "dbus.type.boolean.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid boolean value", EXPFILL }},
+ { &ei_dbus_string_invalid, { "dbus.type.string.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid string value", EXPFILL }},
+ { &ei_dbus_type_signature_invalid, { "dbus.type.signature.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid signature", EXPFILL }},
+ { &ei_dbus_type_array_too_long, { "dbus.type.array.too_long",
+ PI_PROTOCOL, PI_ERROR, "Array too long", EXPFILL }},
+ { &ei_dbus_type_array_content_out_of_bounds, { "dbus.type.array.content_out_of_bounds",
+ PI_PROTOCOL, PI_ERROR, "Array content is out of bounds", EXPFILL }},
+ { &ei_dbus_type_object_path_invalid, { "dbus.type.object_path.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid object path", EXPFILL }},
+ { &ei_dbus_type_variant_signature_invalid, { "dbus.type.variant.signature.invalid",
+ PI_PROTOCOL, PI_ERROR, "Invalid variant signature", EXPFILL }},
+ { &ei_dbus_nested_too_deeply, { "dbus.nested_too_deeply",
+ PI_PROTOCOL, PI_ERROR, "Containers nested too deeply", EXPFILL }},
};
expert_module_t *expert_dbus;
- int proto_dbus;
-
- proto_dbus = proto_register_protocol("D-Bus", "D-BUS", "dbus");
- hfi_dbus = proto_registrar_get_nth(proto_dbus);
-
- proto_register_fields(proto_dbus, hfi, array_length(hfi));
+ proto_dbus = proto_register_protocol("D-Bus", "D-Bus", "dbus");
+ proto_register_field_array(proto_dbus, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_dbus = expert_register_protocol(proto_dbus);
expert_register_field_array(expert_dbus, ei, array_length(ei));
@@ -701,8 +1354,7 @@ proto_register_dbus(void)
}
void
-proto_reg_handoff_dbus(void)
-{
+proto_reg_handoff_dbus(void) {
dissector_add_uint("wtap_encap", WTAP_ENCAP_DBUS, dbus_handle);
dissector_add_for_decode_as_with_preference("tcp.port", dbus_handle_tcp);
}