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