Coverage Report

Created: 2026-07-12 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-dbus.c
Line
Count
Source
1
/* packet-dbus.c
2
 * Routines for D-Bus dissection
3
 * Copyright 2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
4
 * Copyright 2020, Simon Holesch <simon@holesch.de>
5
 *
6
 * Protocol specification available at http://dbus.freedesktop.org/doc/dbus-specification.html
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <wiretap/wtap.h>
19
#include <epan/expert.h>
20
#include <epan/ptvcursor.h>
21
#include <epan/tfs.h>
22
#include <wsutil/ws_roundup.h>
23
#include <epan/conversation.h>
24
#include "packet-tcp.h"
25
26
0
#define DBUS_MAX_ARRAY_LEN (64 * 1024 * 1024)
27
0
#define DBUS_MAX_NAME_LENGTH 255
28
0
#define DBUS_MAX_SIGNATURE_LENGTH 255
29
0
#define DBUS_MAX_TYPE_NESTING_LEVEL 32
30
0
#define DBUS_MAX_TOTAL_NESTING_LEVEL (2 * DBUS_MAX_TYPE_NESTING_LEVEL)
31
32
0
#define SIG_CODE_BYTE ('y')
33
0
#define SIG_CODE_BOOLEAN ('b')
34
0
#define SIG_CODE_INT16 ('n')
35
0
#define SIG_CODE_UINT16 ('q')
36
0
#define SIG_CODE_INT32 ('i')
37
0
#define SIG_CODE_UINT32 ('u')
38
0
#define SIG_CODE_INT64 ('x')
39
0
#define SIG_CODE_UINT64 ('t')
40
0
#define SIG_CODE_DOUBLE ('d')
41
0
#define SIG_CODE_STRING ('s')
42
0
#define SIG_CODE_OBJECT_PATH ('o')
43
0
#define SIG_CODE_SIGNATURE ('g')
44
0
#define SIG_CODE_ARRAY ('a')
45
0
#define SIG_CODE_STRUCT_OPEN ('(')
46
0
#define SIG_CODE_STRUCT_CLOSE (')')
47
0
#define SIG_CODE_VARIANT ('v')
48
0
#define SIG_CODE_DICT_ENTRY_OPEN ('{')
49
0
#define SIG_CODE_DICT_ENTRY_CLOSE ('}')
50
0
#define SIG_CODE_UNIX_FD ('h')
51
52
void proto_register_dbus(void);
53
void proto_reg_handoff_dbus(void);
54
55
static int proto_dbus;
56
static bool dbus_desegment = true;
57
static bool dbus_resolve_names = true;
58
59
static dissector_handle_t dbus_handle;
60
static dissector_handle_t dbus_handle_tcp;
61
62
0
#define DBUS_MESSAGE_TYPE_INVALID 0
63
0
#define DBUS_MESSAGE_TYPE_METHOD_CALL 1
64
0
#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
65
0
#define DBUS_MESSAGE_TYPE_ERROR 3
66
0
#define DBUS_MESSAGE_TYPE_SIGNAL 4
67
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" },
74
  { 0, NULL }
75
};
76
77
0
#define DBUS_HEADER_FIELD_INVALID        0
78
0
#define DBUS_HEADER_FIELD_PATH           1
79
0
#define DBUS_HEADER_FIELD_INTERFACE      2
80
0
#define DBUS_HEADER_FIELD_MEMBER         3
81
0
#define DBUS_HEADER_FIELD_ERROR_NAME     4
82
0
#define DBUS_HEADER_FIELD_REPLY_SERIAL   5
83
0
#define DBUS_HEADER_FIELD_DESTINATION    6
84
0
#define DBUS_HEADER_FIELD_SENDER         7
85
0
#define DBUS_HEADER_FIELD_SIGNATURE      8
86
0
#define DBUS_HEADER_FIELD_UNIX_FDS       9
87
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" },
99
  { 0, NULL }
100
};
101
102
static const value_string endianness_vals[] = {
103
  { 'l', "little-endian" },
104
  { 'B', "big-endian" },
105
  { 0, NULL }
106
};
107
108
15
#define DBUS_FLAGS_NO_REPLY_EXPECTED_MASK 0x01
109
15
#define DBUS_FLAGS_NO_AUTO_START_MASK 0x02
110
15
#define DBUS_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION_MASK 0x04
111
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" };
115
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;
160
161
static int ett_dbus;
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;
170
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;
192
193
typedef struct {
194
  ptvcursor_t *cursor;
195
  packet_info *pinfo;
196
  unsigned enc;
197
  uint32_t message_type;
198
  uint8_t flags;
199
  uint32_t body_len;
200
  uint32_t serial;
201
202
  proto_item *current_pi;
203
  const char *path;
204
  const char *interface;
205
  const char *member;
206
  const char *error_name;
207
  uint32_t reply_serial;
208
  const char *destination;
209
  const char *sender;
210
  const char *signature;
211
  uint32_t unix_fds;
212
} dbus_packet_t;
213
214
typedef struct _dbus_type_reader_t {
215
  dbus_packet_t *packet;
216
  const char *signature;
217
  uint32_t level;
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;
223
  bool is_in_variant;
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;
230
231
typedef union {
232
  bool bool_;
233
  uint32_t uint;
234
  int32_t int_;
235
  uint64_t uint64;
236
  int64_t int64;
237
  double double_;
238
  const char *string;
239
} dbus_val_t;
240
241
typedef struct {
242
  uint32_t req_frame;
243
  uint32_t rep_frame;
244
  nstime_t req_time;
245
  const char *path;
246
  const char *interface;
247
  const char *member;
248
} dbus_transaction_t;
249
250
typedef struct {
251
  wmem_map_t *packets;
252
} dbus_conv_info_t;
253
254
static wmem_map_t *request_info_map;
255
static wmem_map_t *unique_name_map;
256
257
static bool
258
0
is_ascii_digit(char c) {
259
0
  return (unsigned)c - '0' < 10;
260
0
}
261
262
static bool
263
0
is_ascii_alpha(char c) {
264
0
  return ((unsigned)c | 0x20) - 'a' <= 'z' - 'a';
265
0
}
266
267
static bool
268
0
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
271
  //   slash characters.
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
0
  if (*path == '/' && *(path + 1) == '\0') {
277
0
    return true;
278
0
  }
279
280
0
  while (*path == '/') {
281
0
    path++;
282
283
0
    if (*path == '/') {
284
0
      return false;
285
0
    }
286
287
0
    while (is_ascii_alpha(*path) || is_ascii_digit(*path) || *path == '_') {
288
0
      path++;
289
0
    }
290
291
0
    if (*path == '\0') {
292
0
      return *(path - 1) != '/';
293
0
    }
294
0
  }
295
296
0
  return false;
297
0
}
298
299
static bool
300
0
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.
305
0
  int elements = 0;
306
0
  const char *p = interface;
307
0
  do {
308
0
    if (!(is_ascii_alpha(*p) || *p == '_')) {
309
0
      return false;
310
0
    }
311
0
    p++;
312
0
    elements++;
313
314
0
    while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_') {
315
0
      p++;
316
0
    }
317
318
0
    if (*p == '\0') {
319
0
      size_t length = p - interface;
320
0
      return elements >= 2 && length <= DBUS_MAX_NAME_LENGTH;
321
0
    }
322
0
  } while (*p++ == '.');
323
324
0
  return false;
325
0
}
326
327
static bool
328
0
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
0
  const char *p = member_name;
334
335
0
  if (!(is_ascii_alpha(*p) || *p == '_')) {
336
0
    return false;
337
0
  }
338
339
0
  do {
340
0
    p++;
341
0
  } while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_');
342
343
0
  if (*p == '\0') {
344
0
    size_t length = p - member_name;
345
0
    return length <= DBUS_MAX_NAME_LENGTH;
346
0
  }
347
348
0
  return false;
349
0
}
350
351
static bool
352
0
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.
363
0
  int elements = 0;
364
0
  const char *p = bus_name;
365
0
  bool is_unique_name = false;
366
367
0
  if (*p == ':') {
368
0
    is_unique_name = true;
369
0
    p++;
370
0
  }
371
372
0
  do {
373
0
    if (!(is_ascii_alpha(*p) || *p == '_' || *p == '-' || (is_unique_name && is_ascii_digit(*p)))) {
374
0
      return false;
375
0
    }
376
0
    p++;
377
0
    elements++;
378
379
0
    while (is_ascii_alpha(*p) || is_ascii_digit(*p) || *p == '_' || *p == '-') {
380
0
      p++;
381
0
    }
382
383
0
    if (*p == '\0') {
384
0
      size_t length = p - bus_name;
385
0
      return elements >= 2 && length <= DBUS_MAX_NAME_LENGTH;
386
0
    }
387
0
  } while (*p++ == '.');
388
389
0
  return false;
390
0
}
391
392
static bool
393
0
is_basic_type(char sig_code) {
394
0
  switch (sig_code) {
395
0
  case SIG_CODE_BYTE:
396
0
  case SIG_CODE_BOOLEAN:
397
0
  case SIG_CODE_INT16:
398
0
  case SIG_CODE_UINT16:
399
0
  case SIG_CODE_INT32:
400
0
  case SIG_CODE_UINT32:
401
0
  case SIG_CODE_INT64:
402
0
  case SIG_CODE_UINT64:
403
0
  case SIG_CODE_DOUBLE:
404
0
  case SIG_CODE_STRING:
405
0
  case SIG_CODE_OBJECT_PATH:
406
0
  case SIG_CODE_SIGNATURE:
407
0
  case SIG_CODE_UNIX_FD:
408
0
    return true;
409
0
  default:
410
0
    return false;
411
0
  }
412
0
}
413
414
static const char *
415
0
skip_enclosed_container(const char *signature, char open_bracket, char closed_bracket) {
416
0
  int nested = 0;
417
0
  for (char sig_code = *signature++; sig_code != '\0'; sig_code = *signature++) {
418
0
    if (sig_code == closed_bracket) {
419
0
      if (nested == 0) {
420
0
        return signature;
421
0
      }
422
0
      nested--;
423
0
    } else if (sig_code == open_bracket) {
424
0
      nested++;
425
0
    }
426
0
  }
427
0
  return NULL;
428
0
}
429
430
static const char *
431
0
skip_single_complete_type(const char *signature) {
432
0
  char sig_code;
433
0
  while (1) {
434
0
    sig_code = *signature++;
435
0
    switch (sig_code) {
436
0
    case SIG_CODE_BYTE:
437
0
    case SIG_CODE_BOOLEAN:
438
0
    case SIG_CODE_INT16:
439
0
    case SIG_CODE_UINT16:
440
0
    case SIG_CODE_INT32:
441
0
    case SIG_CODE_UINT32:
442
0
    case SIG_CODE_INT64:
443
0
    case SIG_CODE_UINT64:
444
0
    case SIG_CODE_DOUBLE:
445
0
    case SIG_CODE_STRING:
446
0
    case SIG_CODE_OBJECT_PATH:
447
0
    case SIG_CODE_SIGNATURE:
448
0
    case SIG_CODE_VARIANT:
449
0
    case SIG_CODE_UNIX_FD:
450
0
      return signature;
451
0
    case SIG_CODE_ARRAY:
452
0
      continue;
453
0
    case SIG_CODE_STRUCT_OPEN:
454
0
      return skip_enclosed_container(signature, SIG_CODE_STRUCT_OPEN, SIG_CODE_STRUCT_CLOSE);
455
0
    case SIG_CODE_DICT_ENTRY_OPEN:
456
0
      return skip_enclosed_container(signature, SIG_CODE_DICT_ENTRY_OPEN, SIG_CODE_DICT_ENTRY_CLOSE);
457
0
    default:
458
0
      return NULL;
459
0
    }
460
0
  }
461
0
}
462
463
static bool
464
0
is_dbus_signature_valid(const char *signature, dbus_packet_t *packet) {
465
0
  char sig_code;
466
0
  size_t length = 0;
467
0
  char prev_sig_code = '\0';
468
0
  wmem_stack_t *expected_chars = wmem_stack_new(packet->pinfo->pool);
469
470
0
  while ((sig_code = *signature++) != '\0') {
471
0
    if (++length >= DBUS_MAX_SIGNATURE_LENGTH) {
472
0
      return false;
473
0
    }
474
475
0
    switch (sig_code) {
476
0
    case SIG_CODE_BYTE:
477
0
    case SIG_CODE_SIGNATURE:
478
0
    case SIG_CODE_VARIANT:
479
0
    case SIG_CODE_INT16:
480
0
    case SIG_CODE_UINT16:
481
0
    case SIG_CODE_INT32:
482
0
    case SIG_CODE_UINT32:
483
0
    case SIG_CODE_BOOLEAN:
484
0
    case SIG_CODE_OBJECT_PATH:
485
0
    case SIG_CODE_STRING:
486
0
    case SIG_CODE_UNIX_FD:
487
0
    case SIG_CODE_INT64:
488
0
    case SIG_CODE_UINT64:
489
0
    case SIG_CODE_DOUBLE:
490
0
      break;
491
0
    case SIG_CODE_ARRAY:
492
0
      switch (*signature) {
493
0
      case '\0':
494
0
      case SIG_CODE_STRUCT_CLOSE:
495
0
      case SIG_CODE_DICT_ENTRY_CLOSE:
496
        // arrays must be followed by a single complete type
497
0
        return false;
498
0
      }
499
      // invalid signature codes are detected in the next iteration
500
0
      break;
501
0
    case SIG_CODE_STRUCT_OPEN:
502
0
      if (*signature == SIG_CODE_STRUCT_CLOSE) {
503
        // empty structures are not allowed
504
0
        return false;
505
0
      }
506
0
      wmem_stack_push(expected_chars, (void *)SIG_CODE_STRUCT_CLOSE);
507
0
      break;
508
0
    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
0
      if (prev_sig_code != SIG_CODE_ARRAY || !is_basic_type(*signature)) {
512
0
        return false;
513
0
      }
514
515
      // dict entries must contain exactly two single complete types
516
      // + 1 can be used here, since the key is a basic type
517
0
      const char *sig_code_close = skip_single_complete_type(signature + 1);
518
0
      if (!sig_code_close || *sig_code_close != SIG_CODE_DICT_ENTRY_CLOSE) {
519
0
        return false;
520
0
      }
521
0
      wmem_stack_push(expected_chars, (void *)SIG_CODE_DICT_ENTRY_CLOSE);
522
0
      break;
523
0
    }
524
0
    case SIG_CODE_STRUCT_CLOSE:
525
0
    case SIG_CODE_DICT_ENTRY_CLOSE:
526
0
      if (wmem_stack_count(expected_chars) == 0 ||
527
0
        (char)(uintptr_t)wmem_stack_pop(expected_chars) != sig_code) {
528
0
        return false;
529
0
      }
530
0
      break;
531
0
    default:
532
0
      return false;
533
0
    }
534
535
0
    prev_sig_code = sig_code;
536
0
  }
537
0
  return wmem_stack_count(expected_chars) == 0;
538
0
}
539
540
static void
541
0
add_expert(dbus_packet_t *packet, expert_field *ei) {
542
0
  expert_add_info(packet->pinfo, packet->current_pi, ei);
543
0
}
544
545
static uint32_t
546
0
add_uint(dbus_packet_t *packet, int hf) {
547
0
  header_field_info *info = proto_registrar_get_nth(hf);
548
0
  int length;
549
0
  uint32_t value;
550
0
  switch (info->type) {
551
0
  case FT_UINT8:
552
0
    length = 1;
553
0
    break;
554
0
  case FT_UINT32:
555
0
    length = 4;
556
0
    break;
557
0
  default:
558
0
    DISSECTOR_ASSERT_NOT_REACHED();
559
0
  }
560
0
  packet->current_pi = ptvcursor_add_ret_uint(packet->cursor, hf, length, packet->enc, &value);
561
0
  return value;
562
0
}
563
564
static const char *
565
0
add_dbus_string(dbus_packet_t *packet, int hf, unsigned uint_length) {
566
0
  const char *string;
567
0
  int start_offset = ptvcursor_current_offset(packet->cursor);
568
0
  proto_item *pi = ptvcursor_add_ret_string(packet->cursor, hf, uint_length,
569
0
      packet->enc | ENC_UTF_8, packet->pinfo->pool, (const uint8_t**)&string);
570
0
  int item_length = ptvcursor_current_offset(packet->cursor) - start_offset;
571
0
  uint8_t term_byte = tvb_get_uint8(ptvcursor_tvbuff(packet->cursor), ptvcursor_current_offset(packet->cursor));
572
0
  proto_item_set_len(pi, item_length + 1);
573
0
  ptvcursor_advance(packet->cursor, 1);
574
0
  packet->current_pi = pi;
575
576
0
  if ((strlen(string) != (size_t)(item_length - uint_length)) || (term_byte != '\0')) {
577
0
    return NULL;
578
0
  }
579
0
  return string;
580
0
}
581
582
static int
583
0
calculate_padding_len(int offset, char sig) {
584
0
  int alignment;
585
0
  switch (sig) {
586
0
  case SIG_CODE_BYTE:
587
0
  case SIG_CODE_SIGNATURE:
588
0
  case SIG_CODE_VARIANT:
589
0
  default:
590
0
    alignment = 1;
591
0
    break;
592
0
  case SIG_CODE_INT16:
593
0
  case SIG_CODE_UINT16:
594
0
    alignment = 2;
595
0
    break;
596
0
  case SIG_CODE_INT32:
597
0
  case SIG_CODE_UINT32:
598
0
  case SIG_CODE_BOOLEAN:
599
0
  case SIG_CODE_OBJECT_PATH:
600
0
  case SIG_CODE_ARRAY:
601
0
  case SIG_CODE_STRING:
602
0
  case SIG_CODE_UNIX_FD:
603
0
    alignment = 4;
604
0
    break;
605
0
  case SIG_CODE_INT64:
606
0
  case SIG_CODE_UINT64:
607
0
  case SIG_CODE_DOUBLE:
608
0
  case SIG_CODE_STRUCT_OPEN:
609
0
  case SIG_CODE_DICT_ENTRY_OPEN:
610
0
    alignment = 8;
611
0
    break;
612
0
  }
613
0
  return (alignment - (offset % alignment)) % alignment;
614
0
}
615
616
static int
617
0
add_padding(dbus_packet_t *packet, char sig) {
618
0
  uint8_t value;
619
0
  tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
620
0
  int offset = ptvcursor_current_offset(packet->cursor);
621
0
  int padding_len = calculate_padding_len(offset, sig);
622
623
0
  if (padding_len != 0) {
624
0
    packet->current_pi = ptvcursor_add(packet->cursor, hf_dbus_padding, padding_len, packet->enc);
625
0
    for (int i = offset; i < (offset + padding_len); i++) {
626
0
      value = tvb_get_uint8(tvb, i);
627
0
      if (value != 0) {
628
0
        add_expert(packet, &ei_dbus_padding_invalid);
629
0
        return 1;
630
0
      }
631
0
    }
632
0
    proto_item_set_hidden(packet->current_pi);
633
0
  }
634
0
  return 0;
635
0
}
636
637
static void
638
0
reader_cleanup(dbus_type_reader_t *reader) {
639
0
  for (dbus_type_reader_t *r = reader; r->parent; r = r->parent) {
640
0
    ptvcursor_pop_subtree(r->packet->cursor);
641
0
  }
642
0
}
643
644
static dbus_type_reader_t *
645
0
reader_next(dbus_type_reader_t *reader, int hf, int ett, dbus_val_t *value) {
646
0
  int err = 0;
647
0
  char sig_code = *reader->signature++;
648
0
  dbus_packet_t *packet = reader->packet;
649
0
  bool is_single_complete_type = true;
650
0
  add_padding(packet, sig_code);
651
652
0
  switch (sig_code) {
653
0
  case SIG_CODE_BYTE:
654
0
    packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
655
0
        hf != -1 ? hf : hf_dbus_type_byte, 1, packet->enc, &value->uint);
656
0
    break;
657
0
  case SIG_CODE_BOOLEAN: {
658
0
    int offset = ptvcursor_current_offset(packet->cursor);
659
0
    tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
660
0
    uint8_t val = tvb_get_uint8(tvb, offset);
661
0
    packet->current_pi = ptvcursor_add_ret_boolean(packet->cursor,
662
0
        hf != -1 ? hf : hf_dbus_type_boolean, 4, packet->enc, &value->bool_);
663
0
    if (val >= 2) {
664
0
      add_expert(packet, &ei_dbus_type_boolean_invalid);
665
0
      err = 1;
666
0
    }
667
0
    break;
668
0
  }
669
0
  case SIG_CODE_INT16:
670
0
    packet->current_pi = ptvcursor_add_ret_int(packet->cursor,
671
0
        hf != -1 ? hf : hf_dbus_type_int16, 2, packet->enc, &value->int_);
672
0
    break;
673
0
  case SIG_CODE_UINT16:
674
0
    packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
675
0
        hf != -1 ? hf : hf_dbus_type_uint16, 2, packet->enc, &value->uint);
676
0
    break;
677
0
  case SIG_CODE_INT32:
678
0
    packet->current_pi = ptvcursor_add_ret_int(packet->cursor,
679
0
        hf != -1 ? hf : hf_dbus_type_int32, 4, packet->enc, &value->int_);
680
0
    break;
681
0
  case SIG_CODE_UINT32:
682
0
    packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
683
0
        hf != -1 ? hf : hf_dbus_type_uint32, 4, packet->enc, &value->uint);
684
0
    break;
685
0
  case SIG_CODE_INT64: {
686
0
    int offset = ptvcursor_current_offset(packet->cursor);
687
0
    tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
688
0
    value->int64 = tvb_get_int64(tvb, offset, packet->enc);
689
0
    packet->current_pi = ptvcursor_add(packet->cursor,
690
0
        hf != -1 ? hf : hf_dbus_type_int64, 8, packet->enc);
691
0
    break;
692
0
  }
693
0
  case SIG_CODE_UINT64: {
694
0
    int offset = ptvcursor_current_offset(packet->cursor);
695
0
    tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
696
0
    value->uint64 = tvb_get_uint64(tvb, offset, packet->enc);
697
0
    packet->current_pi = ptvcursor_add(packet->cursor,
698
0
        hf != -1 ? hf : hf_dbus_type_uint64, 8, packet->enc);
699
0
    break;
700
0
  }
701
0
  case SIG_CODE_DOUBLE: {
702
0
    int offset = ptvcursor_current_offset(packet->cursor);
703
0
    tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
704
0
    value->double_ = tvb_get_ieee_double(tvb, offset, packet->enc);
705
0
    packet->current_pi = ptvcursor_add(packet->cursor,
706
0
        hf != -1 ? hf : hf_dbus_type_double, 8, packet->enc);
707
0
    break;
708
0
  }
709
0
  case SIG_CODE_STRING: {
710
0
    const char *val = add_dbus_string(packet,
711
0
        hf != -1 ? hf : hf_dbus_type_string, 4);
712
0
    if (!val || !g_utf8_validate(val, -1, NULL)) {
713
0
      add_expert(packet, &ei_dbus_string_invalid);
714
0
      err = 1;
715
0
    }
716
0
    value->string = val;
717
0
    break;
718
0
  }
719
0
  case SIG_CODE_OBJECT_PATH: {
720
0
    const char *val = add_dbus_string(packet, hf != -1 ? hf : hf_dbus_type_object_path, 4);
721
0
    if (!val || !is_dbus_object_path_valid(val)) {
722
0
      add_expert(packet, &ei_dbus_type_object_path_invalid);
723
0
      err = 1;
724
0
    }
725
0
    value->string = val;
726
0
    break;
727
0
  }
728
0
  case SIG_CODE_SIGNATURE: {
729
0
    const char *val = add_dbus_string(packet, hf != -1 ? hf : hf_dbus_type_signature, 1);
730
0
    if (!val || !is_dbus_signature_valid(val, packet)) {
731
0
      add_expert(packet, &ei_dbus_type_signature_invalid);
732
0
      err = 1;
733
0
    }
734
0
    value->string = val;
735
0
    break;
736
0
  }
737
0
  case SIG_CODE_ARRAY: {
738
0
    is_single_complete_type = false;
739
0
    proto_item *array = ptvcursor_add_with_subtree(packet->cursor, hf != -1 ? hf : hf_dbus_type_array,
740
0
        SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_array);
741
0
    if (*reader->signature == SIG_CODE_DICT_ENTRY_OPEN) {
742
0
      proto_item_append_text(array, " (Dict)");
743
0
    }
744
0
    uint32_t array_len = add_uint(packet, hf_dbus_type_array_length);
745
0
    value->uint = array_len;
746
0
    add_padding(packet, *reader->signature);
747
0
    if (array_len == 0) {
748
0
      reader->signature = skip_single_complete_type(reader->signature);
749
      // all signatures are validated
750
0
      DISSECTOR_ASSERT(reader->signature);
751
0
      ptvcursor_pop_subtree(packet->cursor);
752
0
      is_single_complete_type = true;
753
0
    } else if (array_len <= DBUS_MAX_ARRAY_LEN) {
754
0
      int end_offset = ptvcursor_current_offset(packet->cursor) + array_len;
755
0
      dbus_type_reader_t *child = wmem_new(packet->pinfo->pool, dbus_type_reader_t);
756
0
      *child = (dbus_type_reader_t){
757
0
        .packet = reader->packet,
758
0
        .signature = reader->signature,
759
0
        .level = reader->level + 1,
760
0
        .array_level = reader->array_level + 1,
761
0
        .array_type_start = reader->signature,
762
0
        .array_end_offset = end_offset,
763
0
        .container = array,
764
0
        .parent = reader,
765
0
      };
766
0
      reader = child;
767
0
    } else {
768
0
      add_expert(packet, &ei_dbus_type_array_too_long);
769
0
      err = 1;
770
0
      ptvcursor_pop_subtree(packet->cursor);
771
0
    }
772
0
    break;
773
0
  }
774
0
  case SIG_CODE_STRUCT_OPEN: {
775
0
    is_single_complete_type = false;
776
0
    ptvcursor_add_with_subtree(packet->cursor, hf != -1 ? hf : hf_dbus_type_struct,
777
0
        SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_struct);
778
0
    dbus_type_reader_t *child = wmem_new(packet->pinfo->pool, dbus_type_reader_t);
779
0
    *child = (dbus_type_reader_t){
780
0
      .packet = reader->packet,
781
0
      .signature = reader->signature,
782
0
      .level = reader->level + 1,
783
0
      .struct_level = reader->struct_level + 1,
784
0
      .parent = reader,
785
0
    };
786
0
    reader = child;
787
0
    break;
788
0
  }
789
0
  case SIG_CODE_VARIANT: {
790
0
    is_single_complete_type = false;
791
0
    proto_item *variant = ptvcursor_add_with_subtree(packet->cursor,
792
0
        hf != -1 ? hf : hf_dbus_type_variant,
793
0
        SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_variant);
794
0
    const char *variant_signature = add_dbus_string(packet, hf_dbus_type_variant_signature, 1);
795
0
    value->string = variant_signature;
796
0
    if (variant_signature && is_dbus_signature_valid(variant_signature, packet)) {
797
0
      if (variant_signature[0] != '\0') {
798
0
        dbus_type_reader_t *child = wmem_new(packet->pinfo->pool, dbus_type_reader_t);
799
0
        *child = (dbus_type_reader_t){
800
0
          .packet = reader->packet,
801
0
          .signature = variant_signature,
802
0
          .level = reader->level + 1,
803
0
          .is_in_variant = true,
804
0
          .is_basic_variant = is_basic_type(*variant_signature)
805
0
            && *(variant_signature + 1) == '\0',
806
0
          .container = variant,
807
0
          .parent = reader,
808
0
        };
809
0
        if (reader->is_in_dict_entry && child->is_basic_variant) {
810
0
          reader->is_basic_dict_entry = true;
811
0
        }
812
0
        reader = child;
813
0
      } else {
814
0
        ptvcursor_pop_subtree(packet->cursor);
815
0
      }
816
0
    } else {
817
0
      add_expert(packet, &ei_dbus_type_variant_signature_invalid);
818
0
      err = 1;
819
0
      ptvcursor_pop_subtree(packet->cursor);
820
0
    }
821
0
    break;
822
0
  }
823
0
  case SIG_CODE_DICT_ENTRY_OPEN: {
824
0
    is_single_complete_type = false;
825
0
    proto_item *dict_entry = ptvcursor_add_with_subtree(packet->cursor,
826
0
        hf != -1 ? hf : hf_dbus_type_dict_entry,
827
0
        SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett != -1 ? ett : ett_dbus_type_dict_entry);
828
0
    dbus_type_reader_t *child = wmem_new(packet->pinfo->pool, dbus_type_reader_t);
829
0
    *child = (dbus_type_reader_t){
830
0
      .packet = reader->packet,
831
0
      .signature = reader->signature,
832
0
      .level = reader->level + 1,
833
0
      .dict_entry_level = reader->dict_entry_level + 1,
834
0
      .is_in_dict_entry = true,
835
0
      .is_basic_dict_entry = is_basic_type(*(reader->signature + 1)),
836
0
      .container = dict_entry,
837
0
      .parent = reader,
838
0
    };
839
0
    reader = child;
840
0
    break;
841
0
  }
842
0
  case SIG_CODE_STRUCT_CLOSE:
843
0
  case SIG_CODE_DICT_ENTRY_CLOSE:
844
0
    ptvcursor_pop_subtree(packet->cursor);
845
0
    reader->parent->signature = reader->signature;
846
0
    reader = reader->parent;
847
0
    break;
848
0
  case SIG_CODE_UNIX_FD:
849
0
    packet->current_pi = ptvcursor_add_ret_uint(packet->cursor,
850
0
        hf != -1 ? hf : hf_dbus_type_unix_fd, 4, packet->enc, &value->uint);
851
0
    break;
852
0
  default:
853
    // all signatures are validated
854
0
    DISSECTOR_ASSERT_NOT_REACHED();
855
0
  }
856
857
0
  if (reader->level > DBUS_MAX_TOTAL_NESTING_LEVEL ||
858
0
      reader->array_level > DBUS_MAX_TYPE_NESTING_LEVEL ||
859
0
      reader->struct_level > DBUS_MAX_TYPE_NESTING_LEVEL ||
860
0
      reader->dict_entry_level > DBUS_MAX_TYPE_NESTING_LEVEL) {
861
0
    add_expert(packet, &ei_dbus_nested_too_deeply);
862
0
    err= 1;
863
0
  } 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"
866
0
    while (1) {
867
0
      if (reader->array_type_start) { // inside array
868
0
        int offset = ptvcursor_current_offset(packet->cursor);
869
870
0
        if (offset < reader->array_end_offset) {
871
          // parse next array element -> reset signature
872
0
          reader->signature = reader->array_type_start;
873
0
          break;
874
0
        } else if (offset == reader->array_end_offset) {
875
          // all array elements parsed
876
0
          ptvcursor_pop_subtree(packet->cursor);
877
0
          reader->parent->signature = reader->signature;
878
0
          reader = reader->parent;
879
0
        } else {
880
          // array elements don't fit into array
881
0
          expert_add_info(packet->pinfo, reader->container,
882
0
              &ei_dbus_type_array_content_out_of_bounds);
883
0
          err = 1;
884
0
          break;
885
0
        }
886
0
      } else if (reader->is_in_variant) {
887
0
        if (reader->is_basic_variant) {
888
0
          proto_item_append_text(reader->container, ": %s",
889
0
              proto_item_get_display_repr(packet->pinfo->pool, packet->current_pi));
890
0
        }
891
0
        ptvcursor_pop_subtree(packet->cursor);
892
0
        reader = reader->parent;
893
0
      } else {
894
0
        break;
895
0
      }
896
0
    }
897
0
    if (reader->is_in_dict_entry) {
898
      // add "key: value" to dict entry item to make it readable without expanding the tree
899
0
      if (*(reader->signature - 2) == SIG_CODE_DICT_ENTRY_OPEN) { // == key
900
        // key is always a basic type
901
0
        proto_item_append_text(reader->container, ", %s",
902
0
            proto_item_get_display_repr(packet->pinfo->pool, packet->current_pi));
903
0
      } else if (reader->is_basic_dict_entry) { // == value
904
0
        proto_item_append_text(reader->container, ": %s",
905
0
            proto_item_get_display_repr(packet->pinfo->pool, packet->current_pi));
906
0
      }
907
0
    }
908
0
  }
909
910
0
  if (err) {
911
0
    reader_cleanup(reader);
912
0
    return NULL;
913
0
  }
914
0
  return reader;
915
0
}
916
917
static bool
918
0
reader_is_finished(dbus_type_reader_t *reader) {
919
0
  return *reader->signature == '\0' && reader->parent == NULL;
920
0
}
921
922
static int
923
0
dissect_dbus_signature(dbus_packet_t *packet, const char *signature) {
924
0
  dbus_type_reader_t root_reader = {
925
0
    .packet = packet,
926
0
    .signature = signature,
927
0
  };
928
0
  dbus_type_reader_t *reader = &root_reader;
929
0
  dbus_val_t value;
930
0
  while (!reader_is_finished(reader)) {
931
0
    reader = reader_next(reader, -1, -1, &value);
932
0
    if (!reader) {
933
0
      return 1;
934
0
    }
935
0
  }
936
0
  return 0;
937
0
}
938
939
static int
940
0
dissect_dbus_body(dbus_packet_t *packet) {
941
0
  int err = 0;
942
0
  if (packet->signature[0]) {
943
0
    ptvcursor_add_with_subtree(packet->cursor, hf_dbus_body,
944
0
        SUBTREE_UNDEFINED_LENGTH, ENC_NA, ett_dbus_body);
945
0
    err = dissect_dbus_signature(packet, packet->signature);
946
0
    ptvcursor_pop_subtree(packet->cursor);
947
0
  }
948
0
  return err;
949
0
}
950
951
static void
952
0
update_unique_name_map(const char *name1, const char *name2) {
953
0
  const char *unique_name;
954
0
  const char *well_known_name;
955
956
0
  if (!dbus_resolve_names) {
957
0
    return;
958
0
  }
959
960
0
  if (name1[0] == ':' && name2[0] != ':') {
961
0
    unique_name = name1;
962
0
    well_known_name = name2;
963
0
  } else if (name2[0] == ':' && name1[0] != ':') {
964
0
    unique_name = name2;
965
0
    well_known_name = name1;
966
0
  } else {
967
    // both are well-known or both are unique names
968
0
    return;
969
0
  }
970
0
  if (!wmem_map_contains(unique_name_map, unique_name)) {
971
0
    wmem_map_insert(unique_name_map,
972
0
        wmem_strdup(wmem_file_scope(), unique_name),
973
0
        wmem_strdup(wmem_file_scope(), well_known_name));
974
0
  }
975
0
}
976
977
static void
978
0
add_conversation(dbus_packet_t *packet, proto_tree *header_field_tree) {
979
0
  bool is_request;
980
0
  char *request_dest;
981
0
  char *key;
982
983
0
  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.
986
0
    return;
987
0
  }
988
989
0
  switch (packet->message_type) {
990
0
  case DBUS_MESSAGE_TYPE_METHOD_CALL:
991
0
    if (packet->flags & DBUS_FLAGS_NO_REPLY_EXPECTED_MASK) {
992
      // there won't be a response, no need to track
993
0
      return;
994
0
    }
995
0
    is_request = true;
996
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 +
1005
    // reply serial.
1006
0
    if (!PINFO_FD_VISITED(packet->pinfo)) {
1007
0
      request_dest = wmem_strdup(wmem_file_scope(), packet->destination);
1008
0
      key = wmem_strdup_printf(wmem_file_scope(), "%s %u", packet->sender, packet->serial);
1009
0
      wmem_map_insert(request_info_map, key, request_dest);
1010
0
    }
1011
0
    break;
1012
0
  case DBUS_MESSAGE_TYPE_METHOD_RETURN:
1013
0
  case DBUS_MESSAGE_TYPE_ERROR:
1014
0
    is_request = false;
1015
1016
0
    key = wmem_strdup_printf(packet->pinfo->pool, "%s %u", packet->destination, packet->reply_serial);
1017
0
    request_dest = (char *)wmem_map_lookup(request_info_map, key);
1018
0
    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
0
      address sender_addr;
1022
0
      set_address(&sender_addr, AT_STRINGZ, (int)strlen(request_dest)+1, request_dest);
1023
0
      conversation_set_conv_addr_port_endpoints(packet->pinfo, &sender_addr, &packet->pinfo->dst,
1024
0
          conversation_pt_to_endpoint_type(packet->pinfo->ptype),
1025
0
          packet->pinfo->srcport, packet->pinfo->destport);
1026
1027
0
      if (!PINFO_FD_VISITED(packet->pinfo) && packet->message_type == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
1028
0
        update_unique_name_map(request_dest, packet->sender);
1029
0
      }
1030
0
    }
1031
0
    break;
1032
0
  case DBUS_MESSAGE_TYPE_SIGNAL:
1033
0
  default:
1034
    // signals don't have a response, no need to track
1035
0
    return;
1036
0
  }
1037
1038
0
  conversation_t *conversation = find_or_create_conversation(packet->pinfo);
1039
0
  dbus_conv_info_t *conv_info = (dbus_conv_info_t *)conversation_get_proto_data(conversation, proto_dbus);
1040
1041
0
  if (!conv_info) {
1042
0
    conv_info = wmem_new(wmem_file_scope(), dbus_conv_info_t);
1043
0
    conv_info->packets = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1044
0
    conversation_add_proto_data(conversation, proto_dbus, conv_info);
1045
0
  }
1046
1047
0
  dbus_transaction_t *trans;
1048
0
  if (!PINFO_FD_VISITED(packet->pinfo)) {
1049
0
    if (is_request) {
1050
0
      trans = wmem_new(wmem_file_scope(), dbus_transaction_t);
1051
0
      *trans = (dbus_transaction_t){
1052
0
        .req_frame = packet->pinfo->num,
1053
0
        .req_time = packet->pinfo->fd->abs_ts,
1054
0
        .path = wmem_strdup(wmem_file_scope(), packet->path),
1055
0
        .interface = wmem_strdup(wmem_file_scope(), packet->interface),
1056
0
        .member = wmem_strdup(wmem_file_scope(), packet->member),
1057
0
      };
1058
0
      wmem_map_insert(conv_info->packets, GUINT_TO_POINTER(packet->serial), (void *)trans);
1059
0
    } else {
1060
0
      trans = (dbus_transaction_t *)wmem_map_lookup(conv_info->packets, GUINT_TO_POINTER(packet->reply_serial));
1061
0
      if (trans) {
1062
0
        trans->rep_frame = packet->pinfo->num;
1063
0
      }
1064
0
    }
1065
0
  } else {
1066
0
    uint32_t request_serial = is_request ? packet->serial : packet->reply_serial;
1067
0
    trans = (dbus_transaction_t *)wmem_map_lookup(conv_info->packets, GUINT_TO_POINTER(request_serial));
1068
0
  }
1069
1070
0
  if (!trans) {
1071
0
    return;
1072
0
  }
1073
1074
0
  if (is_request) {
1075
0
    proto_item *it = proto_tree_add_uint(header_field_tree, hf_dbus_response_in, ptvcursor_tvbuff(packet->cursor), 0, 0, trans->rep_frame);
1076
0
    proto_item_set_generated(it);
1077
0
  } else {
1078
0
    nstime_t ns;
1079
0
    proto_item *it;
1080
0
    tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
1081
1082
0
    it = proto_tree_add_string(header_field_tree, hf_dbus_path, tvb, 0, 0, trans->path);
1083
0
    proto_item_set_generated(it);
1084
0
    packet->path = trans->path;
1085
1086
0
    it = proto_tree_add_string(header_field_tree, hf_dbus_interface, tvb, 0, 0, trans->interface);
1087
0
    proto_item_set_generated(it);
1088
0
    packet->interface = trans->interface;
1089
1090
0
    it = proto_tree_add_string(header_field_tree, hf_dbus_member, tvb, 0, 0, trans->member);
1091
0
    proto_item_set_generated(it);
1092
0
    packet->member = trans->member;
1093
1094
0
    it = proto_tree_add_uint(header_field_tree, hf_dbus_response_to, tvb, 0, 0, trans->req_frame);
1095
0
    proto_item_set_generated(it);
1096
1097
0
    nstime_delta(&ns, &packet->pinfo->fd->abs_ts, &trans->req_time);
1098
0
    it = proto_tree_add_time(header_field_tree, hf_dbus_response_time, tvb, 0, 0, &ns);
1099
0
    proto_item_set_generated(it);
1100
0
  }
1101
0
}
1102
1103
static void
1104
0
resolve_unique_name(dbus_packet_t *packet, proto_tree *header_field_tree) {
1105
0
  proto_item *it;
1106
0
  tvbuff_t *tvb = ptvcursor_tvbuff(packet->cursor);
1107
1108
0
  if (packet->sender) {
1109
0
    const char *sender_well_known = (const char *)wmem_map_lookup(unique_name_map, packet->sender);
1110
0
    if (sender_well_known) {
1111
0
      set_address(&packet->pinfo->src, AT_STRINGZ, (int)strlen(sender_well_known)+1, sender_well_known);
1112
0
      it = proto_tree_add_string(header_field_tree, hf_dbus_sender, tvb, 0, 0, sender_well_known);
1113
0
      proto_item_set_generated(it);
1114
0
    }
1115
0
  }
1116
1117
0
  if (packet->destination) {
1118
0
    const char *destination_well_known = (const char *)wmem_map_lookup(unique_name_map, packet->destination);
1119
0
    if (destination_well_known) {
1120
0
      set_address(&packet->pinfo->dst, AT_STRINGZ, (int)strlen(destination_well_known)+1, destination_well_known);
1121
0
      it = proto_tree_add_string(header_field_tree, hf_dbus_destination, tvb, 0, 0, destination_well_known);
1122
0
      proto_item_set_generated(it);
1123
0
    }
1124
0
  }
1125
0
}
1126
1127
static int
1128
0
dissect_dbus_header_fields(dbus_packet_t *packet) {
1129
0
  dbus_type_reader_t root_reader = {
1130
0
    .packet = packet,
1131
0
    .signature = "a{yv}",
1132
0
  };
1133
0
  dbus_type_reader_t *reader = &root_reader;
1134
0
  dbus_val_t value;
1135
0
#define NEXT_OR_RETURN(hf, ett) if (!(reader = reader_next(reader, hf, ett, &value))) return 1;
1136
1137
  // Header Field Array
1138
0
  NEXT_OR_RETURN(-1, ett_dbus_header_field_array);
1139
0
  proto_item *header_field_array_pi = reader->container;
1140
0
  proto_item_set_text(header_field_array_pi, "Header Field Array");
1141
0
  while (reader->level > 0) {
1142
    // Header Field (Dict)
1143
0
    NEXT_OR_RETURN(-1, ett_dbus_header_field);
1144
    // Field Code
1145
0
    NEXT_OR_RETURN(hf_dbus_field_code, -1);
1146
0
    uint32_t field_code = value.uint;
1147
0
    const char *field_code_str = val_to_str_const(field_code, field_code_vals, "Unknown field code");
1148
0
    proto_item_append_text(reader->container, ", %s", field_code_str);
1149
0
    if (field_code == DBUS_HEADER_FIELD_INVALID) {
1150
0
      add_expert(packet, &ei_dbus_field_code_invalid);
1151
0
      reader_cleanup(reader);
1152
0
      return 1;
1153
0
    }
1154
1155
    // Header Field Value (Variant)
1156
0
    NEXT_OR_RETURN(-1, -1);
1157
0
    const char *header_field_signature = value.string;
1158
1159
0
    const char *expected_signature;
1160
0
    switch (field_code) {
1161
0
    case DBUS_HEADER_FIELD_PATH:
1162
0
      expected_signature = "o";
1163
0
      break;
1164
0
    case DBUS_HEADER_FIELD_INTERFACE:
1165
0
    case DBUS_HEADER_FIELD_MEMBER:
1166
0
    case DBUS_HEADER_FIELD_ERROR_NAME:
1167
0
    case DBUS_HEADER_FIELD_DESTINATION:
1168
0
    case DBUS_HEADER_FIELD_SENDER:
1169
0
      expected_signature = "s";
1170
0
      break;
1171
0
    case DBUS_HEADER_FIELD_REPLY_SERIAL:
1172
0
      expected_signature = "u";
1173
0
      break;
1174
0
    case DBUS_HEADER_FIELD_UNIX_FDS:
1175
0
      expected_signature = "u";
1176
0
      break;
1177
0
    case DBUS_HEADER_FIELD_SIGNATURE:
1178
0
      expected_signature = "g";
1179
0
      break;
1180
0
    default:
1181
0
      expected_signature = NULL;
1182
0
    }
1183
1184
0
    if (expected_signature && strcmp(header_field_signature, expected_signature) != 0) {
1185
0
      add_expert(packet, &ei_dbus_field_signature_wrong);
1186
0
      reader_cleanup(reader);
1187
0
      return 1;
1188
0
    }
1189
1190
    // Variant Value
1191
0
    switch (field_code) {
1192
0
    case DBUS_HEADER_FIELD_PATH:
1193
0
      NEXT_OR_RETURN(hf_dbus_path, -1);
1194
0
      packet->path = value.string;
1195
0
      break;
1196
0
    case DBUS_HEADER_FIELD_INTERFACE:
1197
0
      NEXT_OR_RETURN(hf_dbus_interface, -1);
1198
0
      packet->interface = value.string;
1199
0
      if (!is_dbus_interface_valid(packet->interface)) {
1200
0
        add_expert(packet, &ei_dbus_interface_invalid);
1201
0
        reader_cleanup(reader);
1202
0
        return 1;
1203
0
      }
1204
0
      break;
1205
0
    case DBUS_HEADER_FIELD_MEMBER:
1206
0
      NEXT_OR_RETURN(hf_dbus_member, -1);
1207
0
      packet->member = value.string;
1208
0
      if (!is_dbus_member_name_valid(packet->member)) {
1209
0
        add_expert(packet, &ei_dbus_member_invalid);
1210
0
        reader_cleanup(reader);
1211
0
        return 1;
1212
0
      }
1213
0
      break;
1214
0
    case DBUS_HEADER_FIELD_ERROR_NAME:
1215
0
      NEXT_OR_RETURN(hf_dbus_error_name, -1);
1216
0
      packet->error_name = value.string;
1217
0
      if (!is_dbus_interface_valid(packet->error_name)) {
1218
0
        add_expert(packet, &ei_dbus_error_name_invalid);
1219
0
        reader_cleanup(reader);
1220
0
        return 1;
1221
0
      }
1222
0
      break;
1223
0
    case DBUS_HEADER_FIELD_DESTINATION:
1224
0
      NEXT_OR_RETURN(hf_dbus_destination, -1);
1225
0
      packet->destination = value.string;
1226
0
      if (!is_dbus_bus_name_valid(packet->destination)) {
1227
0
        add_expert(packet, &ei_dbus_bus_name_invalid);
1228
0
        reader_cleanup(reader);
1229
0
        return 1;
1230
0
      }
1231
0
      set_address(&packet->pinfo->dst, AT_STRINGZ, (int)strlen(packet->destination)+1,
1232
0
        wmem_strdup(packet->pinfo->pool, packet->destination));
1233
0
      break;
1234
0
    case DBUS_HEADER_FIELD_SENDER:
1235
0
      NEXT_OR_RETURN(hf_dbus_sender, -1);
1236
0
      packet->sender = value.string;
1237
0
      if (!is_dbus_bus_name_valid(packet->sender)) {
1238
0
        add_expert(packet, &ei_dbus_bus_name_invalid);
1239
0
        reader_cleanup(reader);
1240
0
        return 1;
1241
0
      }
1242
0
      set_address(&packet->pinfo->src, AT_STRINGZ, (int)strlen(packet->sender)+1,
1243
0
        wmem_strdup(packet->pinfo->pool, packet->sender));
1244
0
      break;
1245
0
    case DBUS_HEADER_FIELD_SIGNATURE:
1246
0
      NEXT_OR_RETURN(hf_dbus_signature, -1);
1247
0
      packet->signature = value.string;
1248
0
      break;
1249
0
    case DBUS_HEADER_FIELD_REPLY_SERIAL:
1250
0
      NEXT_OR_RETURN(hf_dbus_reply_serial, -1);
1251
0
      packet->reply_serial = value.uint;
1252
0
      if (packet->reply_serial == 0) {
1253
0
        add_expert(packet, &ei_dbus_serial_invalid);
1254
0
        reader_cleanup(reader);
1255
0
        return 1;
1256
0
      }
1257
0
      break;
1258
0
    case DBUS_HEADER_FIELD_UNIX_FDS:
1259
0
      NEXT_OR_RETURN(hf_dbus_unix_fds, -1);
1260
0
      packet->unix_fds = value.uint;
1261
0
      break;
1262
0
    default:
1263
      // Unknown Field code must be skipped without error
1264
0
      do {
1265
0
        NEXT_OR_RETURN(-1, -1);
1266
        // Skip while inside Header Field Array -> Header Field Dict -> Variant
1267
0
      } while (reader->level >= 3);
1268
0
    }
1269
    // end of dict
1270
0
    NEXT_OR_RETURN(-1, -1);
1271
0
  }
1272
1273
0
  bool is_field_missing = false;
1274
0
  switch (packet->message_type) {
1275
0
  case DBUS_MESSAGE_TYPE_METHOD_CALL:
1276
0
    is_field_missing = !packet->path || !packet->member;
1277
0
    break;
1278
0
  case DBUS_MESSAGE_TYPE_METHOD_RETURN:
1279
0
    is_field_missing = !packet->reply_serial;
1280
0
    break;
1281
0
  case DBUS_MESSAGE_TYPE_ERROR:
1282
0
    is_field_missing = !packet->error_name || !packet->reply_serial;
1283
0
    break;
1284
0
  case DBUS_MESSAGE_TYPE_SIGNAL:
1285
0
    is_field_missing = !packet->path || !packet->interface || !packet->member;
1286
0
    break;
1287
0
  default:
1288
0
    DISSECTOR_ASSERT_NOT_REACHED();
1289
0
    break;
1290
0
  }
1291
0
  if (is_field_missing) {
1292
0
    expert_add_info(packet->pinfo, header_field_array_pi, &ei_dbus_required_header_field_missing);
1293
0
    return 1;
1294
0
  }
1295
1296
0
  add_conversation(packet, proto_item_get_subtree(header_field_array_pi));
1297
0
  if (dbus_resolve_names) {
1298
0
    resolve_unique_name(packet, proto_item_get_subtree(header_field_array_pi));
1299
0
  }
1300
1301
0
  switch(packet->message_type) {
1302
0
  case DBUS_MESSAGE_TYPE_METHOD_CALL:
1303
0
    col_add_fstr(packet->pinfo->cinfo, COL_INFO, "%s(%s) @ %s", packet->member, packet->signature, packet->path);
1304
0
    break;
1305
0
  case DBUS_MESSAGE_TYPE_SIGNAL:
1306
0
    col_add_fstr(packet->pinfo->cinfo, COL_INFO, "* %s(%s) @ %s", packet->member, packet->signature, packet->path);
1307
0
    break;
1308
0
  case DBUS_MESSAGE_TYPE_ERROR:
1309
0
    if (packet->member) {
1310
0
      col_add_fstr(packet->pinfo->cinfo, COL_INFO, "! %s: %s", packet->member, packet->error_name);
1311
0
    } else {
1312
0
      col_add_fstr(packet->pinfo->cinfo, COL_INFO, "! %s", packet->error_name);
1313
0
    }
1314
0
    break;
1315
0
  case DBUS_MESSAGE_TYPE_METHOD_RETURN:
1316
0
    if (packet->member) {
1317
0
      if (*packet->signature != '\0') {
1318
0
        col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> %s: '%s'", packet->member, packet->signature);
1319
0
      } else {
1320
0
        col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> %s: OK", packet->member);
1321
1322
0
      }
1323
0
    } else {
1324
0
      col_add_fstr(packet->pinfo->cinfo, COL_INFO, "-> '%s'", packet->signature);
1325
0
    }
1326
0
    break;
1327
0
  default:
1328
0
    DISSECTOR_ASSERT_NOT_REACHED();
1329
0
    break;
1330
0
  }
1331
1332
  // Header length must be a multiple of 8 bytes
1333
0
  return add_padding(packet, SIG_CODE_STRUCT_OPEN);
1334
0
}
1335
1336
static int
1337
0
dissect_dbus_header(dbus_packet_t *packet) {
1338
0
  uint32_t val;
1339
1340
  // Endianness
1341
0
  packet->current_pi = ptvcursor_add_ret_uint(packet->cursor, hf_dbus_endianness, 1, ENC_NA, &val);
1342
0
  switch (val) {
1343
0
    case 'l':
1344
0
      packet->enc = ENC_LITTLE_ENDIAN;
1345
0
      break;
1346
0
    case 'B':
1347
0
      packet->enc = ENC_BIG_ENDIAN;
1348
0
      break;
1349
0
    default:
1350
0
      add_expert(packet, &ei_dbus_endianness_invalid);
1351
0
      return 1;
1352
0
  }
1353
1354
  // Message Type
1355
0
  packet->message_type = add_uint(packet, hf_dbus_message_type);
1356
0
  const char *info = try_val_to_str(packet->message_type, message_type_vals);
1357
0
  if (packet->message_type == DBUS_MESSAGE_TYPE_INVALID) {
1358
0
    col_set_str(packet->pinfo->cinfo, COL_INFO, info);
1359
0
    add_expert(packet, &ei_dbus_message_type_invalid);
1360
0
    return 1;
1361
0
  } else if (!info) {
1362
0
    col_set_str(packet->pinfo->cinfo, COL_INFO, "Unknown message type");
1363
0
    add_expert(packet, &ei_dbus_message_type_unknown);
1364
0
    return 1;
1365
0
  }
1366
0
  col_set_str(packet->pinfo->cinfo, COL_INFO, info);
1367
1368
  // Flags
1369
0
  ptvcursor_add_with_subtree(packet->cursor, hf_dbus_flags, 1, packet->enc, ett_dbus_flags);
1370
0
  ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_no_reply_expected, 1, packet->enc);
1371
0
  ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_no_auto_start, 1, packet->enc);
1372
0
  ptvcursor_add_no_advance(packet->cursor, hf_dbus_flags_allow_interactive_authorization, 1, packet->enc);
1373
0
  packet->flags = tvb_get_uint8(ptvcursor_tvbuff(packet->cursor), ptvcursor_current_offset(packet->cursor));
1374
0
  ptvcursor_advance(packet->cursor, 1);
1375
0
  ptvcursor_pop_subtree(packet->cursor);
1376
1377
  // Version
1378
0
  if (add_uint(packet, hf_dbus_version) != 1) {
1379
0
    add_expert(packet, &ei_dbus_version_invalid);
1380
0
    return 1;
1381
0
  }
1382
1383
  // Body Length
1384
0
  packet->body_len = add_uint(packet, hf_dbus_body_length);
1385
1386
  // Serial
1387
0
  packet->serial = add_uint(packet, hf_dbus_serial);
1388
0
  if (packet->serial == 0) {
1389
0
    add_expert(packet, &ei_dbus_serial_invalid);
1390
0
    return 1;
1391
0
  }
1392
1393
0
  return 0;
1394
0
}
1395
1396
static int
1397
0
dissect_dbus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
1398
0
  dbus_packet_t packet = { .pinfo = pinfo, .signature = "" };
1399
1400
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "D-Bus");
1401
0
  col_set_str(pinfo->cinfo, COL_INFO, "D-Bus");
1402
1403
0
  proto_item *pi = proto_tree_add_protocol_format(tree, proto_dbus, tvb, 0, -1, "D-Bus");
1404
0
  proto_tree *dbus_tree = proto_item_add_subtree(pi, ett_dbus);
1405
1406
0
  unsigned offset = 0;
1407
0
  packet.cursor = ptvcursor_new(pinfo->pool, dbus_tree, tvb, offset);
1408
1409
0
  (void)(dissect_dbus_header(&packet) ||
1410
0
    dissect_dbus_header_fields(&packet) ||
1411
0
    dissect_dbus_body(&packet));
1412
1413
0
  offset = ptvcursor_current_offset(packet.cursor);
1414
0
  proto_item_set_end(pi, tvb, offset);
1415
0
  ptvcursor_free(packet.cursor);
1416
0
  return offset;
1417
0
}
1418
1419
0
#define DBUS_HEADER_LEN 16
1420
1421
static unsigned
1422
get_dbus_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
1423
0
                     int offset, void *data _U_) {
1424
1425
0
  unsigned encoding;
1426
0
  uint32_t len_body, len_hdr;
1427
1428
0
  switch (tvb_get_uint8(tvb, offset)) {
1429
0
    case 'l':
1430
0
      encoding = ENC_LITTLE_ENDIAN;
1431
0
      break;
1432
0
    case 'B':
1433
0
    default:
1434
0
      encoding = ENC_BIG_ENDIAN;
1435
0
      break;
1436
0
  }
1437
1438
0
  len_hdr = DBUS_HEADER_LEN + tvb_get_uint32(tvb, offset + 12, encoding);
1439
0
  len_hdr = WS_ROUNDUP_8(len_hdr);
1440
0
  len_body = tvb_get_uint32(tvb, offset + 4, encoding);
1441
1442
0
  return len_hdr + len_body;
1443
0
}
1444
1445
static int
1446
0
dissect_dbus_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
1447
0
  return dissect_dbus(tvb, pinfo, tree, data);
1448
0
}
1449
1450
static int
1451
0
dissect_dbus_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
1452
0
  tcp_dissect_pdus(tvb, pinfo, tree, dbus_desegment, DBUS_HEADER_LEN,
1453
0
      get_dbus_message_len, dissect_dbus_pdu, data);
1454
0
  return tvb_reported_length(tvb);
1455
0
}
1456
1457
void
1458
15
proto_register_dbus(void) {
1459
15
  static hf_register_info hf[] = {
1460
15
    { &hf_dbus_endianness, { "Endianness", "dbus.endianness",
1461
15
      FT_UINT8, BASE_NONE, VALS(endianness_vals), 0x00, NULL, HFILL }},
1462
15
    { &hf_dbus_message_type, { "Message Type", "dbus.message_type",
1463
15
      FT_UINT8, BASE_NONE, VALS(message_type_vals), 0x00, NULL, HFILL }},
1464
15
    { &hf_dbus_flags, { "Message Flags", "dbus.flags",
1465
15
      FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
1466
15
    { &hf_dbus_flags_no_reply_expected, { "No Reply Expected", "dbus.flags.no_reply_expected",
1467
15
      FT_BOOLEAN, 8, TFS(&not_expected_vals),
1468
15
      DBUS_FLAGS_NO_REPLY_EXPECTED_MASK, NULL, HFILL }},
1469
15
    { &hf_dbus_flags_no_auto_start, { "No Auto Start", "dbus.flags.no_auto_start",
1470
15
      FT_BOOLEAN, 8, TFS(&no_start_vals),
1471
15
      DBUS_FLAGS_NO_AUTO_START_MASK, NULL, HFILL }},
1472
15
    { &hf_dbus_flags_allow_interactive_authorization, { "Allow Interactive Authorization", "dbus.flags.allow_interactive_authorization",
1473
15
      FT_BOOLEAN, 8, TFS(&allow_vals),
1474
15
      DBUS_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION_MASK, NULL, HFILL }},
1475
15
    { &hf_dbus_version, { "Protocol Version", "dbus.version",
1476
15
      FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1477
15
    { &hf_dbus_body_length, { "Message Body Length", "dbus.body_length",
1478
15
      FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1479
15
    { &hf_dbus_serial, { "Message Serial", "dbus.serial",
1480
15
      FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1481
15
    { &hf_dbus_field_code, { "Field Code", "dbus.field_code",
1482
15
      FT_UINT8, BASE_DEC, VALS(field_code_vals), 0x00, NULL, HFILL }},
1483
15
    { &hf_dbus_padding, { "Padding", "dbus.padding",
1484
15
      FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1485
15
    { &hf_dbus_path, { "Path", "dbus.path",
1486
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1487
15
    { &hf_dbus_interface, { "Interface", "dbus.interface",
1488
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1489
15
    { &hf_dbus_member, { "Member", "dbus.member",
1490
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1491
15
    { &hf_dbus_error_name, { "Error name", "dbus.error_name",
1492
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1493
15
    { &hf_dbus_reply_serial, { "Reply serial", "dbus.reply_serial",
1494
15
      FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1495
15
    { &hf_dbus_destination, { "Destination", "dbus.destination",
1496
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1497
15
    { &hf_dbus_sender, { "Sender", "dbus.sender",
1498
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1499
15
    { &hf_dbus_signature, { "Signature", "dbus.signature",
1500
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1501
15
    { &hf_dbus_unix_fds, { "Unix FDs", "dbus.unix_fds",
1502
15
      FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1503
15
    { &hf_dbus_body, { "Body", "dbus.body",
1504
15
      FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1505
15
    { &hf_dbus_type_byte, { "Byte", "dbus.type.byte",
1506
15
      FT_UINT8, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
1507
15
    { &hf_dbus_type_boolean, { "Boolean", "dbus.type.boolean",
1508
15
      FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1509
15
    { &hf_dbus_type_int16, { "Int16", "dbus.type.int16",
1510
15
      FT_INT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1511
15
    { &hf_dbus_type_uint16, { "Uint16", "dbus.type.uint16",
1512
15
      FT_UINT16, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
1513
15
    { &hf_dbus_type_int32, { "Int32", "dbus.type.int32",
1514
15
      FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1515
15
    { &hf_dbus_type_uint32, { "Uint32", "dbus.type.uint32",
1516
15
      FT_UINT32, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
1517
15
    { &hf_dbus_type_int64, { "Int64", "dbus.type.int64",
1518
15
      FT_INT64, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1519
15
    { &hf_dbus_type_uint64, { "Uint64", "dbus.type.uint64",
1520
15
      FT_UINT64, BASE_DEC_HEX, NULL, 0x00, NULL, HFILL }},
1521
15
    { &hf_dbus_type_double, { "Double", "dbus.type.double",
1522
15
      FT_DOUBLE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1523
15
    { &hf_dbus_type_string, { "String", "dbus.type.string",
1524
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1525
15
    { &hf_dbus_type_object_path, { "Object Path", "dbus.type.object_path",
1526
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1527
15
    { &hf_dbus_type_signature, { "Signature", "dbus.type.signature",
1528
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1529
15
    { &hf_dbus_type_array, { "Array", "dbus.type.array",
1530
15
      FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1531
15
    { &hf_dbus_type_array_length, { "Array Length", "dbus.type.array.length",
1532
15
      FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1533
15
    { &hf_dbus_type_struct, { "Struct", "dbus.type.struct",
1534
15
      FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1535
15
    { &hf_dbus_type_variant, { "Variant", "dbus.type.variant",
1536
15
      FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1537
15
    { &hf_dbus_type_variant_signature, { "Variant Signature", "dbus.type.variant.signature",
1538
15
      FT_UINT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }},
1539
15
    { &hf_dbus_type_dict_entry, { "Dict Entry", "dbus.type.dict_entry",
1540
15
      FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1541
15
    { &hf_dbus_type_dict_entry_key, { "Key", "dbus.type.dict_entry.key",
1542
15
      FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x00, NULL, HFILL }},
1543
15
    { &hf_dbus_type_unix_fd, { "Unix FD", "dbus.type.unix_fd",
1544
15
      FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
1545
15
    { &hf_dbus_response_in, { "Response In", "dbus.response_in",
1546
15
      FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
1547
15
      "The response to this D-Bus call is in this frame", HFILL }},
1548
15
    { &hf_dbus_response_to, { "Response To", "dbus.response_to",
1549
15
      FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
1550
15
      "This is a response to the D-Bus call in this frame", HFILL }},
1551
15
    { &hf_dbus_response_time, { "Response Time", "dbus.response_time",
1552
15
      FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
1553
15
      "The time between the Call and the Reply", HFILL }},
1554
15
  };
1555
1556
15
  static int *ett[] = {
1557
15
    &ett_dbus,
1558
15
    &ett_dbus_flags,
1559
15
    &ett_dbus_header_field_array,
1560
15
    &ett_dbus_header_field,
1561
15
    &ett_dbus_body,
1562
15
    &ett_dbus_type_array,
1563
15
    &ett_dbus_type_struct,
1564
15
    &ett_dbus_type_variant,
1565
15
    &ett_dbus_type_dict_entry,
1566
15
  };
1567
1568
15
  static ei_register_info ei[] = {
1569
15
    { &ei_dbus_endianness_invalid, { "dbus.endianness.invalid",
1570
15
      PI_PROTOCOL, PI_ERROR, "Invalid endianness flag", EXPFILL }},
1571
15
    { &ei_dbus_message_type_invalid, { "dbus.message_type.invalid",
1572
15
      PI_PROTOCOL, PI_ERROR, "Invalid message type", EXPFILL }},
1573
15
    { &ei_dbus_message_type_unknown, { "dbus.message_type.unknown",
1574
15
      PI_PROTOCOL, PI_WARN, "Unknown message type", EXPFILL }},
1575
15
    { &ei_dbus_version_invalid, { "dbus.version.invalid",
1576
15
      PI_PROTOCOL, PI_ERROR, "Invalid version", EXPFILL }},
1577
15
    { &ei_dbus_serial_invalid, { "dbus.serial.invalid",
1578
15
      PI_PROTOCOL, PI_ERROR, "Invalid serial", EXPFILL }},
1579
15
    { &ei_dbus_field_code_invalid, { "dbus.field_code.invalid",
1580
15
      PI_PROTOCOL, PI_ERROR, "Invalid field code", EXPFILL }},
1581
15
    { &ei_dbus_required_header_field_missing, { "dbus.required_header_field_missing",
1582
15
      PI_PROTOCOL, PI_ERROR, "Required header field is missing", EXPFILL }},
1583
15
    { &ei_dbus_padding_invalid, { "dbus.padding.invalid",
1584
15
      PI_PROTOCOL, PI_ERROR, "Padding bytes must be zero", EXPFILL }},
1585
15
    { &ei_dbus_field_signature_wrong, { "dbus.field_signature_wrong",
1586
15
      PI_PROTOCOL, PI_ERROR, "Wrong header field variant signature", EXPFILL }},
1587
15
    { &ei_dbus_interface_invalid, { "dbus.interface.invalid",
1588
15
      PI_PROTOCOL, PI_ERROR, "Invalid interface name", EXPFILL }},
1589
15
    { &ei_dbus_member_invalid, { "dbus.member.invalid",
1590
15
      PI_PROTOCOL, PI_ERROR, "Invalid member name", EXPFILL }},
1591
15
    { &ei_dbus_error_name_invalid, { "dbus.error_name.invalid",
1592
15
      PI_PROTOCOL, PI_ERROR, "Invalid error name", EXPFILL }},
1593
15
    { &ei_dbus_bus_name_invalid, { "dbus.bus_name.invalid",
1594
15
      PI_PROTOCOL, PI_ERROR, "Invalid bus name", EXPFILL }},
1595
15
    { &ei_dbus_type_boolean_invalid, { "dbus.type.boolean.invalid",
1596
15
      PI_PROTOCOL, PI_ERROR, "Invalid boolean value", EXPFILL }},
1597
15
    { &ei_dbus_string_invalid, { "dbus.type.string.invalid",
1598
15
      PI_PROTOCOL, PI_ERROR, "Invalid string value", EXPFILL }},
1599
15
    { &ei_dbus_type_signature_invalid, { "dbus.type.signature.invalid",
1600
15
      PI_PROTOCOL, PI_ERROR, "Invalid signature", EXPFILL }},
1601
15
    { &ei_dbus_type_array_too_long, { "dbus.type.array.too_long",
1602
15
      PI_PROTOCOL, PI_ERROR, "Array too long", EXPFILL }},
1603
15
    { &ei_dbus_type_array_content_out_of_bounds, { "dbus.type.array.content_out_of_bounds",
1604
15
      PI_PROTOCOL, PI_ERROR, "Array content is out of bounds", EXPFILL }},
1605
15
    { &ei_dbus_type_object_path_invalid, { "dbus.type.object_path.invalid",
1606
15
      PI_PROTOCOL, PI_ERROR, "Invalid object path", EXPFILL }},
1607
15
    { &ei_dbus_type_variant_signature_invalid, { "dbus.type.variant.signature.invalid",
1608
15
      PI_PROTOCOL, PI_ERROR, "Invalid variant signature", EXPFILL }},
1609
15
    { &ei_dbus_nested_too_deeply, { "dbus.nested_too_deeply",
1610
15
      PI_PROTOCOL, PI_ERROR, "Containers nested too deeply", EXPFILL }},
1611
15
  };
1612
1613
15
  expert_module_t *expert_dbus;
1614
15
  module_t *dbus_module;
1615
1616
15
  proto_dbus = proto_register_protocol("D-Bus", "D-Bus", "dbus");
1617
15
  proto_register_field_array(proto_dbus, hf, array_length(hf));
1618
15
  proto_register_subtree_array(ett, array_length(ett));
1619
15
  expert_dbus = expert_register_protocol(proto_dbus);
1620
15
  expert_register_field_array(expert_dbus, ei, array_length(ei));
1621
1622
15
  dbus_handle = register_dissector("dbus", dissect_dbus, proto_dbus);
1623
15
  dbus_handle_tcp = register_dissector("dbus.tcp", dissect_dbus_tcp, proto_dbus);
1624
1625
15
  dbus_module = prefs_register_protocol(proto_dbus, NULL);
1626
15
  prefs_register_bool_preference(dbus_module, "resolve_names",
1627
15
      "Resolve unique names into well-known names",
1628
15
      "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);
1629
1630
15
  request_info_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash, g_str_equal);
1631
15
  unique_name_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash, g_str_equal);
1632
15
}
1633
1634
void
1635
15
proto_reg_handoff_dbus(void) {
1636
15
  dissector_add_uint("wtap_encap", WTAP_ENCAP_DBUS, dbus_handle);
1637
15
  dissector_add_for_decode_as_with_preference("tcp.port", dbus_handle_tcp);
1638
15
}
1639
1640
/*
1641
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1642
 *
1643
 * Local variables:
1644
 * c-basic-offset: 8
1645
 * tab-width: 8
1646
 * indent-tabs-mode: t
1647
 * End:
1648
 *
1649
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1650
 * :indentSize=8:tabSize=8:noTabs=false:
1651
 */