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