Typo's. That is all.
[metze/wireshark/wip.git] / epan / dissectors / packet-dbus.c
1 /* packet-dbus.c
2  * Routines for D-Bus dissection
3  * Copyright 2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
4  *
5  * $Id$
6  *
7  * Protocol specification available at http://dbus.freedesktop.org/doc/dbus-specification.html
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 #include "config.h"
29
30 #include <epan/packet.h>
31 #include <epan/strutil.h>
32 #include <epan/expert.h>
33 #include <epan/dissectors/packet-tcp.h>
34
35 void proto_register_dbus(void);
36 void proto_reg_handoff_dbus(void);
37
38 static gboolean dbus_desegment = TRUE;
39
40 static int hf_dbus_hdr = -1;
41 static int hf_dbus_hdr_endianness = -1;
42 static int hf_dbus_hdr_type = -1;
43 static int hf_dbus_hdr_flags = -1;
44 static int hf_dbus_hdr_version = -1;
45 static int hf_dbus_hdr_body_length = -1;
46 static int hf_dbus_hdr_serial = -1;
47 static int hf_dbus_hdr_fields_length = -1;
48 static int hf_dbus_hdr_field = -1;
49 static int hf_dbus_hdr_field_code = -1;
50
51 static int hf_dbus_value_bool = -1;
52 static int hf_dbus_value_int = -1;
53 static int hf_dbus_value_uint = -1;
54 static int hf_dbus_value_str = -1;
55 static int hf_dbus_value_double = -1;
56
57 static int hf_dbus_body = -1;
58 static int hf_dbus_type_signature = -1;
59
60 static int ett_dbus = -1;
61 static int ett_dbus_hdr = -1;
62 static int ett_dbus_body = -1;
63 static int ett_dbus_field = -1;
64
65 static int proto_dbus = -1;
66
67 #define DBUS_MESSAGE_TYPE_INVALID 0
68 #define DBUS_MESSAGE_TYPE_METHOD_CALL 1
69 #define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
70 #define DBUS_MESSAGE_TYPE_ERROR 3
71 #define DBUS_MESSAGE_TYPE_SIGNAL 4
72
73 static const value_string message_type_vals[] = {
74         { DBUS_MESSAGE_TYPE_INVALID, "Invalid" },
75         { DBUS_MESSAGE_TYPE_METHOD_CALL, "Method call" },
76         { DBUS_MESSAGE_TYPE_METHOD_RETURN, "Method reply" },
77         { DBUS_MESSAGE_TYPE_ERROR, "Error reply" },
78         { DBUS_MESSAGE_TYPE_SIGNAL, "Signal emission" },
79         { 0, NULL }
80 };
81
82 #define DBUS_HEADER_FIELD_INVALID        0
83 #define DBUS_HEADER_FIELD_PATH           1
84 #define DBUS_HEADER_FIELD_INTERFACE      2
85 #define DBUS_HEADER_FIELD_MEMBER         3
86 #define DBUS_HEADER_FIELD_ERROR_NAME     4
87 #define DBUS_HEADER_FIELD_REPLY_SERIAL   5
88 #define DBUS_HEADER_FIELD_DESTINATION    6
89 #define DBUS_HEADER_FIELD_SENDER         7
90 #define DBUS_HEADER_FIELD_SIGNATURE      8
91 #define DBUS_HEADER_FIELD_UNIX_FDS       9
92
93 static const value_string field_code_vals[] = {
94         { DBUS_HEADER_FIELD_INVALID, "INVALID" },
95         { DBUS_HEADER_FIELD_PATH, "PATH" },
96         { DBUS_HEADER_FIELD_INTERFACE, "INTERFACE" },
97         { DBUS_HEADER_FIELD_MEMBER, "MEMBER" },
98         { DBUS_HEADER_FIELD_ERROR_NAME, "ERROR_NAME" },
99         { DBUS_HEADER_FIELD_REPLY_SERIAL, "REPLY_SERIAL" },
100         { DBUS_HEADER_FIELD_DESTINATION, "DESTINATION" },
101         { DBUS_HEADER_FIELD_SENDER, "SENDER" },
102         { DBUS_HEADER_FIELD_SIGNATURE, "SIGNATURE" },
103         { DBUS_HEADER_FIELD_UNIX_FDS, "UNIX_FDS" },
104         { 0, NULL }
105 };
106
107 typedef struct {
108         packet_info *pinfo;
109
110         guint16 (*get16)(tvbuff_t *, const gint);
111         guint32 (*get32)(tvbuff_t *, const gint);
112         gdouble (*getdouble)(tvbuff_t *, const gint);
113         int enc;
114
115         guint32 body_len;
116         guint32 fields_len;
117         const char *body_sig;
118 } dbus_info_t;
119
120 typedef union {
121         char *str;
122         guint uint;
123
124 } dbus_val_t;
125
126 static gboolean
127 dbus_validate_object_path(const char *path)
128 {
129         /* XXX check */
130         if (*path != '/')
131                 return FALSE;
132
133         do {
134                 path++;
135
136                 if (*path == '/')
137                         return FALSE;
138
139                 while ((*path >= 'A' && *path <= 'Z') || (*path >= 'a' && *path <= 'z') || (*path >= '0' && *path <= '9') || *path == '_')
140                         path++;
141
142                 if (*path == '\0')
143                         return TRUE;
144
145         } while (*path == '/');
146
147         return FALSE;
148 }
149
150 static gboolean
151 dbus_validate_signature(const char *sig _U_)
152 {
153         /* XXX implement */
154         return TRUE;
155 }
156
157 static int
158 dissect_dbus_sig(tvbuff_t *tvb, dbus_info_t *dinfo, proto_tree *tree, int offset, char sig, dbus_val_t *ret)
159 {
160         const int org_offset = offset;
161         proto_item *ti;
162
163         switch (sig) {
164                 case 'y':       /* BYTE */
165                 {
166                         guint8 val;
167
168                         val = tvb_get_guint8(tvb, offset);
169                         offset += 1;
170
171                         proto_tree_add_uint_format(tree, hf_dbus_value_uint, tvb, org_offset, offset - org_offset, val, "BYTE: %u", val);
172                         ret->uint = val;
173                         return offset;
174                 }
175
176                 case 'b':       /* BOOLEAN */
177                 {
178                         guint32 val;
179
180                         val = dinfo->get32(tvb, offset);
181                         offset += 4;
182
183                         ti = proto_tree_add_boolean_format(tree, hf_dbus_value_bool, tvb, org_offset, offset - org_offset, val, "BOOLEAN: %s", val ? "True" : "False");
184                         if (val != 0 && val != 1) {
185                                 expert_add_info_format(dinfo->pinfo, ti, PI_PROTOCOL, PI_WARN, "Invalid boolean value (must be 0 or 1 is: %u)", val);
186                                 return -1;
187                         }
188                         ret->uint = val;
189                         return offset;
190                 }
191
192                 case 'n':       /* INT16 */
193                 {
194                         gint16 val;
195
196                         val = (gint16 )dinfo->get16(tvb, offset);
197                         offset += 2;
198
199                         proto_tree_add_uint_format(tree, hf_dbus_value_int, tvb, org_offset, offset - org_offset, val, "INT16: %d", val);
200                         /* XXX ret */
201                         return offset;
202                 }
203
204                 case 'q':       /* UINT16 */
205                 {
206                         guint16 val;
207
208                         val = dinfo->get16(tvb, offset);
209                         offset += 2;
210
211                         proto_tree_add_uint_format(tree, hf_dbus_value_uint, tvb, org_offset, offset - org_offset, val, "UINT16: %u", val);
212                         ret->uint = val;
213                         return offset;
214                 }
215
216                 case 'i':       /* INT32 */
217                 {
218                         gint32 val;
219
220                         val = (gint32) dinfo->get32(tvb, offset);
221                         offset += 4;
222
223                         proto_tree_add_int_format(tree, hf_dbus_value_int, tvb, org_offset, offset - org_offset, val, "INT32: %d", val);
224                         /* XXX ret */
225                         return offset;
226                 }
227
228                 case 'u':       /* UINT32 */
229                 {
230                         guint32 val;
231
232                         val = dinfo->get32(tvb, offset);
233                         offset += 4;
234
235                         proto_tree_add_uint_format(tree, hf_dbus_value_uint, tvb, org_offset, offset - org_offset, val, "UINT32: %u", val);
236                         ret->uint = val;
237                         return offset;
238                 }
239
240                 case 'x':       /* INT64 */
241                 case 't':       /* UINT64 */
242                         return -1;
243
244                 case 'd':       /* DOUBLE */
245                 {
246                         gdouble val;
247
248                         val = dinfo->getdouble(tvb, offset);
249                         offset += 8;
250
251                         proto_tree_add_double_format(tree, hf_dbus_value_double, tvb, org_offset, offset - org_offset, val, "DOUBLE: %." STRINGIFY(DBL_DIG) "g", val);
252                         /* XXX ret */
253                         return offset;
254                 }
255
256                 case 's':       /* STRING */
257                 case 'o':       /* OBJECT_PATH */
258                 {
259                         guint32 len;
260                         char *val;
261
262                         len = dinfo->get32(tvb, offset);
263                         offset += 4;
264
265                         val = tvb_get_ephemeral_string(tvb, offset, len);
266                         offset += (len + 1 /* NUL-byte */ + 3) & ~3;
267
268                         if (sig == 's') {
269                                 ti = proto_tree_add_string_format(tree, hf_dbus_value_str, tvb, org_offset, offset - org_offset, val, "STRING: %s", val);
270                                 if (!g_utf8_validate(val, -1, NULL)) {
271                                         expert_add_info_format(dinfo->pinfo, ti, PI_PROTOCOL, PI_WARN, "Invalid string (not UTF-8)");
272                                         return -1;
273                                 }
274                         } else {
275                                 ti = proto_tree_add_string_format(tree, hf_dbus_value_str, tvb, org_offset, offset - org_offset, val, "OBJECT_PATH: %s", val);
276                                 if (!dbus_validate_object_path(val)) {
277                                         expert_add_info_format(dinfo->pinfo, ti, PI_PROTOCOL, PI_WARN, "Invalid object_path");
278                                         return -1;
279                                 }
280                         }
281                         ret->str = val;
282                         return offset;
283                 }
284
285                 case 'g':       /* SIGNATURE */
286                 {
287                         guint8 len;
288                         char *val;
289
290                         len = tvb_get_guint8(tvb, offset);
291                         offset += 1;
292
293                         val = tvb_get_ephemeral_string(tvb, offset, len);
294                         offset += (len + 1);
295
296                         ti = proto_tree_add_string_format(tree, hf_dbus_value_str, tvb, org_offset, offset - org_offset, val, "SIGNATURE: %s", val);
297                         if (!dbus_validate_signature(val)) {
298                                 expert_add_info_format(dinfo->pinfo, ti, PI_PROTOCOL, PI_WARN, "Invalid signature");
299                                 return -1;
300                         }
301                         ret->str = val;
302                         return offset;
303                 }
304
305                 /* ... */
306         }
307         return -1;
308 }
309
310 static int
311 dissect_dbus_field_signature(tvbuff_t *tvb, dbus_info_t *dinfo, proto_tree *tree, int offset, int field_code)
312 {
313         const int org_offset = offset;
314
315         proto_item *ti;
316         guint sig_len;
317         char *sig;
318
319         sig_len = tvb_get_guint8(tvb, offset);
320         offset += 1;
321
322         /* sig_len = tvb_strsize(tvb, offset); */
323
324         sig = tvb_get_ephemeral_string(tvb, offset, sig_len);
325         offset += (sig_len + 1);
326
327         ti = proto_tree_add_string(tree, hf_dbus_type_signature, tvb, org_offset, offset - org_offset, sig);
328         if (!dbus_validate_signature(sig)) {
329                 expert_add_info_format(dinfo->pinfo, ti, PI_PROTOCOL, PI_WARN, "Invalid signature");
330                 return -1;
331         }
332
333         switch (field_code) {
334                 case DBUS_HEADER_FIELD_REPLY_SERIAL:
335                         if (!strcmp(sig, "u")) {        /* UINT32 */
336                                 dbus_val_t serial_val;
337
338                                 offset = dissect_dbus_sig(tvb, dinfo, tree, offset, 'u', &serial_val);
339                                 if (offset != -1)
340                                         { /* XXX link with sending frame (serial_val.uint) */ }
341                                 return offset;
342                         }
343                         break;
344
345                 case DBUS_HEADER_FIELD_DESTINATION:
346                 case DBUS_HEADER_FIELD_SENDER:
347                         if (!strcmp(sig, "s")) {        /* STRING */
348                                 dbus_val_t addr_val;
349
350                                 offset = dissect_dbus_sig(tvb, dinfo, tree, offset, 's', &addr_val);
351                                 if (offset != -1)
352                                         SET_ADDRESS((field_code == DBUS_HEADER_FIELD_DESTINATION) ? &dinfo->pinfo->dst : &dinfo->pinfo->src,
353                                                     AT_STRINGZ, (int)strlen(addr_val.str)+1, addr_val.str);
354                                 return offset;
355                         }
356                         break;
357
358                 case DBUS_HEADER_FIELD_SIGNATURE:
359                         if (!strcmp(sig, "g")) {        /* SIGNATURE */
360                                 dbus_val_t sig_val;
361
362                                 offset = dissect_dbus_sig(tvb, dinfo, tree, offset, 'g', &sig_val);
363                                 if (offset != -1)
364                                         dinfo->body_sig = sig_val.str;
365                                 return offset;
366                         }
367                         break;
368         }
369
370         while (*sig) {
371                 dbus_val_t val;
372
373                 offset = dissect_dbus_sig(tvb, dinfo, tree, offset, *sig, &val);
374                 if (offset == -1)
375                         return -1;
376                 sig++;
377         }
378         return offset;
379 }
380
381 static int
382 dissect_dbus_hdr_fields(tvbuff_t *tvb, dbus_info_t *dinfo, proto_tree *tree, int offset)
383 {
384         int end_offset;
385
386         end_offset = offset + dinfo->fields_len;
387
388         while (offset < end_offset) {
389                 proto_tree *field_tree;
390                 proto_item *ti;
391
392                 guint8 field_code;
393
394                 ti = proto_tree_add_item(tree, hf_dbus_hdr_field, tvb, offset, 0, ENC_NA);
395                 field_tree = proto_item_add_subtree(ti, ett_dbus_field);
396
397                 field_code = tvb_get_guint8(tvb, offset);
398                 proto_tree_add_item(field_tree, hf_dbus_hdr_field_code, tvb, offset, 1, dinfo->enc);
399                 proto_item_append_text(ti, ": %s", val_to_str(field_code, field_code_vals, "Unknown: %d"));
400                 offset += 1;
401
402                 offset = dissect_dbus_field_signature(tvb, dinfo, field_tree, offset, field_code);
403                 if (offset == -1)
404                         break;
405
406                 offset = (offset + 7) & ~7;     /* XXX ? */
407
408                 proto_item_set_end(ti, tvb, offset);
409         }
410
411         /* XXX, verify if all required fields are preset */
412
413         if (offset >= end_offset) {
414                 /* XXX expert */
415         }
416
417         return end_offset;
418 }
419
420 static int
421 dissect_dbus_hdr(tvbuff_t *tvb, dbus_info_t *dinfo, proto_tree *tree, int offset)
422 {
423         proto_tree *hdr_tree;
424         proto_item *ti;
425
426         guint8 type;
427
428         ti = proto_tree_add_item(tree, hf_dbus_hdr, tvb, offset, 0, ENC_NA);
429         hdr_tree = proto_item_add_subtree(ti, ett_dbus_hdr);
430
431         proto_tree_add_item(hdr_tree, hf_dbus_hdr_endianness, tvb, offset, 1, ENC_ASCII | ENC_NA);
432         offset += 1;
433
434         type = tvb_get_guint8(tvb, offset);
435         col_add_str(dinfo->pinfo->cinfo, COL_INFO, val_to_str_const(type, message_type_vals, ""));
436         proto_tree_add_item(hdr_tree, hf_dbus_hdr_type, tvb, offset, 1, dinfo->enc);
437         offset += 1;
438
439         proto_tree_add_item(hdr_tree, hf_dbus_hdr_flags, tvb, offset, 1, dinfo->enc);
440         offset += 1;
441
442         proto_tree_add_item(hdr_tree, hf_dbus_hdr_version, tvb, offset, 1, dinfo->enc);
443         offset += 1;
444
445         dinfo->body_len = dinfo->get32(tvb, offset);
446         proto_tree_add_item(hdr_tree, hf_dbus_hdr_body_length, tvb, offset, 4, dinfo->enc);
447         offset += 4;
448
449         proto_tree_add_item(hdr_tree, hf_dbus_hdr_serial, tvb, offset, 4, dinfo->enc);
450         offset += 4;
451
452         dinfo->fields_len = dinfo->get32(tvb, offset);
453         proto_tree_add_item(hdr_tree, hf_dbus_hdr_fields_length, tvb, offset, 4, dinfo->enc);
454         offset += 4;
455
456         return offset;
457 }
458
459 static int
460 dissect_dbus_body(tvbuff_t *tvb, dbus_info_t *dinfo, proto_tree *tree, int offset)
461 {
462         proto_tree *body_tree;
463         proto_item *ti;
464
465         if (dinfo->body_len && dinfo->body_sig[0]) {
466                 const char *sig = dinfo->body_sig;
467
468                 ti = proto_tree_add_item(tree, hf_dbus_body, tvb, offset, 0, ENC_NA);
469                 body_tree = proto_item_add_subtree(ti, ett_dbus_body);
470
471                 while (*sig) {
472                         dbus_val_t val;
473
474                         offset = dissect_dbus_sig(tvb, dinfo, body_tree, offset, *sig, &val);
475                         if (offset == -1)
476                                 return -1;
477                         sig++;
478                 }
479
480                 proto_item_set_end(ti, tvb, offset);
481
482         } else if (dinfo->body_len || dinfo->body_sig[0]) {
483                 /* XXX smth wrong */
484         }
485         return offset;
486 }
487
488 static int
489 dissect_dbus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
490 {
491         proto_tree *dbus_tree = NULL;
492         dbus_info_t dinfo;
493
494         int offset;
495
496         col_set_str(pinfo->cinfo, COL_PROTOCOL, "D-BUS");
497         col_clear(pinfo->cinfo, COL_INFO);
498
499         memset(&dinfo, 0, sizeof(dinfo));
500         dinfo.pinfo = pinfo;
501         switch (tvb_get_guint8(tvb, 0)) {
502                 case 'l':
503                         dinfo.enc   = ENC_LITTLE_ENDIAN;
504                         dinfo.get16 = tvb_get_letohs;
505                         dinfo.get32 = tvb_get_letohl;
506                         dinfo.getdouble = tvb_get_letohieee_double;
507                         break;
508                 case 'B':
509                         dinfo.enc   = ENC_BIG_ENDIAN;
510                         dinfo.get16 = tvb_get_ntohs;
511                         dinfo.get32 = tvb_get_ntohl;
512                         dinfo.getdouble = tvb_get_ntohieee_double;
513                         break;
514                 default:        /* same as BIG_ENDIAN */
515                         /* XXX we should probably return 0; */
516                         dinfo.enc   = ENC_NA;
517                         dinfo.get16 = tvb_get_ntohs;
518                         dinfo.get32 = tvb_get_ntohl;
519                         dinfo.getdouble = tvb_get_ntohieee_double;
520         }
521
522         if (tree) {
523                 proto_item *ti = proto_tree_add_item(tree, proto_dbus, tvb, 0, -1, ENC_NA);
524                 dbus_tree = proto_item_add_subtree(ti, ett_dbus);
525         }
526
527         offset = 0;
528         offset = dissect_dbus_hdr(tvb, &dinfo, dbus_tree, offset);
529         offset = dissect_dbus_hdr_fields(tvb, &dinfo, dbus_tree, offset);
530         /* header aligned to 8B */
531         offset = (offset + 7) & ~7;
532
533         if (!dinfo.body_sig)
534                 dinfo.body_sig = "";
535
536         offset = dissect_dbus_body(tvb, &dinfo, dbus_tree, offset);
537
538         return offset;
539 }
540
541 #define DBUS_HEADER_LEN 16
542
543 static guint
544 get_dbus_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
545 {
546         guint32 (*get_guint32)(tvbuff_t *, const gint);
547
548         guint32 len_body, len_hdr;
549
550         switch (tvb_get_guint8(tvb, offset)) {
551                 case 'l':
552                         get_guint32 = tvb_get_letohl;
553                         break;
554                 case 'B':
555                 default:
556                         get_guint32 = tvb_get_ntohl;
557                         break;
558         }
559
560         len_hdr = DBUS_HEADER_LEN + get_guint32(tvb, offset + 12);
561         len_hdr = (len_hdr + 7) & ~7;
562         len_body = get_guint32(tvb, offset + 4);
563
564         return len_hdr + len_body;
565 }
566
567 static void
568 dissect_dbus_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
569 {
570         dissect_dbus(tvb, pinfo, tree, NULL);
571 }
572
573 static int
574 dissect_dbus_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
575 {
576         tcp_dissect_pdus(tvb, pinfo, tree, dbus_desegment, DBUS_HEADER_LEN, get_dbus_message_len, dissect_dbus_pdu);
577         return tvb_length(tvb);
578 }
579
580 void
581 proto_register_dbus(void)
582 {
583         /* XXX, FT_NONE -> FT_BYTES? */
584         static hf_register_info hf[] = {
585         /* Header */
586                 { &hf_dbus_hdr,
587                         { "Header", "dbus.header", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
588                 },
589                 { &hf_dbus_hdr_endianness,
590                         { "Endianness Flag", "dbus.endianness", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }
591                 },
592                 { &hf_dbus_hdr_type,
593                         { "Message Type", "dbus.type", FT_UINT8, BASE_DEC, VALS(message_type_vals), 0x00, NULL, HFILL }
594                 },
595                 { &hf_dbus_hdr_flags,
596                         { "Message Flags", "dbus.flags", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }
597                 },
598                 { &hf_dbus_hdr_version,
599                         { "Protocol Version", "dbus.version", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }
600                 },
601                 { &hf_dbus_hdr_body_length,
602                         { "Message body Length", "dbus.length", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
603                 },
604                 { &hf_dbus_hdr_serial,
605                         { "Message Serial (cookie)", "dbus.serial", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
606                 },
607                 { &hf_dbus_hdr_fields_length,
608                         { "Header fields Length", "dbus.fields_length", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
609                 },
610         /* Header field */
611                 { &hf_dbus_hdr_field,
612                         { "Header Field", "dbus.field", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
613                 },
614                 { &hf_dbus_hdr_field_code,
615                         { "Field code", "dbus.field.code", FT_UINT8, BASE_DEC, VALS(field_code_vals), 0x00, NULL, HFILL }
616                 },
617
618                 { &hf_dbus_type_signature,
619                         { "Type signature", "dbus.type_signature", FT_STRINGZ, BASE_NONE, NULL, 0x00, NULL, HFILL }
620                 },
621
622                 { &hf_dbus_body,
623                         { "Body", "dbus.body", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
624                 },
625
626         /* Values */
627                 { &hf_dbus_value_bool,
628                         { "Value", "dbus.value.bool", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL }
629                 },
630                 { &hf_dbus_value_int,
631                         { "Value", "dbus.value.int", FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
632                 },
633                 { &hf_dbus_value_uint,
634                         { "Value", "dbus.value.uint", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
635                 },
636                 { &hf_dbus_value_str,
637                         { "Value", "dbus.value.str", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL }
638                 },
639                 { &hf_dbus_value_double,
640                         { "Value", "dbus.value.double", FT_DOUBLE, BASE_NONE, NULL, 0x00, NULL, HFILL }
641                 }
642         };
643
644         static gint *ett[] = {
645                 &ett_dbus,
646                 &ett_dbus_hdr,
647                 &ett_dbus_body,
648                 &ett_dbus_field
649         };
650
651         proto_dbus = proto_register_protocol("D-Bus", "D-BUS", "dbus");
652
653         proto_register_field_array(proto_dbus, hf, array_length(hf));
654         proto_register_subtree_array(ett, array_length(ett));
655 }
656
657 void
658 proto_reg_handoff_dbus(void)
659 {
660         dissector_handle_t dbus_handle = new_create_dissector_handle(dissect_dbus, proto_dbus);
661         dissector_handle_t dbus_handle_tcp = new_create_dissector_handle(dissect_dbus_tcp, proto_dbus);
662
663         dissector_add_uint("wtap_encap", WTAP_ENCAP_DBUS, dbus_handle);
664         dissector_add_handle("tcp.port", dbus_handle_tcp);
665 }
666