2 * Routines for D-Bus dissection
3 * Copyright 2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
4 * Copyright 2020, Simon Holesch <simon@holesch.de>
6 * Protocol specification available at http://dbus.freedesktop.org/doc/dbus-specification.html
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include <epan/packet.h>
18 #include <wiretap/wtap.h>
19 #include <epan/expert.h>
20 #include <epan/ptvcursor.h>
22 #include <wsutil/ws_roundup.h>
23 #include <epan/conversation.h>
24 #include "packet-tcp.h"
26 #define DBUS_MAX_ARRAY_LEN (64 * 1024 * 1024)
27 #define DBUS_MAX_NAME_LENGTH 255
28 #define DBUS_MAX_SIGNATURE_LENGTH 255
29 #define DBUS_MAX_TYPE_NESTING_LEVEL 32
30 #define DBUS_MAX_TOTAL_NESTING_LEVEL (2 * DBUS_MAX_TYPE_NESTING_LEVEL)
32 #define SIG_CODE_BYTE ('y')
33 #define SIG_CODE_BOOLEAN ('b')
34 #define SIG_CODE_INT16 ('n')
35 #define SIG_CODE_UINT16 ('q')
36 #define SIG_CODE_INT32 ('i')
37 #define SIG_CODE_UINT32 ('u')
38 #define SIG_CODE_INT64 ('x')
39 #define SIG_CODE_UINT64 ('t')
40 #define SIG_CODE_DOUBLE ('d')
41 #define SIG_CODE_STRING ('s')
42 #define SIG_CODE_OBJECT_PATH ('o')
43 #define SIG_CODE_SIGNATURE ('g')
44 #define SIG_CODE_ARRAY ('a')
45 #define SIG_CODE_STRUCT_OPEN ('(')
46 #define SIG_CODE_STRUCT_CLOSE (')')
47 #define SIG_CODE_VARIANT ('v')
48 #define SIG_CODE_DICT_ENTRY_OPEN ('{')
49 #define SIG_CODE_DICT_ENTRY_CLOSE ('}')
50 #define SIG_CODE_UNIX_FD ('h')
52 void proto_register_dbus(void);
53 void proto_reg_handoff_dbus(void);
55 static int proto_dbus
;
56 static bool dbus_desegment
= true;
57 static bool dbus_resolve_names
= true;
59 static dissector_handle_t dbus_handle
;
60 static dissector_handle_t dbus_handle_tcp
;
62 #define DBUS_MESSAGE_TYPE_INVALID 0
63 #define DBUS_MESSAGE_TYPE_METHOD_CALL 1
64 #define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
65 #define DBUS_MESSAGE_TYPE_ERROR 3
66 #define DBUS_MESSAGE_TYPE_SIGNAL 4
68 static const value_string message_type_vals
[] = {
69 { DBUS_MESSAGE_TYPE_INVALID
, "Invalid" },
70 { DBUS_MESSAGE_TYPE_METHOD_CALL
, "Method call" },
71 { DBUS_MESSAGE_TYPE_METHOD_RETURN
, "Method reply" },
72 { DBUS_MESSAGE_TYPE_ERROR
, "Error reply" },
73 { DBUS_MESSAGE_TYPE_SIGNAL
, "Signal emission" },
77 #define DBUS_HEADER_FIELD_INVALID 0
78 #define DBUS_HEADER_FIELD_PATH 1
79 #define DBUS_HEADER_FIELD_INTERFACE 2
80 #define DBUS_HEADER_FIELD_MEMBER 3
81 #define DBUS_HEADER_FIELD_ERROR_NAME 4
82 #define DBUS_HEADER_FIELD_REPLY_SERIAL 5
83 #define DBUS_HEADER_FIELD_DESTINATION 6
84 #define DBUS_HEADER_FIELD_SENDER 7
85 #define DBUS_HEADER_FIELD_SIGNATURE 8
86 #define DBUS_HEADER_FIELD_UNIX_FDS 9
88 static const value_string field_code_vals
[] = {
89 { DBUS_HEADER_FIELD_INVALID
, "Invalid" },
90 { DBUS_HEADER_FIELD_PATH
, "Path" },
91 { DBUS_HEADER_FIELD_INTERFACE
, "Interface" },
92 { DBUS_HEADER_FIELD_MEMBER
, "Member" },
93 { DBUS_HEADER_FIELD_ERROR_NAME
, "Error name" },
94 { DBUS_HEADER_FIELD_REPLY_SERIAL
, "Reply serial" },
95 { DBUS_HEADER_FIELD_DESTINATION
, "Destination" },
96 { DBUS_HEADER_FIELD_SENDER
, "sender" },
97 { DBUS_HEADER_FIELD_SIGNATURE
, "Signature" },
98 { DBUS_HEADER_FIELD_UNIX_FDS
, "Unix FDs" },
102 static const value_string endianness_vals
[] = {
103 { 'l', "little-endian" },
104 { 'B', "big-endian" },
108 #define DBUS_FLAGS_NO_REPLY_EXPECTED_MASK 0x01
109 #define DBUS_FLAGS_NO_AUTO_START_MASK 0x02
110 #define DBUS_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION_MASK 0x04
112 static const true_false_string allow_vals
= { "Allow", "Don't allow" };
113 static const true_false_string no_start_vals
= { "Don't start", "Start" };
114 static const true_false_string not_expected_vals
= { "Not expected", "Expected" };
116 static int hf_dbus_endianness
;
117 static int hf_dbus_message_type
;
118 static int hf_dbus_flags
;
119 static int hf_dbus_flags_no_reply_expected
;
120 static int hf_dbus_flags_no_auto_start
;
121 static int hf_dbus_flags_allow_interactive_authorization
;
122 static int hf_dbus_version
;
123 static int hf_dbus_body_length
;
124 static int hf_dbus_serial
;
125 static int hf_dbus_field_code
;
126 static int hf_dbus_padding
;
127 static int hf_dbus_path
;
128 static int hf_dbus_interface
;
129 static int hf_dbus_member
;
130 static int hf_dbus_error_name
;
131 static int hf_dbus_reply_serial
;
132 static int hf_dbus_destination
;
133 static int hf_dbus_sender
;
134 static int hf_dbus_signature
;
135 static int hf_dbus_unix_fds
;
136 static int hf_dbus_body
;
137 static int hf_dbus_type_byte
;
138 static int hf_dbus_type_boolean
;
139 static int hf_dbus_type_int16
;
140 static int hf_dbus_type_uint16
;
141 static int hf_dbus_type_int32
;
142 static int hf_dbus_type_uint32
;
143 static int hf_dbus_type_int64
;
144 static int hf_dbus_type_uint64
;
145 static int hf_dbus_type_double
;
146 static int hf_dbus_type_string
;
147 static int hf_dbus_type_object_path
;
148 static int hf_dbus_type_signature
;
149 static int hf_dbus_type_array
;
150 static int hf_dbus_type_array_length
;
151 static int hf_dbus_type_struct
;
152 static int hf_dbus_type_variant
;
153 static int hf_dbus_type_variant_signature
;
154 static int hf_dbus_type_dict_entry
;
155 static int hf_dbus_type_dict_entry_key
;
156 static int hf_dbus_type_unix_fd
;
157 static int hf_dbus_response_in
;
158 static int hf_dbus_response_to
;
159 static int hf_dbus_response_time
;
162 static int ett_dbus_flags
;
163 static int ett_dbus_header_field_array
;
164 static int ett_dbus_header_field
;
165 static int ett_dbus_body
;
166 static int ett_dbus_type_array
;
167 static int ett_dbus_type_struct
;
168 static int ett_dbus_type_variant
;
169 static int ett_dbus_type_dict_entry
;
171 static expert_field ei_dbus_endianness_invalid
;
172 static expert_field ei_dbus_message_type_invalid
;
173 static expert_field ei_dbus_message_type_unknown
;
174 static expert_field ei_dbus_version_invalid
;
175 static expert_field ei_dbus_serial_invalid
;
176 static expert_field ei_dbus_field_code_invalid
;
177 static expert_field ei_dbus_required_header_field_missing
;
178 static expert_field ei_dbus_padding_invalid
;
179 static expert_field ei_dbus_field_signature_wrong
;
180 static expert_field ei_dbus_interface_invalid
;
181 static expert_field ei_dbus_member_invalid
;
182 static expert_field ei_dbus_error_name_invalid
;
183 static expert_field ei_dbus_bus_name_invalid
;
184 static expert_field ei_dbus_type_boolean_invalid
;
185 static expert_field ei_dbus_string_invalid
;
186 static expert_field ei_dbus_type_signature_invalid
;
187 static expert_field ei_dbus_type_array_too_long
;
188 static expert_field ei_dbus_type_array_content_out_of_bounds
;
189 static expert_field ei_dbus_type_object_path_invalid
;
190 static expert_field ei_dbus_type_variant_signature_invalid
;
191 static expert_field ei_dbus_nested_too_deeply
;
197 uint32_t message_type
;
202 proto_item
*current_pi
;
204 const char *interface
;
206 const char *error_name
;
207 uint32_t reply_serial
;
208 const char *destination
;
210 const char *signature
;
214 typedef struct _dbus_type_reader_t
{
215 dbus_packet_t
*packet
;
216 const char *signature
;
218 uint32_t array_level
;
219 uint32_t struct_level
;
220 uint32_t dict_entry_level
;
221 const char *array_type_start
;
222 int array_end_offset
;
224 bool is_basic_variant
;
225 bool is_in_dict_entry
;
226 bool is_basic_dict_entry
;
227 proto_item
*container
;
228 struct _dbus_type_reader_t
*parent
;
229 } dbus_type_reader_t
;
246 const char *interface
;
248 } dbus_transaction_t
;
254 static wmem_map_t
*request_info_map
;
255 static wmem_map_t
*unique_name_map
;
258 is_ascii_digit(char c
) {
259 return (unsigned)c
- '0' < 10;
263 is_ascii_alpha(char c
) {
264 return ((unsigned)c
| 0x20) - 'a' <= 'z' - 'a';
268 is_dbus_object_path_valid(const char *path
) {
269 // - The path may be of any length.
270 // - The path must begin with an ASCII '/' (integer 47) character, and must consist of elements separated by
272 // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
273 // - No element may be the empty string.
274 // - Multiple '/' characters cannot occur in sequence.
275 // - A trailing '/' character is not allowed unless the path is the root path (a single '/' character).
276 if (*path
== '/' && *(path
+ 1) == '\0') {
280 while (*path
== '/') {
287 while (is_ascii_alpha(*path
) || is_ascii_digit(*path
) || *path
== '_') {
292 return *(path
- 1) != '/';
300 is_dbus_interface_valid(const char *interface
) {
301 // - Interface names are composed of 2 or more elements separated by a period ('.') character. All elements
302 // must contain at least one character.
303 // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_" and must not begin with a digit.
304 // - Interface names must not exceed the maximum name length.
306 const char *p
= interface
;
308 if (!(is_ascii_alpha(*p
) || *p
== '_')) {
314 while (is_ascii_alpha(*p
) || is_ascii_digit(*p
) || *p
== '_') {
319 size_t length
= p
- interface
;
320 return elements
>= 2 && length
<= DBUS_MAX_NAME_LENGTH
;
322 } while (*p
++ == '.');
328 is_dbus_member_name_valid(const char *member_name
) {
329 // - Must only contain the ASCII characters "[A-Z][a-z][0-9]_" and may not begin with a digit.
330 // - Must not contain the '.' (period) character.
331 // - Must not exceed the maximum name length.
332 // - Must be at least 1 byte in length.
333 const char *p
= member_name
;
335 if (!(is_ascii_alpha(*p
) || *p
== '_')) {
341 } while (is_ascii_alpha(*p
) || is_ascii_digit(*p
) || *p
== '_');
344 size_t length
= p
- member_name
;
345 return length
<= DBUS_MAX_NAME_LENGTH
;
352 is_dbus_bus_name_valid(const char *bus_name
) {
353 // - Bus names that start with a colon (':') character are unique connection names. Other bus names are called
354 // well-known bus names.
355 // - Bus names are composed of 1 or more elements separated by a period ('.') character. All elements must
356 // contain at least one character.
357 // - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-", with "-" discouraged in new bus
358 // names. Only elements that are part of a unique connection name may begin with a digit, elements in other
359 // bus names must not begin with a digit.
360 // - Bus names must contain at least one '.' (period) character (and thus at least two elements).
361 // - Bus names must not begin with a '.' (period) character.
362 // - Bus names must not exceed the maximum name length.
364 const char *p
= bus_name
;
365 bool is_unique_name
= false;
368 is_unique_name
= true;
373 if (!(is_ascii_alpha(*p
) || *p
== '_' || *p
== '-' || (is_unique_name
&& is_ascii_digit(*p
)))) {
379 while (is_ascii_alpha(*p
) || is_ascii_digit(*p
) || *p
== '_' || *p
== '-') {
384 size_t length
= p
- bus_name
;
385 return elements
>= 2 && length
<= DBUS_MAX_NAME_LENGTH
;
387 } while (*p
++ == '.');
393 is_basic_type(char sig_code
) {
396 case SIG_CODE_BOOLEAN
:
398 case SIG_CODE_UINT16
:
400 case SIG_CODE_UINT32
:
402 case SIG_CODE_UINT64
:
403 case SIG_CODE_DOUBLE
:
404 case SIG_CODE_STRING
:
405 case SIG_CODE_OBJECT_PATH
:
406 case SIG_CODE_SIGNATURE
:
407 case SIG_CODE_UNIX_FD
:
415 skip_enclosed_container(const char *signature
, char open_bracket
, char closed_bracket
) {
417 for (char sig_code
= *signature
++; sig_code
!= '\0'; sig_code
= *signature
++) {
418 if (sig_code
== closed_bracket
) {
423 } else if (sig_code
== open_bracket
) {
431 skip_single_complete_type(const char *signature
) {
434 sig_code
= *signature
++;
437 case SIG_CODE_BOOLEAN
:
439 case SIG_CODE_UINT16
:
441 case SIG_CODE_UINT32
:
443 case SIG_CODE_UINT64
:
444 case SIG_CODE_DOUBLE
:
445 case SIG_CODE_STRING
:
446 case SIG_CODE_OBJECT_PATH
:
447 case SIG_CODE_SIGNATURE
:
448 case SIG_CODE_VARIANT
:
449 case SIG_CODE_UNIX_FD
:
453 case SIG_CODE_STRUCT_OPEN
:
454 return skip_enclosed_container(signature
, SIG_CODE_STRUCT_OPEN
, SIG_CODE_STRUCT_CLOSE
);
455 case SIG_CODE_DICT_ENTRY_OPEN
:
456 return skip_enclosed_container(signature
, SIG_CODE_DICT_ENTRY_OPEN
, SIG_CODE_DICT_ENTRY_CLOSE
);
464 is_dbus_signature_valid(const char *signature
, dbus_packet_t
*packet
) {
467 char prev_sig_code
= '\0';
468 wmem_stack_t
*expected_chars
= wmem_stack_new(packet
->pinfo
->pool
);
470 while ((sig_code
= *signature
++) != '\0') {
471 if (++length
>= DBUS_MAX_SIGNATURE_LENGTH
) {
477 case SIG_CODE_SIGNATURE
:
478 case SIG_CODE_VARIANT
:
480 case SIG_CODE_UINT16
:
482 case SIG_CODE_UINT32
:
483 case SIG_CODE_BOOLEAN
:
484 case SIG_CODE_OBJECT_PATH
:
485 case SIG_CODE_STRING
:
486 case SIG_CODE_UNIX_FD
:
488 case SIG_CODE_UINT64
:
489 case SIG_CODE_DOUBLE
:
492 switch (*signature
) {
494 case SIG_CODE_STRUCT_CLOSE
:
495 case SIG_CODE_DICT_ENTRY_CLOSE
:
496 // arrays must be followed by a single complete type
499 // invalid signature codes are detected in the next iteration
501 case SIG_CODE_STRUCT_OPEN
:
502 if (*signature
== SIG_CODE_STRUCT_CLOSE
) {
503 // empty structures are not allowed
506 wmem_stack_push(expected_chars
, (void *)SIG_CODE_STRUCT_CLOSE
);
508 case SIG_CODE_DICT_ENTRY_OPEN
: {
509 // dict entries must be an array element type
510 // the first single complete type (the "key") must be a basic type
511 if (prev_sig_code
!= SIG_CODE_ARRAY
|| !is_basic_type(*signature
)) {
515 // dict entries must contain exactly two single complete types
516 // + 1 can be used here, since the key is a basic type
517 const char *sig_code_close
= skip_single_complete_type(signature
+ 1);
518 if (!sig_code_close
|| *sig_code_close
!= SIG_CODE_DICT_ENTRY_CLOSE
) {
521 wmem_stack_push(expected_chars
, (void *)SIG_CODE_DICT_ENTRY_CLOSE
);
524 case SIG_CODE_STRUCT_CLOSE
:
525 case SIG_CODE_DICT_ENTRY_CLOSE
:
526 if (wmem_stack_count(expected_chars
) == 0 ||
527 (char)(uintptr_t)wmem_stack_pop(expected_chars
) != sig_code
) {
535 prev_sig_code
= sig_code
;
537 return wmem_stack_count(expected_chars
) == 0;
541 add_expert(dbus_packet_t
*packet
, expert_field
*ei
) {
542 expert_add_info(packet
->pinfo
, packet
->current_pi
, ei
);
546 add_uint(dbus_packet_t
*packet
, int hf
) {
547 header_field_info
*info
= proto_registrar_get_nth(hf
);
550 switch (info
->type
) {
558 DISSECTOR_ASSERT_NOT_REACHED();
560 packet
->current_pi
= ptvcursor_add_ret_uint(packet
->cursor
, hf
, length
, packet
->enc
, &value
);
564 static const uint8_t *
565 add_dbus_string(dbus_packet_t
*packet
, int hf
, int uint_length
) {
566 const uint8_t *string
;
567 int start_offset
= ptvcursor_current_offset(packet
->cursor
);
568 proto_item
*pi
= ptvcursor_add_ret_string(packet
->cursor
, hf
, uint_length
,
569 packet
->enc
| ENC_UTF_8
, packet
->pinfo
->pool
, &string
);
570 int item_length
= ptvcursor_current_offset(packet
->cursor
) - start_offset
;
571 uint8_t term_byte
= tvb_get_uint8(ptvcursor_tvbuff(packet
->cursor
), ptvcursor_current_offset(packet
->cursor
));
572 proto_item_set_len(pi
, item_length
+ 1);
573 ptvcursor_advance(packet
->cursor
, 1);
574 packet
->current_pi
= pi
;
576 if ((strlen(string
) != (size_t)(item_length
- uint_length
)) || (term_byte
!= '\0')) {
583 calculate_padding_len(int offset
, char sig
) {
587 case SIG_CODE_SIGNATURE
:
588 case SIG_CODE_VARIANT
:
593 case SIG_CODE_UINT16
:
597 case SIG_CODE_UINT32
:
598 case SIG_CODE_BOOLEAN
:
599 case SIG_CODE_OBJECT_PATH
:
601 case SIG_CODE_STRING
:
602 case SIG_CODE_UNIX_FD
:
606 case SIG_CODE_UINT64
:
607 case SIG_CODE_DOUBLE
:
608 case SIG_CODE_STRUCT_OPEN
:
609 case SIG_CODE_DICT_ENTRY_OPEN
:
613 return (alignment
- (offset
% alignment
)) % alignment
;
617 add_padding(dbus_packet_t
*packet
, char sig
) {
619 tvbuff_t
*tvb
= ptvcursor_tvbuff(packet
->cursor
);
620 int offset
= ptvcursor_current_offset(packet
->cursor
);
621 int padding_len
= calculate_padding_len(offset
, sig
);
623 if (padding_len
!= 0) {
624 packet
->current_pi
= ptvcursor_add(packet
->cursor
, hf_dbus_padding
, padding_len
, packet
->enc
);
625 for (int i
= offset
; i
< (offset
+ padding_len
); i
++) {
626 value
= tvb_get_uint8(tvb
, i
);
628 add_expert(packet
, &ei_dbus_padding_invalid
);
632 proto_item_set_hidden(packet
->current_pi
);
638 reader_cleanup(dbus_type_reader_t
*reader
) {
639 for (dbus_type_reader_t
*r
= reader
; r
->parent
; r
= r
->parent
) {
640 ptvcursor_pop_subtree(r
->packet
->cursor
);
644 static dbus_type_reader_t
*
645 reader_next(dbus_type_reader_t
*reader
, int hf
, int ett
, dbus_val_t
*value
) {
647 char sig_code
= *reader
->signature
++;
648 dbus_packet_t
*packet
= reader
->packet
;
649 bool is_single_complete_type
= true;
650 add_padding(packet
, sig_code
);
654 packet
->current_pi
= ptvcursor_add_ret_uint(packet
->cursor
,
655 hf
!= -1 ? hf
: hf_dbus_type_byte
, 1, packet
->enc
, &value
->uint
);
657 case SIG_CODE_BOOLEAN
: {
658 int offset
= ptvcursor_current_offset(packet
->cursor
);
659 tvbuff_t
*tvb
= ptvcursor_tvbuff(packet
->cursor
);
660 uint8_t val
= tvb_get_uint8(tvb
, offset
);
661 packet
->current_pi
= ptvcursor_add_ret_boolean(packet
->cursor
,
662 hf
!= -1 ? hf
: hf_dbus_type_boolean
, 4, packet
->enc
, &value
->bool_
);
664 add_expert(packet
, &ei_dbus_type_boolean_invalid
);
670 packet
->current_pi
= ptvcursor_add_ret_int(packet
->cursor
,
671 hf
!= -1 ? hf
: hf_dbus_type_int16
, 2, packet
->enc
, &value
->int_
);
673 case SIG_CODE_UINT16
:
674 packet
->current_pi
= ptvcursor_add_ret_uint(packet
->cursor
,
675 hf
!= -1 ? hf
: hf_dbus_type_uint16
, 2, packet
->enc
, &value
->uint
);
678 packet
->current_pi
= ptvcursor_add_ret_int(packet
->cursor
,
679 hf
!= -1 ? hf
: hf_dbus_type_int32
, 4, packet
->enc
, &value
->int_
);
681 case SIG_CODE_UINT32
:
682 packet
->current_pi
= ptvcursor_add_ret_uint(packet
->cursor
,
683 hf
!= -1 ? hf
: hf_dbus_type_uint32
, 4, packet
->enc
, &value
->uint
);
685 case SIG_CODE_INT64
: {
686 int offset
= ptvcursor_current_offset(packet
->cursor
);
687 tvbuff_t
*tvb
= ptvcursor_tvbuff(packet
->cursor
);
688 value
->int64
= tvb_get_int64(tvb
, offset
, packet
->enc
);
689 packet
->current_pi
= ptvcursor_add(packet
->cursor
,
690 hf
!= -1 ? hf
: hf_dbus_type_int64
, 8, packet
->enc
);
693 case SIG_CODE_UINT64
: {
694 int offset
= ptvcursor_current_offset(packet
->cursor
);
695 tvbuff_t
*tvb
= ptvcursor_tvbuff(packet
->cursor
);
696 value
->uint64
= tvb_get_uint64(tvb
, offset
, packet
->enc
);
697 packet
->current_pi
= ptvcursor_add(packet
->cursor
,
698 hf
!= -1 ? hf
: hf_dbus_type_uint64
, 8, packet
->enc
);
701 case SIG_CODE_DOUBLE
: {
702 int offset
= ptvcursor_current_offset(packet
->cursor
);
703 tvbuff_t
*tvb
= ptvcursor_tvbuff(packet
->cursor
);
704 value
->double_
= tvb_get_ieee_double(tvb
, offset
, packet
->enc
);
705 packet
->current_pi
= ptvcursor_add(packet
->cursor
,
706 hf
!= -1 ? hf
: hf_dbus_type_double
, 8, packet
->enc
);
709 case SIG_CODE_STRING
: {
710 const char *val
= add_dbus_string(packet
,
711 hf
!= -1 ? hf
: hf_dbus_type_string
, 4);
712 if (!val
|| !g_utf8_validate(val
, -1, NULL
)) {
713 add_expert(packet
, &ei_dbus_string_invalid
);
719 case SIG_CODE_OBJECT_PATH
: {
720 const char *val
= add_dbus_string(packet
, hf
!= -1 ? hf
: hf_dbus_type_object_path
, 4);
721 if (!val
|| !is_dbus_object_path_valid(val
)) {
722 add_expert(packet
, &ei_dbus_type_object_path_invalid
);
728 case SIG_CODE_SIGNATURE
: {
729 const char *val
= add_dbus_string(packet
, hf
!= -1 ? hf
: hf_dbus_type_signature
, 1);
730 if (!val
|| !is_dbus_signature_valid(val
, packet
)) {
731 add_expert(packet
, &ei_dbus_type_signature_invalid
);
737 case SIG_CODE_ARRAY
: {
738 is_single_complete_type
= false;
739 proto_item
*array
= ptvcursor_add_with_subtree(packet
->cursor
, hf
!= -1 ? hf
: hf_dbus_type_array
,
740 SUBTREE_UNDEFINED_LENGTH
, ENC_NA
, ett
!= -1 ? ett
: ett_dbus_type_array
);
741 if (*reader
->signature
== SIG_CODE_DICT_ENTRY_OPEN
) {
742 proto_item_append_text(array
, " (Dict)");
744 uint32_t array_len
= add_uint(packet
, hf_dbus_type_array_length
);
745 value
->uint
= array_len
;
746 add_padding(packet
, *reader
->signature
);
747 if (array_len
== 0) {
748 reader
->signature
= skip_single_complete_type(reader
->signature
);
749 // all signatures are validated
750 DISSECTOR_ASSERT(reader
->signature
);
751 ptvcursor_pop_subtree(packet
->cursor
);
752 is_single_complete_type
= true;
753 } else if (array_len
<= DBUS_MAX_ARRAY_LEN
) {
754 int end_offset
= ptvcursor_current_offset(packet
->cursor
) + array_len
;
755 dbus_type_reader_t
*child
= wmem_new(packet
->pinfo
->pool
, dbus_type_reader_t
);
756 *child
= (dbus_type_reader_t
){
757 .packet
= reader
->packet
,
758 .signature
= reader
->signature
,
759 .level
= reader
->level
+ 1,
760 .array_level
= reader
->array_level
+ 1,
761 .array_type_start
= reader
->signature
,
762 .array_end_offset
= end_offset
,
768 add_expert(packet
, &ei_dbus_type_array_too_long
);
770 ptvcursor_pop_subtree(packet
->cursor
);
774 case SIG_CODE_STRUCT_OPEN
: {
775 is_single_complete_type
= false;
776 ptvcursor_add_with_subtree(packet
->cursor
, hf
!= -1 ? hf
: hf_dbus_type_struct
,
777 SUBTREE_UNDEFINED_LENGTH
, ENC_NA
, ett
!= -1 ? ett
: ett_dbus_type_struct
);
778 dbus_type_reader_t
*child
= wmem_new(packet
->pinfo
->pool
, dbus_type_reader_t
);
779 *child
= (dbus_type_reader_t
){
780 .packet
= reader
->packet
,
781 .signature
= reader
->signature
,
782 .level
= reader
->level
+ 1,
783 .struct_level
= reader
->struct_level
+ 1,
789 case SIG_CODE_VARIANT
: {
790 is_single_complete_type
= false;
791 proto_item
*variant
= ptvcursor_add_with_subtree(packet
->cursor
,
792 hf
!= -1 ? hf
: hf_dbus_type_variant
,
793 SUBTREE_UNDEFINED_LENGTH
, ENC_NA
, ett
!= -1 ? ett
: ett_dbus_type_variant
);
794 const char *variant_signature
= add_dbus_string(packet
, hf_dbus_type_variant_signature
, 1);
795 value
->string
= variant_signature
;
796 if (variant_signature
&& is_dbus_signature_valid(variant_signature
, packet
)) {
797 if (variant_signature
[0] != '\0') {
798 dbus_type_reader_t
*child
= wmem_new(packet
->pinfo
->pool
, dbus_type_reader_t
);
799 *child
= (dbus_type_reader_t
){
800 .packet
= reader
->packet
,
801 .signature
= variant_signature
,
802 .level
= reader
->level
+ 1,
803 .is_in_variant
= true,
804 .is_basic_variant
= is_basic_type(*variant_signature
)
805 && *(variant_signature
+ 1) == '\0',
806 .container
= variant
,
809 if (reader
->is_in_dict_entry
&& child
->is_basic_variant
) {
810 reader
->is_basic_dict_entry
= true;
814 ptvcursor_pop_subtree(packet
->cursor
);
817 add_expert(packet
, &ei_dbus_type_variant_signature_invalid
);
819 ptvcursor_pop_subtree(packet
->cursor
);
823 case SIG_CODE_DICT_ENTRY_OPEN
: {
824 is_single_complete_type
= false;
825 proto_item
*dict_entry
= ptvcursor_add_with_subtree(packet
->cursor
,
826 hf
!= -1 ? hf
: hf_dbus_type_dict_entry
,
827 SUBTREE_UNDEFINED_LENGTH
, ENC_NA
, ett
!= -1 ? ett
: ett_dbus_type_dict_entry
);
828 dbus_type_reader_t
*child
= wmem_new(packet
->pinfo
->pool
, dbus_type_reader_t
);
829 *child
= (dbus_type_reader_t
){
830 .packet
= reader
->packet
,
831 .signature
= reader
->signature
,
832 .level
= reader
->level
+ 1,
833 .dict_entry_level
= reader
->dict_entry_level
+ 1,
834 .is_in_dict_entry
= true,
835 .is_basic_dict_entry
= is_basic_type(*(reader
->signature
+ 1)),
836 .container
= dict_entry
,
842 case SIG_CODE_STRUCT_CLOSE
:
843 case SIG_CODE_DICT_ENTRY_CLOSE
:
844 ptvcursor_pop_subtree(packet
->cursor
);
845 reader
->parent
->signature
= reader
->signature
;
846 reader
= reader
->parent
;
848 case SIG_CODE_UNIX_FD
:
849 packet
->current_pi
= ptvcursor_add_ret_uint(packet
->cursor
,
850 hf
!= -1 ? hf
: hf_dbus_type_unix_fd
, 4, packet
->enc
, &value
->uint
);
853 // all signatures are validated
854 DISSECTOR_ASSERT_NOT_REACHED();
857 if (reader
->level
> DBUS_MAX_TOTAL_NESTING_LEVEL
||
858 reader
->array_level
> DBUS_MAX_TYPE_NESTING_LEVEL
||
859 reader
->struct_level
> DBUS_MAX_TYPE_NESTING_LEVEL
||
860 reader
->dict_entry_level
> DBUS_MAX_TYPE_NESTING_LEVEL
) {
861 add_expert(packet
, &ei_dbus_nested_too_deeply
);
863 } else if (is_single_complete_type
) {
864 // Arrays and variants don't have a closing signature code, but they end after a single complete type.
865 // Close them here recursively, e.g. "aav"
867 if (reader
->array_type_start
) { // inside array
868 int offset
= ptvcursor_current_offset(packet
->cursor
);
870 if (offset
< reader
->array_end_offset
) {
871 // parse next array element -> reset signature
872 reader
->signature
= reader
->array_type_start
;
874 } else if (offset
== reader
->array_end_offset
) {
875 // all array elements parsed
876 ptvcursor_pop_subtree(packet
->cursor
);
877 reader
->parent
->signature
= reader
->signature
;
878 reader
= reader
->parent
;
880 // array elements don't fit into array
881 expert_add_info(packet
->pinfo
, reader
->container
,
882 &ei_dbus_type_array_content_out_of_bounds
);
886 } else if (reader
->is_in_variant
) {
887 if (reader
->is_basic_variant
) {
888 proto_item_append_text(reader
->container
, ": %s",
889 proto_item_get_display_repr(packet
->pinfo
->pool
, packet
->current_pi
));
891 ptvcursor_pop_subtree(packet
->cursor
);
892 reader
= reader
->parent
;
897 if (reader
->is_in_dict_entry
) {
898 // add "key: value" to dict entry item to make it readable without expanding the tree
899 if (*(reader
->signature
- 2) == SIG_CODE_DICT_ENTRY_OPEN
) { // == key
900 // key is always a basic type
901 proto_item_append_text(reader
->container
, ", %s",
902 proto_item_get_display_repr(packet
->pinfo
->pool
, packet
->current_pi
));
903 } else if (reader
->is_basic_dict_entry
) { // == value
904 proto_item_append_text(reader
->container
, ": %s",
905 proto_item_get_display_repr(packet
->pinfo
->pool
, packet
->current_pi
));
911 reader_cleanup(reader
);
918 reader_is_finished(dbus_type_reader_t
*reader
) {
919 return *reader
->signature
== '\0' && reader
->parent
== NULL
;
923 dissect_dbus_signature(dbus_packet_t
*packet
, const char *signature
) {
924 dbus_type_reader_t root_reader
= {
926 .signature
= signature
,
928 dbus_type_reader_t
*reader
= &root_reader
;
930 while (!reader_is_finished(reader
)) {
931 reader
= reader_next(reader
, -1, -1, &value
);
940 dissect_dbus_body(dbus_packet_t
*packet
) {
942 if (packet
->signature
[0]) {
943 ptvcursor_add_with_subtree(packet
->cursor
, hf_dbus_body
,
944 SUBTREE_UNDEFINED_LENGTH
, ENC_NA
, ett_dbus_body
);
945 err
= dissect_dbus_signature(packet
, packet
->signature
);
946 ptvcursor_pop_subtree(packet
->cursor
);
952 update_unique_name_map(const char *name1
, const char *name2
) {
953 const char *unique_name
;
954 const char *well_known_name
;
956 if (!dbus_resolve_names
) {
960 if (name1
[0] == ':' && name2
[0] != ':') {
962 well_known_name
= name2
;
963 } else if (name2
[0] == ':' && name1
[0] != ':') {
965 well_known_name
= name1
;
967 // both are well-known or both are unique names
970 if (!wmem_map_contains(unique_name_map
, unique_name
)) {
971 wmem_map_insert(unique_name_map
,
972 wmem_strdup(wmem_file_scope(), unique_name
),
973 wmem_strdup(wmem_file_scope(), well_known_name
));
978 add_conversation(dbus_packet_t
*packet
, proto_tree
*header_field_tree
) {
983 if (!packet
->sender
|| !packet
->destination
) {
984 // in a peer-to-peer setup, sender and destination can be unset, in which case conversation tracking
985 // doesn't make sense.
989 switch (packet
->message_type
) {
990 case DBUS_MESSAGE_TYPE_METHOD_CALL
:
991 if (packet
->flags
& DBUS_FLAGS_NO_REPLY_EXPECTED_MASK
) {
992 // there won't be a response, no need to track
997 // There are cases where the destination address of the request doesn't match the sender address of the
998 // response, for example:
999 // - The request is sent to the well-known bus name (e.g. org.freedesktop.PolicyKit1), but the reply is
1000 // sent from the unique connection name (e.g. :1.10). Both names refer to the same connection and for
1001 // every unique connection name, there can be multiple well-known names.
1002 // - The D-Bus daemon (org.freedesktop.DBus) sends the reply, instead of the recipient, e.g.
1003 // org.freedesktop.DBus.Error.AccessDenied
1004 // To find the correct response, match the request sender + serial with the response destination +
1006 if (!PINFO_FD_VISITED(packet
->pinfo
)) {
1007 request_dest
= wmem_strdup(wmem_file_scope(), packet
->destination
);
1008 key
= wmem_strdup_printf(wmem_file_scope(), "%s %u", packet
->sender
, packet
->serial
);
1009 wmem_map_insert(request_info_map
, key
, request_dest
);
1012 case DBUS_MESSAGE_TYPE_METHOD_RETURN
:
1013 case DBUS_MESSAGE_TYPE_ERROR
:
1016 key
= wmem_strdup_printf(packet
->pinfo
->pool
, "%s %u", packet
->destination
, packet
->reply_serial
);
1017 request_dest
= (char *)wmem_map_lookup(request_info_map
, key
);
1018 if (request_dest
&& !g_str_equal(request_dest
, packet
->sender
)) {
1019 // Replace the sender address of the response with the destination address of the request, so
1020 // the conversation can be found.
1021 address sender_addr
;
1022 set_address(&sender_addr
, AT_STRINGZ
, (int)strlen(request_dest
)+1, request_dest
);
1023 conversation_set_conv_addr_port_endpoints(packet
->pinfo
, &sender_addr
, &packet
->pinfo
->dst
,
1024 conversation_pt_to_endpoint_type(packet
->pinfo
->ptype
),
1025 packet
->pinfo
->srcport
, packet
->pinfo
->destport
);
1027 if (!PINFO_FD_VISITED(packet
->pinfo
) && packet
->message_type
== DBUS_MESSAGE_TYPE_METHOD_RETURN
) {
1028 update_unique_name_map(request_dest
, packet
->sender
);
1032 case DBUS_MESSAGE_TYPE_SIGNAL
:
1034 // signals don't have a response, no need to track
1038 conversation_t
*conversation
= find_or_create_conversation(packet
->pinfo
);
1039 dbus_conv_info_t
*conv_info
= (dbus_conv_info_t
*)conversation_get_proto_data(conversation
, proto_dbus
);
1042 conv_info
= wmem_new(wmem_file_scope(), dbus_conv_info_t
);
1043 conv_info
->packets
= wmem_map_new(wmem_file_scope(), g_direct_hash
, g_direct_equal
);
1044 conversation_add_proto_data(conversation
, proto_dbus
, conv_info
);
1047 dbus_transaction_t
*trans
;
1048 if (!PINFO_FD_VISITED(packet
->pinfo
)) {
1050 trans
= wmem_new(wmem_file_scope(), dbus_transaction_t
);
1051 *trans
= (dbus_transaction_t
){
1052 .req_frame
= packet
->pinfo
->num
,
1053 .req_time
= packet
->pinfo
->fd
->abs_ts
,
1054 .path
= wmem_strdup(wmem_file_scope(), packet
->path
),
1055 .interface
= wmem_strdup(wmem_file_scope(), packet
->interface
),
1056 .member
= wmem_strdup(wmem_file_scope(), packet
->member
),
1058 wmem_map_insert(conv_info
->packets
, GUINT_TO_POINTER(packet
->serial
), (void *)trans
);
1060 trans
= (dbus_transaction_t
*)wmem_map_lookup(conv_info
->packets
, GUINT_TO_POINTER(packet
->reply_serial
));
1062 trans
->rep_frame
= packet
->pinfo
->num
;
1066 uint32_t request_serial
= is_request
? packet
->serial
: packet
->reply_serial
;
1067 trans
= (dbus_transaction_t
*)wmem_map_lookup(conv_info
->packets
, GUINT_TO_POINTER(request_serial
));
1075 proto_item
*it
= proto_tree_add_uint(header_field_tree
, hf_dbus_response_in
, ptvcursor_tvbuff(packet
->cursor
), 0, 0, trans
->rep_frame
);
1076 proto_item_set_generated(it
);
1080 tvbuff_t
*tvb
= ptvcursor_tvbuff(packet
->cursor
);
1082 it
= proto_tree_add_string(header_field_tree
, hf_dbus_path
, tvb
, 0, 0, trans
->path
);
1083 proto_item_set_generated(it
);
1084 packet
->path
= trans
->path
;
1086 it
= proto_tree_add_string(header_field_tree
, hf_dbus_interface
, tvb
, 0, 0, trans
->interface
);
1087 proto_item_set_generated(it
);
1088 packet
->interface
= trans
->interface
;
1090 it
= proto_tree_add_string(header_field_tree
, hf_dbus_member
, tvb
, 0, 0, trans
->member
);
1091 proto_item_set_generated(it
);
1092 packet
->member
= trans
->member
;
1094 it
= proto_tree_add_uint(header_field_tree
, hf_dbus_response_to
, tvb
, 0, 0, trans
->req_frame
);
1095 proto_item_set_generated(it
);
1097 nstime_delta(&ns
, &packet
->pinfo
->fd
->abs_ts
, &trans
->req_time
);
1098 it
= proto_tree_add_time(header_field_tree
, hf_dbus_response_time
, tvb
, 0, 0, &ns
);
1099 proto_item_set_generated(it
);
1104 resolve_unique_name(dbus_packet_t
*packet
, proto_tree
*header_field_tree
) {
1106 tvbuff_t
*tvb
= ptvcursor_tvbuff(packet
->cursor
);
1108 if (packet
->sender
) {
1109 const char *sender_well_known
= (const char *)wmem_map_lookup(unique_name_map
, packet
->sender
);
1110 if (sender_well_known
) {
1111 set_address(&packet
->pinfo
->src
, AT_STRINGZ
, (int)strlen(sender_well_known
)+1, sender_well_known
);
1112 it
= proto_tree_add_string(header_field_tree
, hf_dbus_sender
, tvb
, 0, 0, sender_well_known
);
1113 proto_item_set_generated(it
);
1117 if (packet
->destination
) {
1118 const char *destination_well_known
= (const char *)wmem_map_lookup(unique_name_map
, packet
->destination
);
1119 if (destination_well_known
) {
1120 set_address(&packet
->pinfo
->dst
, AT_STRINGZ
, (int)strlen(destination_well_known
)+1, destination_well_known
);
1121 it
= proto_tree_add_string(header_field_tree
, hf_dbus_destination
, tvb
, 0, 0, destination_well_known
);
1122 proto_item_set_generated(it
);
1128 dissect_dbus_header_fields(dbus_packet_t
*packet
) {
1129 dbus_type_reader_t root_reader
= {
1131 .signature
= "a{yv}",
1133 dbus_type_reader_t
*reader
= &root_reader
;
1135 #define NEXT_OR_RETURN(hf, ett) if (!(reader = reader_next(reader, hf, ett, &value))) return 1;
1137 // Header Field Array
1138 NEXT_OR_RETURN(-1, ett_dbus_header_field_array
);
1139 proto_item
*header_field_array_pi
= reader
->container
;
1140 proto_item_set_text(header_field_array_pi
, "Header Field Array");
1141 while (reader
->level
> 0) {
1142 // Header Field (Dict)
1143 NEXT_OR_RETURN(-1, ett_dbus_header_field
);
1145 NEXT_OR_RETURN(hf_dbus_field_code
, -1);
1146 uint32_t field_code
= value
.uint
;
1147 const char *field_code_str
= val_to_str_const(field_code
, field_code_vals
, "Unknown field code");
1148 proto_item_append_text(reader
->container
, ", %s", field_code_str
);
1149 if (field_code
== DBUS_HEADER_FIELD_INVALID
) {
1150 add_expert(packet
, &ei_dbus_field_code_invalid
);
1151 reader_cleanup(reader
);
1155 // Header Field Value (Variant)
1156 NEXT_OR_RETURN(-1, -1);
1157 const char *header_field_signature
= value
.string
;
1159 const char *expected_signature
;
1160 switch (field_code
) {
1161 case DBUS_HEADER_FIELD_PATH
:
1162 expected_signature
= "o";
1164 case DBUS_HEADER_FIELD_INTERFACE
:
1165 case DBUS_HEADER_FIELD_MEMBER
:
1166 case DBUS_HEADER_FIELD_ERROR_NAME
:
1167 case DBUS_HEADER_FIELD_DESTINATION
:
1168 case DBUS_HEADER_FIELD_SENDER
:
1169 expected_signature
= "s";
1171 case DBUS_HEADER_FIELD_REPLY_SERIAL
:
1172 expected_signature
= "u";
1174 case DBUS_HEADER_FIELD_UNIX_FDS
:
1175 expected_signature
= "u";
1177 case DBUS_HEADER_FIELD_SIGNATURE
:
1178 expected_signature
= "g";
1181 expected_signature
= NULL
;
1184 if (expected_signature
&& strcmp(header_field_signature
, expected_signature
) != 0) {
1185 add_expert(packet
, &ei_dbus_field_signature_wrong
);
1186 reader_cleanup(reader
);
1191 switch (field_code
) {
1192 case DBUS_HEADER_FIELD_PATH
:
1193 NEXT_OR_RETURN(hf_dbus_path
, -1);
1194 packet
->path
= value
.string
;
1196 case DBUS_HEADER_FIELD_INTERFACE
:
1197 NEXT_OR_RETURN(hf_dbus_interface
, -1);
1198 packet
->interface
= value
.string
;
1199 if (!is_dbus_interface_valid(packet
->interface
)) {
1200 add_expert(packet
, &ei_dbus_interface_invalid
);
1201 reader_cleanup(reader
);
1205 case DBUS_HEADER_FIELD_MEMBER
:
1206 NEXT_OR_RETURN(hf_dbus_member
, -1);
1207 packet
->member
= value
.string
;
1208 if (!is_dbus_member_name_valid(packet
->member
)) {
1209 add_expert(packet
, &ei_dbus_member_invalid
);
1210 reader_cleanup(reader
);
1214 case DBUS_HEADER_FIELD_ERROR_NAME
:
1215 NEXT_OR_RETURN(hf_dbus_error_name
, -1);
1216 packet
->error_name
= value
.string
;
1217 if (!is_dbus_interface_valid(packet
->error_name
)) {
1218 add_expert(packet
, &ei_dbus_error_name_invalid
);
1219 reader_cleanup(reader
);
1223 case DBUS_HEADER_FIELD_DESTINATION
:
1224 NEXT_OR_RETURN(hf_dbus_destination
, -1);
1225 packet
->destination
= value
.string
;
1226 if (!is_dbus_bus_name_valid(packet
->destination
)) {
1227 add_expert(packet
, &ei_dbus_bus_name_invalid
);
1228 reader_cleanup(reader
);
1231 set_address(&packet
->pinfo
->dst
, AT_STRINGZ
, (int)strlen(packet
->destination
)+1,
1232 wmem_strdup(packet
->pinfo
->pool
, packet
->destination
));
1234 case DBUS_HEADER_FIELD_SENDER
:
1235 NEXT_OR_RETURN(hf_dbus_sender
, -1);
1236 packet
->sender
= value
.string
;
1237 if (!is_dbus_bus_name_valid(packet
->sender
)) {
1238 add_expert(packet
, &ei_dbus_bus_name_invalid
);
1239 reader_cleanup(reader
);
1242 set_address(&packet
->pinfo
->src
, AT_STRINGZ
, (int)strlen(packet
->sender
)+1,
1243 wmem_strdup(packet
->pinfo
->pool
, packet
->sender
));
1245 case DBUS_HEADER_FIELD_SIGNATURE
:
1246 NEXT_OR_RETURN(hf_dbus_signature
, -1);
1247 packet
->signature
= value
.string
;
1249 case DBUS_HEADER_FIELD_REPLY_SERIAL
:
1250 NEXT_OR_RETURN(hf_dbus_reply_serial
, -1);
1251 packet
->reply_serial
= value
.uint
;
1252 if (packet
->reply_serial
== 0) {
1253 add_expert(packet
, &ei_dbus_serial_invalid
);
1254 reader_cleanup(reader
);
1258 case DBUS_HEADER_FIELD_UNIX_FDS
:
1259 NEXT_OR_RETURN(hf_dbus_unix_fds
, -1);
1260 packet
->unix_fds
= value
.uint
;
1263 // Unknown Field code must be skipped without error
1265 NEXT_OR_RETURN(-1, -1);
1266 // Skip while inside Header Field Array -> Header Field Dict -> Variant
1267 } while (reader
->level
>= 3);
1270 NEXT_OR_RETURN(-1, -1);
1273 bool is_field_missing
= false;
1274 switch (packet
->message_type
) {
1275 case DBUS_MESSAGE_TYPE_METHOD_CALL
:
1276 is_field_missing
= !packet
->path
|| !packet
->member
;
1278 case DBUS_MESSAGE_TYPE_METHOD_RETURN
:
1279 is_field_missing
= !packet
->reply_serial
;
1281 case DBUS_MESSAGE_TYPE_ERROR
:
1282 is_field_missing
= !packet
->error_name
|| !packet
->reply_serial
;
1284 case DBUS_MESSAGE_TYPE_SIGNAL
:
1285 is_field_missing
= !packet
->path
|| !packet
->interface
|| !packet
->member
;
1288 DISSECTOR_ASSERT_NOT_REACHED();
1291 if (is_field_missing
) {
1292 expert_add_info(packet
->pinfo
, header_field_array_pi
, &ei_dbus_required_header_field_missing
);
1296 add_conversation(packet
, proto_item_get_subtree(header_field_array_pi
));
1297 if (dbus_resolve_names
) {
1298 resolve_unique_name(packet
, proto_item_get_subtree(header_field_array_pi
));
1301 switch(packet
->message_type
) {
1302 case DBUS_MESSAGE_TYPE_METHOD_CALL
:
1303 col_add_fstr(packet
->pinfo
->cinfo
, COL_INFO
, "%s(%s) @ %s", packet
->member
, packet
->signature
, packet
->path
);
1305 case DBUS_MESSAGE_TYPE_SIGNAL
:
1306 col_add_fstr(packet
->pinfo
->cinfo
, COL_INFO
, "* %s(%s) @ %s", packet
->member
, packet
->signature
, packet
->path
);
1308 case DBUS_MESSAGE_TYPE_ERROR
:
1309 if (packet
->member
) {
1310 col_add_fstr(packet
->pinfo
->cinfo
, COL_INFO
, "! %s: %s", packet
->member
, packet
->error_name
);
1312 col_add_fstr(packet
->pinfo
->cinfo
, COL_INFO
, "! %s", packet
->error_name
);
1315 case DBUS_MESSAGE_TYPE_METHOD_RETURN
:
1316 if (packet
->member
) {
1317 if (*packet
->signature
!= '\0') {
1318 col_add_fstr(packet
->pinfo
->cinfo
, COL_INFO
, "-> %s: '%s'", packet
->member
, packet
->signature
);
1320 col_add_fstr(packet
->pinfo
->cinfo
, COL_INFO
, "-> %s: OK", packet
->member
);
1324 col_add_fstr(packet
->pinfo
->cinfo
, COL_INFO
, "-> '%s'", packet
->signature
);
1328 DISSECTOR_ASSERT_NOT_REACHED();
1332 // Header length must be a multiple of 8 bytes
1333 return add_padding(packet
, SIG_CODE_STRUCT_OPEN
);
1337 dissect_dbus_header(dbus_packet_t
*packet
) {
1341 packet
->current_pi
= ptvcursor_add_ret_uint(packet
->cursor
, hf_dbus_endianness
, 1, ENC_NA
, &val
);
1344 packet
->enc
= ENC_LITTLE_ENDIAN
;
1347 packet
->enc
= ENC_BIG_ENDIAN
;
1350 add_expert(packet
, &ei_dbus_endianness_invalid
);
1355 packet
->message_type
= add_uint(packet
, hf_dbus_message_type
);
1356 const char *info
= try_val_to_str(packet
->message_type
, message_type_vals
);
1357 if (packet
->message_type
== DBUS_MESSAGE_TYPE_INVALID
) {
1358 col_set_str(packet
->pinfo
->cinfo
, COL_INFO
, info
);
1359 add_expert(packet
, &ei_dbus_message_type_invalid
);
1362 col_set_str(packet
->pinfo
->cinfo
, COL_INFO
, "Unknown message type");
1363 add_expert(packet
, &ei_dbus_message_type_unknown
);
1366 col_set_str(packet
->pinfo
->cinfo
, COL_INFO
, info
);
1369 ptvcursor_add_with_subtree(packet
->cursor
, hf_dbus_flags
, 1, packet
->enc
, ett_dbus_flags
);
1370 ptvcursor_add_no_advance(packet
->cursor
, hf_dbus_flags_no_reply_expected
, 1, packet
->enc
);
1371 ptvcursor_add_no_advance(packet
->cursor
, hf_dbus_flags_no_auto_start
, 1, packet
->enc
);
1372 ptvcursor_add_no_advance(packet
->cursor
, hf_dbus_flags_allow_interactive_authorization
, 1, packet
->enc
);
1373 packet
->flags
= tvb_get_uint8(ptvcursor_tvbuff(packet
->cursor
), ptvcursor_current_offset(packet
->cursor
));
1374 ptvcursor_advance(packet
->cursor
, 1);
1375 ptvcursor_pop_subtree(packet
->cursor
);
1378 if (add_uint(packet
, hf_dbus_version
) != 1) {
1379 add_expert(packet
, &ei_dbus_version_invalid
);
1384 packet
->body_len
= add_uint(packet
, hf_dbus_body_length
);
1387 packet
->serial
= add_uint(packet
, hf_dbus_serial
);
1388 if (packet
->serial
== 0) {
1389 add_expert(packet
, &ei_dbus_serial_invalid
);
1397 dissect_dbus(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
) {
1398 dbus_packet_t packet
= { .pinfo
= pinfo
, .signature
= "" };
1400 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "D-Bus");
1401 col_set_str(pinfo
->cinfo
, COL_INFO
, "D-Bus");
1403 proto_item
*pi
= proto_tree_add_protocol_format(tree
, proto_dbus
, tvb
, 0, -1, "D-Bus");
1404 proto_tree
*dbus_tree
= proto_item_add_subtree(pi
, ett_dbus
);
1407 packet
.cursor
= ptvcursor_new(pinfo
->pool
, dbus_tree
, tvb
, offset
);
1409 (void)(dissect_dbus_header(&packet
) ||
1410 dissect_dbus_header_fields(&packet
) ||
1411 dissect_dbus_body(&packet
));
1413 offset
= ptvcursor_current_offset(packet
.cursor
);
1414 proto_item_set_end(pi
, tvb
, offset
);
1415 ptvcursor_free(packet
.cursor
);
1419 #define DBUS_HEADER_LEN 16
1422 get_dbus_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
1423 int offset
, void *data _U_
) {
1424 uint32_t (*get_uint32
)(tvbuff_t
*, const int);
1426 uint32_t len_body
, len_hdr
;
1428 switch (tvb_get_uint8(tvb
, offset
)) {
1430 get_uint32
= tvb_get_letohl
;
1434 get_uint32
= tvb_get_ntohl
;
1438 len_hdr
= DBUS_HEADER_LEN
+ get_uint32(tvb
, offset
+ 12);
1439 len_hdr
= WS_ROUNDUP_8(len_hdr
);
1440 len_body
= get_uint32(tvb
, offset
+ 4);
1442 return len_hdr
+ len_body
;
1446 dissect_dbus_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
1447 return dissect_dbus(tvb
, pinfo
, tree
, data
);
1451 dissect_dbus_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
1452 tcp_dissect_pdus(tvb
, pinfo
, tree
, dbus_desegment
, DBUS_HEADER_LEN
,
1453 get_dbus_message_len
, dissect_dbus_pdu
, data
);
1454 return tvb_reported_length(tvb
);
1458 proto_register_dbus(void) {
1459 static hf_register_info hf
[] = {
1460 { &hf_dbus_endianness
, { "Endianness", "dbus.endianness",
1461 FT_UINT8
, BASE_NONE
, VALS(endianness_vals
), 0x00, NULL
, HFILL
}},
1462 { &hf_dbus_message_type
, { "Message Type", "dbus.message_type",
1463 FT_UINT8
, BASE_NONE
, VALS(message_type_vals
), 0x00, NULL
, HFILL
}},
1464 { &hf_dbus_flags
, { "Message Flags", "dbus.flags",
1465 FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
1466 { &hf_dbus_flags_no_reply_expected
, { "No Reply Expected", "dbus.flags.no_reply_expected",
1467 FT_BOOLEAN
, 8, TFS(¬_expected_vals
),
1468 DBUS_FLAGS_NO_REPLY_EXPECTED_MASK
, NULL
, HFILL
}},
1469 { &hf_dbus_flags_no_auto_start
, { "No Auto Start", "dbus.flags.no_auto_start",
1470 FT_BOOLEAN
, 8, TFS(&no_start_vals
),
1471 DBUS_FLAGS_NO_AUTO_START_MASK
, NULL
, HFILL
}},
1472 { &hf_dbus_flags_allow_interactive_authorization
, { "Allow Interactive Authorization", "dbus.flags.allow_interactive_authorization",
1473 FT_BOOLEAN
, 8, TFS(&allow_vals
),
1474 DBUS_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION_MASK
, NULL
, HFILL
}},
1475 { &hf_dbus_version
, { "Protocol Version", "dbus.version",
1476 FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1477 { &hf_dbus_body_length
, { "Message Body Length", "dbus.body_length",
1478 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1479 { &hf_dbus_serial
, { "Message Serial", "dbus.serial",
1480 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1481 { &hf_dbus_field_code
, { "Field Code", "dbus.field_code",
1482 FT_UINT8
, BASE_DEC
, VALS(field_code_vals
), 0x00, NULL
, HFILL
}},
1483 { &hf_dbus_padding
, { "Padding", "dbus.padding",
1484 FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x00, NULL
, HFILL
}},
1485 { &hf_dbus_path
, { "Path", "dbus.path",
1486 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1487 { &hf_dbus_interface
, { "Interface", "dbus.interface",
1488 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1489 { &hf_dbus_member
, { "Member", "dbus.member",
1490 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1491 { &hf_dbus_error_name
, { "Error name", "dbus.error_name",
1492 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1493 { &hf_dbus_reply_serial
, { "Reply serial", "dbus.reply_serial",
1494 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1495 { &hf_dbus_destination
, { "Destination", "dbus.destination",
1496 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1497 { &hf_dbus_sender
, { "Sender", "dbus.sender",
1498 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1499 { &hf_dbus_signature
, { "Signature", "dbus.signature",
1500 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1501 { &hf_dbus_unix_fds
, { "Unix FDs", "dbus.unix_fds",
1502 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1503 { &hf_dbus_body
, { "Body", "dbus.body",
1504 FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x00, NULL
, HFILL
}},
1505 { &hf_dbus_type_byte
, { "Byte", "dbus.type.byte",
1506 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}},
1507 { &hf_dbus_type_boolean
, { "Boolean", "dbus.type.boolean",
1508 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1509 { &hf_dbus_type_int16
, { "Int16", "dbus.type.int16",
1510 FT_INT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1511 { &hf_dbus_type_uint16
, { "Uint16", "dbus.type.uint16",
1512 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}},
1513 { &hf_dbus_type_int32
, { "Int32", "dbus.type.int32",
1514 FT_INT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1515 { &hf_dbus_type_uint32
, { "Uint32", "dbus.type.uint32",
1516 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}},
1517 { &hf_dbus_type_int64
, { "Int64", "dbus.type.int64",
1518 FT_INT64
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1519 { &hf_dbus_type_uint64
, { "Uint64", "dbus.type.uint64",
1520 FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x00, NULL
, HFILL
}},
1521 { &hf_dbus_type_double
, { "Double", "dbus.type.double",
1522 FT_DOUBLE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1523 { &hf_dbus_type_string
, { "String", "dbus.type.string",
1524 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1525 { &hf_dbus_type_object_path
, { "Object Path", "dbus.type.object_path",
1526 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1527 { &hf_dbus_type_signature
, { "Signature", "dbus.type.signature",
1528 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1529 { &hf_dbus_type_array
, { "Array", "dbus.type.array",
1530 FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x00, NULL
, HFILL
}},
1531 { &hf_dbus_type_array_length
, { "Array Length", "dbus.type.array.length",
1532 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1533 { &hf_dbus_type_struct
, { "Struct", "dbus.type.struct",
1534 FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x00, NULL
, HFILL
}},
1535 { &hf_dbus_type_variant
, { "Variant", "dbus.type.variant",
1536 FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x00, NULL
, HFILL
}},
1537 { &hf_dbus_type_variant_signature
, { "Variant Signature", "dbus.type.variant.signature",
1538 FT_UINT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
1539 { &hf_dbus_type_dict_entry
, { "Dict Entry", "dbus.type.dict_entry",
1540 FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x00, NULL
, HFILL
}},
1541 { &hf_dbus_type_dict_entry_key
, { "Key", "dbus.type.dict_entry.key",
1542 FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x00, NULL
, HFILL
}},
1543 { &hf_dbus_type_unix_fd
, { "Unix FD", "dbus.type.unix_fd",
1544 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
1545 { &hf_dbus_response_in
, { "Response In", "dbus.response_in",
1546 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
1547 "The response to this D-Bus call is in this frame", HFILL
}},
1548 { &hf_dbus_response_to
, { "Response To", "dbus.response_to",
1549 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
1550 "This is a response to the D-Bus call in this frame", HFILL
}},
1551 { &hf_dbus_response_time
, { "Response Time", "dbus.response_time",
1552 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
1553 "The time between the Call and the Reply", HFILL
}},
1556 static int *ett
[] = {
1559 &ett_dbus_header_field_array
,
1560 &ett_dbus_header_field
,
1562 &ett_dbus_type_array
,
1563 &ett_dbus_type_struct
,
1564 &ett_dbus_type_variant
,
1565 &ett_dbus_type_dict_entry
,
1568 static ei_register_info ei
[] = {
1569 { &ei_dbus_endianness_invalid
, { "dbus.endianness.invalid",
1570 PI_PROTOCOL
, PI_ERROR
, "Invalid endianness flag", EXPFILL
}},
1571 { &ei_dbus_message_type_invalid
, { "dbus.message_type.invalid",
1572 PI_PROTOCOL
, PI_ERROR
, "Invalid message type", EXPFILL
}},
1573 { &ei_dbus_message_type_unknown
, { "dbus.message_type.unknown",
1574 PI_PROTOCOL
, PI_WARN
, "Unknown message type", EXPFILL
}},
1575 { &ei_dbus_version_invalid
, { "dbus.version.invalid",
1576 PI_PROTOCOL
, PI_ERROR
, "Invalid version", EXPFILL
}},
1577 { &ei_dbus_serial_invalid
, { "dbus.serial.invalid",
1578 PI_PROTOCOL
, PI_ERROR
, "Invalid serial", EXPFILL
}},
1579 { &ei_dbus_field_code_invalid
, { "dbus.field_code.invalid",
1580 PI_PROTOCOL
, PI_ERROR
, "Invalid field code", EXPFILL
}},
1581 { &ei_dbus_required_header_field_missing
, { "dbus.required_header_field_missing",
1582 PI_PROTOCOL
, PI_ERROR
, "Required header field is missing", EXPFILL
}},
1583 { &ei_dbus_padding_invalid
, { "dbus.padding.invalid",
1584 PI_PROTOCOL
, PI_ERROR
, "Padding bytes must be zero", EXPFILL
}},
1585 { &ei_dbus_field_signature_wrong
, { "dbus.field_signature_wrong",
1586 PI_PROTOCOL
, PI_ERROR
, "Wrong header field variant signature", EXPFILL
}},
1587 { &ei_dbus_interface_invalid
, { "dbus.interface.invalid",
1588 PI_PROTOCOL
, PI_ERROR
, "Invalid interface name", EXPFILL
}},
1589 { &ei_dbus_member_invalid
, { "dbus.member.invalid",
1590 PI_PROTOCOL
, PI_ERROR
, "Invalid member name", EXPFILL
}},
1591 { &ei_dbus_error_name_invalid
, { "dbus.error_name.invalid",
1592 PI_PROTOCOL
, PI_ERROR
, "Invalid error name", EXPFILL
}},
1593 { &ei_dbus_bus_name_invalid
, { "dbus.bus_name.invalid",
1594 PI_PROTOCOL
, PI_ERROR
, "Invalid bus name", EXPFILL
}},
1595 { &ei_dbus_type_boolean_invalid
, { "dbus.type.boolean.invalid",
1596 PI_PROTOCOL
, PI_ERROR
, "Invalid boolean value", EXPFILL
}},
1597 { &ei_dbus_string_invalid
, { "dbus.type.string.invalid",
1598 PI_PROTOCOL
, PI_ERROR
, "Invalid string value", EXPFILL
}},
1599 { &ei_dbus_type_signature_invalid
, { "dbus.type.signature.invalid",
1600 PI_PROTOCOL
, PI_ERROR
, "Invalid signature", EXPFILL
}},
1601 { &ei_dbus_type_array_too_long
, { "dbus.type.array.too_long",
1602 PI_PROTOCOL
, PI_ERROR
, "Array too long", EXPFILL
}},
1603 { &ei_dbus_type_array_content_out_of_bounds
, { "dbus.type.array.content_out_of_bounds",
1604 PI_PROTOCOL
, PI_ERROR
, "Array content is out of bounds", EXPFILL
}},
1605 { &ei_dbus_type_object_path_invalid
, { "dbus.type.object_path.invalid",
1606 PI_PROTOCOL
, PI_ERROR
, "Invalid object path", EXPFILL
}},
1607 { &ei_dbus_type_variant_signature_invalid
, { "dbus.type.variant.signature.invalid",
1608 PI_PROTOCOL
, PI_ERROR
, "Invalid variant signature", EXPFILL
}},
1609 { &ei_dbus_nested_too_deeply
, { "dbus.nested_too_deeply",
1610 PI_PROTOCOL
, PI_ERROR
, "Containers nested too deeply", EXPFILL
}},
1613 expert_module_t
*expert_dbus
;
1614 module_t
*dbus_module
;
1616 proto_dbus
= proto_register_protocol("D-Bus", "D-Bus", "dbus");
1617 proto_register_field_array(proto_dbus
, hf
, array_length(hf
));
1618 proto_register_subtree_array(ett
, array_length(ett
));
1619 expert_dbus
= expert_register_protocol(proto_dbus
);
1620 expert_register_field_array(expert_dbus
, ei
, array_length(ei
));
1622 dbus_handle
= register_dissector("dbus", dissect_dbus
, proto_dbus
);
1623 dbus_handle_tcp
= register_dissector("dbus.tcp", dissect_dbus_tcp
, proto_dbus
);
1625 dbus_module
= prefs_register_protocol(proto_dbus
, NULL
);
1626 prefs_register_bool_preference(dbus_module
, "resolve_names",
1627 "Resolve unique names into well-known names",
1628 "Show the first inferred well-known bus name (e.g. \"com.example.MusicPlayer1\") instead of the unique connection name (e.g. \":1.18\"). Might be confusing if a connection owns more than one well-known name.", &dbus_resolve_names
);
1630 request_info_map
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash
, g_str_equal
);
1631 unique_name_map
= wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash
, g_str_equal
);
1635 proto_reg_handoff_dbus(void) {
1636 dissector_add_uint("wtap_encap", WTAP_ENCAP_DBUS
, dbus_handle
);
1637 dissector_add_for_decode_as_with_preference("tcp.port", dbus_handle_tcp
);
1641 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1646 * indent-tabs-mode: t
1649 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1650 * :indentSize=8:tabSize=8:noTabs=false: