3 * Copyright (c) 2010, Holger Grandy, BMW Car IT GmbH (holger.grandy@bmw-carit.de)
7 * Apache Etch Protocol dissector
8 * http://incubator.apache.org/etch/
10 * This dissector reads configuration files (generated by Etch IDL compiler).
11 * Configuration file directory path is given in dissector options.
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40 #include <wsutil/file_util.h>
41 #include <wsutil/report_err.h>
42 #include <epan/packet.h>
43 #include <epan/prefs.h>
44 #include <epan/dissectors/packet-tcp.h>
45 #include <epan/wmem/wmem.h>
48 * maximum numbers for symbols from config files
50 #define ETCH_MAX_SYMBOL_LENGTH "256"
53 * Magic Number for Etch
55 static const guint8 etch_magic
[] = { 0xde, 0xad, 0xbe, 0xef };
58 * Typecodes in the Etch protocol, representing the field types
60 #define ETCH_TC_NULL 0x80
61 #define ETCH_TC_NONE 0x81
62 #define ETCH_TC_BOOLEAN_FALSE 0x82
63 #define ETCH_TC_BOOLEAN_TRUE 0x83
64 #define ETCH_TC_BYTE 0x84
65 #define ETCH_TC_SHORT 0x85
66 #define ETCH_TC_INT 0x86
67 #define ETCH_TC_LONG 0x87
68 #define ETCH_TC_FLOAT 0x88
69 #define ETCH_TC_DOUBLE 0x89
70 #define ETCH_TC_BYTES 0x8B
71 #define ETCH_TC_ARRAY 0x91
72 #define ETCH_TC_EMPTY_STRING 0x92
73 #define ETCH_TC_STRING 0x93
74 #define ETCH_TC_STRUCT 0x94
75 #define ETCH_TC_CUSTOM 0x95
76 #define ETCH_TC_ANY 0x96
77 #define ETCH_TC_MIN_TINY_INT 0xC0
78 #define ETCH_TC_MAX_TINY_INT 0x7F
80 /***************************************************************************/
84 * String representation of all Type Codes
86 static const value_string tc_lookup_table
[] = {
87 { ETCH_TC_NULL
, "Etch TypeCode: NULL"},
88 { ETCH_TC_NONE
, "Etch TypeCode: NONE"},
89 { ETCH_TC_BOOLEAN_FALSE
, "Etch TypeCode: BOOLEAN_FALSE" },
90 { ETCH_TC_BOOLEAN_TRUE
, "Etch TypeCode: BOOLEAN_TRUE"},
91 { ETCH_TC_BYTE
, "Etch TypeCode: BYTE"},
92 { ETCH_TC_SHORT
, "Etch TypeCode: SHORT"},
93 { ETCH_TC_INT
, "Etch TypeCode: INT"},
94 { ETCH_TC_LONG
, "Etch TypeCode: LONG"},
95 { ETCH_TC_FLOAT
, "Etch TypeCode: FLOAT"},
96 { ETCH_TC_DOUBLE
, "Etch TypeCode: DOUBLE"},
97 { ETCH_TC_BYTES
, "Etch TypeCode: BYTES"},
98 { ETCH_TC_ARRAY
, "Etch TypeCode: ARRAY"},
99 { ETCH_TC_EMPTY_STRING
, "Etch TypeCode: EMPTY_STRING"},
100 { ETCH_TC_STRING
, "Etch TypeCode: STRING"},
101 { ETCH_TC_STRUCT
, "Etch TypeCode: STRUCT"},
102 { ETCH_TC_CUSTOM
, "Etch TypeCode: CUSTOM"},
103 { ETCH_TC_ANY
, "Etch TypeCode: ANY"},
108 * Wireshark internal fields
110 static int proto_etch
= -1;
111 static gint ett_etch
= -1;
112 static gint ett_etch_struct
= -1;
113 static gint ett_etch_keyvalue
= -1;
114 static gint ett_etch_key
= -1;
115 static gint ett_etch_value
= -1;
116 static int hf_etch_sig
= -1;
117 static int hf_etch_length
= -1;
118 static int hf_etch_version
= -1;
119 /* static int hf_etch_typecode = -1; */
120 static int hf_etch_value
= -1;
121 static int hf_etch_bytes
= -1;
122 static int hf_etch_byte
= -1;
123 static int hf_etch_short
= -1;
124 static int hf_etch_int
= -1;
125 static int hf_etch_long
= -1;
126 static int hf_etch_float
= -1;
127 static int hf_etch_double
= -1;
128 /* static int hf_etch_key = -1; */
129 static int hf_etch_valuename
= -1;
130 static int hf_etch_keyname
= -1;
131 static int hf_etch_string
= -1;
132 static int hf_etch_keyvalue
= -1;
133 static int hf_etch_struct
= -1;
134 static int hf_etch_dim
= -1;
135 static int hf_etch_symbol
= -1;
137 static dissector_handle_t etch_handle
;
140 * internal fields/defines for dissector
143 static const char *gbl_keytab_folder
= "";
144 static guint gbl_etch_port
= 0;
145 static char *gbl_current_keytab_folder
= NULL
;
147 static int gbl_pdu_counter
;
148 static guint32 gbl_old_frame_num
;
150 static wmem_strbuf_t
*gbl_symbol_buffer
= NULL
;
151 static gboolean gbl_have_symbol
= FALSE
;
153 /***************************************************************************/
157 * forward declared dissector methods
159 static void read_key_value(unsigned int *offset
, tvbuff_t
*tvb
,
160 proto_tree
*etch_tree
);
161 static void read_struct(unsigned int *offset
, tvbuff_t
*tvb
,
162 proto_tree
*etch_tree
, int add_type_field
);
163 static int read_value(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
,
165 void proto_reg_handoff_etch(void);
167 /************************************************************************
168 * Symbol value-string functions
169 * Essentially: Build a value_string_ext at runtime:
170 * a. Upon startup & whenever symbol folder changed: Read from file(s)
171 * and add all hash/symbol pairs to a GArray;
172 * b. When file reads complete, sort the GArray and then create a
173 * value_string_ext from the array for use by try_val_to_str_ext & friends.
174 * (Code based upon code in packet-diameter.c)
176 static GArray
*gbl_symbols_array
= NULL
;
177 static value_string_ext
*gbl_symbols_vs_ext
= NULL
;
180 gbl_symbols_new(void)
182 DISSECTOR_ASSERT(gbl_symbols_array
== NULL
);
183 gbl_symbols_array
= g_array_new(TRUE
, TRUE
, sizeof(value_string
));
187 gbl_symbols_free(void)
189 wmem_free(wmem_epan_scope(), gbl_symbols_vs_ext
);
190 gbl_symbols_vs_ext
= NULL
;
192 if (gbl_symbols_array
!= NULL
) {
195 vs_p
= (value_string
*)(void *)gbl_symbols_array
->data
;
196 for (i
=0; i
<gbl_symbols_array
->len
; i
++) {
197 g_free((gchar
*)vs_p
[i
].strptr
);
199 g_array_free(gbl_symbols_array
, TRUE
);
200 gbl_symbols_array
= NULL
;
205 gbl_symbols_array_append(guint32 hash
, gchar
*symbol
)
207 value_string vs
= {hash
, symbol
};
208 DISSECTOR_ASSERT(gbl_symbols_array
!= NULL
);
209 g_array_append_val(gbl_symbols_array
, vs
);
213 gbl_symbols_compare_vs(gconstpointer a
, gconstpointer b
)
215 value_string
*vsa
= (value_string
*)a
;
216 value_string
*vsb
= (value_string
*)b
;
218 if(vsa
->value
> vsb
->value
)
220 if(vsa
->value
< vsb
->value
)
227 gbl_symbols_vs_ext_new(void)
229 DISSECTOR_ASSERT(gbl_symbols_vs_ext
== NULL
);
230 DISSECTOR_ASSERT(gbl_symbols_array
!= NULL
);
231 g_array_sort(gbl_symbols_array
, gbl_symbols_compare_vs
);
232 gbl_symbols_vs_ext
= value_string_ext_new((value_string
*)(void *)gbl_symbols_array
->data
,
233 gbl_symbols_array
->len
+1,
234 "etch-global-symbols" );
237 /*********************************************************************************/
241 * get the length of a given typecode in bytes, -1 if to be derived from message
244 get_byte_length(guint8 typecode
)
249 case ETCH_TC_BOOLEAN_FALSE
:
250 case ETCH_TC_BOOLEAN_TRUE
:
251 case ETCH_TC_EMPTY_STRING
:
252 case ETCH_TC_MIN_TINY_INT
:
253 case ETCH_TC_MAX_TINY_INT
:
285 * add all etch symbols from file to our symbol cache
288 add_symbols_of_file(const char *filename
)
292 pFile
= ws_fopen(filename
, "r");
296 while (fgets(line
, sizeof line
, pFile
) != NULL
) {
300 length
= strlen(line
);
302 /* Must at least have a hash, else skip line */
307 while (pos
> 0 && (line
[pos
] == 0xD || line
[pos
] == 0xA)) {
310 line
[pos
+ 1] = '\0';
313 if (sscanf(&line
[0], "%x", &hash
) != 1)
314 continue; /* didn't find a valid hex value at the beginning of the line */
316 /* And read the symbol */
317 pos
= strcspn(line
, ",");
318 if ((line
[pos
] != '\0') && (line
[pos
+1] !='\0')) /* require at least 1 char in symbol */
319 gbl_symbols_array_append(hash
,
320 g_strdup_printf("%." ETCH_MAX_SYMBOL_LENGTH
"s", &line
[pos
+1]));
327 * add all etch symbol from directory to our symbol cache
330 read_hashed_symbols_from_dir(const char *dirname
)
336 GError
*err_p
= NULL
;
338 if(gbl_current_keytab_folder
!= NULL
) {
339 g_free(gbl_current_keytab_folder
);
340 gbl_current_keytab_folder
= NULL
;
345 if ((dirname
== NULL
) || (dirname
[0] == '\0'))
348 if ((dir
= ws_dir_open(dirname
, 0, &err_p
)) != NULL
) {
351 gbl_current_keytab_folder
= g_strdup(dirname
);
352 while ((file
= ws_dir_read_name(dir
)) != NULL
) {
353 name
= ws_dir_get_name(file
);
355 if (g_str_has_suffix(file
, ".ewh")) {
357 g_strdup_printf("%s" G_DIR_SEPARATOR_S
"%s", dirname
,
359 add_symbols_of_file(filename
);
364 gbl_symbols_vs_ext_new();
366 report_failure("%s", err_p
->message
);
371 /***********************************************************************************/
372 /* Etch Protocol Functions */
375 * read a type flag from tvb and add it to tree
378 read_type(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
)
382 const gchar
*type_as_string
;
384 type_code
= tvb_get_guint8(tvb
, *offset
);
385 type_as_string
= val_to_str(type_code
, tc_lookup_table
, "Etch TypeCode: 0x%02x");
386 proto_tree_add_text(etch_tree
, tvb
, *offset
, 1, "%s", type_as_string
);
392 * read a array type flag and add it to tree
395 read_array_type(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
)
399 type_code
= tvb_get_guint8(tvb
, *offset
);
401 read_type(offset
, tvb
, etch_tree
);
402 if (type_code
== ETCH_TC_CUSTOM
) {
403 read_type(offset
, tvb
, etch_tree
);
404 proto_tree_add_item(etch_tree
, hf_etch_value
, tvb
, *offset
, 4,
412 * read the length of an array and add it to tree
415 read_length(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
)
418 int length_of_array_length_type
;
421 tiny
= tvb_get_guint8(tvb
, *offset
);
423 /* Is this the value already? */
424 if ( tiny
<= ETCH_TC_MAX_TINY_INT
425 || tiny
>= ETCH_TC_MIN_TINY_INT
) {
427 length_of_array_length_type
= 1;
430 type_code
= read_type(offset
, tvb
, etch_tree
);
431 length_of_array_length_type
= get_byte_length(type_code
);
433 switch (length_of_array_length_type
) {
435 length
= tvb_get_guint8(tvb
, *offset
);
438 length
= tvb_get_ntohs(tvb
, *offset
);
441 length
= tvb_get_ntohl(tvb
, *offset
);
444 return 0; /* error! */
447 proto_tree_add_item(etch_tree
, hf_etch_length
, tvb
, *offset
,
448 length_of_array_length_type
, ENC_BIG_ENDIAN
);
449 (*offset
) += length_of_array_length_type
;
451 if (*offset
+ length
< *offset
) {
453 * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8464 */
454 length
= tvb_reported_length_remaining(tvb
, *offset
);
461 * read an array from tvb and add it to tree
464 read_array(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
)
469 read_type(offset
, tvb
, etch_tree
);
472 read_array_type(offset
, tvb
, etch_tree
);
475 proto_tree_add_item(etch_tree
, hf_etch_dim
, tvb
, *offset
, 1, ENC_NA
);
479 length
= read_length(offset
, tvb
, etch_tree
);
481 for (; length
> 0; length
--) {
482 read_value(offset
, tvb
, etch_tree
, hf_etch_value
);
485 read_type(offset
, tvb
, etch_tree
);
490 * read a sequence of bytes and add them to tree
493 read_bytes(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
)
497 read_type(offset
, tvb
, etch_tree
);
498 length
= read_length(offset
, tvb
, etch_tree
);
499 proto_tree_add_item(etch_tree
, hf_etch_bytes
, tvb
, *offset
, length
,
505 * read a string and add it to tree
508 read_string(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
)
512 read_type(offset
, tvb
, etch_tree
);
514 byteLength
= read_length(offset
, tvb
, etch_tree
);
516 proto_tree_add_item(etch_tree
, hf_etch_string
, tvb
, *offset
,
517 byteLength
, ENC_ASCII
|ENC_NA
);
518 (*offset
) += byteLength
;
522 * read a number and add it to tree
525 read_number(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
,
526 int asWhat
, guint8 type_code
)
530 read_type(offset
, tvb
, etch_tree
);
531 byteLength
= get_byte_length(type_code
);
532 if (byteLength
> 0) {
534 const gchar
*symbol
= NULL
;
537 gbl_symbol_buffer
= wmem_strbuf_new_label(wmem_packet_scope()); /* no symbol found yet */
538 if (byteLength
== 4) {
539 hash
= tvb_get_ntohl(tvb
, *offset
);
540 symbol
= try_val_to_str_ext(hash
, gbl_symbols_vs_ext
);
542 asWhat
= hf_etch_symbol
;
543 gbl_have_symbol
= TRUE
;
544 wmem_strbuf_append_printf(gbl_symbol_buffer
,"%s",symbol
);
547 ti
= proto_tree_add_item(etch_tree
, asWhat
, tvb
, *offset
,
548 byteLength
, ENC_BIG_ENDIAN
);
549 *offset
+= byteLength
;
550 if (symbol
!= NULL
) {
551 proto_item_append_text(ti
, " (0x%08x) %s", hash
, symbol
);
557 * read a value and add it to tree
560 read_value(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
,
565 type_code
= tvb_get_guint8(tvb
, *offset
);
566 if (type_code
<= ETCH_TC_MAX_TINY_INT
||
567 type_code
>= ETCH_TC_MIN_TINY_INT
) {
568 /* this is the value already */
569 proto_tree_add_item(etch_tree
, asWhat
, tvb
, *offset
, 1, ENC_BIG_ENDIAN
);
576 read_struct(offset
, tvb
, etch_tree
, 1);
579 read_array(offset
, tvb
, etch_tree
);
582 read_string(offset
, tvb
, etch_tree
);
585 read_number(offset
, tvb
, etch_tree
, hf_etch_float
, type_code
);
588 read_number(offset
, tvb
, etch_tree
, hf_etch_double
, type_code
);
591 read_number(offset
, tvb
, etch_tree
, hf_etch_short
, type_code
);
594 read_number(offset
, tvb
, etch_tree
, hf_etch_int
, type_code
);
597 read_number(offset
, tvb
, etch_tree
, hf_etch_long
, type_code
);
600 read_number(offset
, tvb
, etch_tree
, hf_etch_byte
, type_code
);
603 read_bytes(offset
, tvb
, etch_tree
);
606 read_number(offset
, tvb
, etch_tree
, asWhat
, type_code
);
612 * read a struct and add it to tree
615 read_struct(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
,
619 proto_tree
*new_tree
;
623 ti
= proto_tree_add_item(etch_tree
, hf_etch_struct
, tvb
, *offset
,
624 tvb_length(tvb
) - *offset
, ENC_NA
);
625 new_tree
= proto_item_add_subtree(ti
, ett_etch_struct
);
627 if (add_type_field
) {
628 read_type(offset
, tvb
, new_tree
);
630 /* struct type as hash */
631 read_value(offset
, tvb
, new_tree
, hf_etch_value
);
634 length
= read_value(offset
, tvb
, new_tree
, hf_etch_length
);
636 for (i
= 0; i
< length
; i
++) {
637 read_key_value(offset
, tvb
, new_tree
);
641 read_type(offset
, tvb
, new_tree
);
645 * read a key value pair and add it to tree
648 read_key_value(unsigned int *offset
, tvbuff_t
*tvb
, proto_tree
*etch_tree
)
650 proto_tree
*new_tree
;
651 proto_tree
*new_tree_bck
;
652 proto_item
*ti
, *parent_ti
;
654 gbl_have_symbol
= FALSE
;
657 proto_tree_add_item(etch_tree
, hf_etch_keyvalue
, tvb
, *offset
, 1,
659 new_tree_bck
= new_tree
=
660 proto_item_add_subtree(parent_ti
, ett_etch_keyvalue
);
662 ti
= proto_tree_add_item(new_tree
, hf_etch_keyname
, tvb
, *offset
, 0,
664 new_tree
= proto_item_add_subtree(ti
, ett_etch_key
);
665 read_value(offset
, tvb
, new_tree
, hf_etch_value
);
667 /* append the symbol of the key */
668 if(gbl_have_symbol
== TRUE
){
669 proto_item_append_text(parent_ti
, " (");
670 proto_item_append_text(parent_ti
, "%s", wmem_strbuf_get_str(gbl_symbol_buffer
));
671 proto_item_append_text(parent_ti
, ")");
674 ti
= proto_tree_add_item(new_tree_bck
, hf_etch_valuename
, tvb
, *offset
,
676 new_tree
= proto_item_add_subtree(ti
, ett_etch_value
);
677 read_value(offset
, tvb
, new_tree
, hf_etch_value
);
680 /*************************************************************************/
682 * Preparse the message for the info column
684 static wmem_strbuf_t
*
685 get_column_info(tvbuff_t
*tvb
)
689 wmem_strbuf_t
*result_buf
;
692 /* We've a full PDU: 8 bytes + pdu_packetlen bytes */
693 result_buf
= wmem_strbuf_new_label(wmem_packet_scope());
695 my_offset
+= (4 + 4 + 1); /* skip Magic, Length, Version */
697 type_code
= tvb_get_guint8(tvb
, my_offset
);
698 byte_length
= get_byte_length(type_code
);
701 if (byte_length
== 4) {
704 hash
= tvb_get_ntohl(tvb
, my_offset
);
705 symbol
= try_val_to_str_ext(hash
, gbl_symbols_vs_ext
);
706 if (symbol
!= NULL
) {
707 wmem_strbuf_append_printf(result_buf
, "%s()", symbol
);
715 /****************************************************************************************************/
717 * main dissector function for an etch message
720 dissect_etch_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
722 /* We've a full PDU: 8 bytes + pdu_packetlen bytes */
723 wmem_strbuf_t
*colInfo
= NULL
;
725 if (pinfo
->cinfo
|| tree
) {
726 colInfo
= get_column_info(tvb
); /* get current symbol */
730 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ETCH");
733 /* Switch to another frame? => Clear column */
734 if (pinfo
->fd
->num
!= gbl_old_frame_num
) {
735 col_clear(pinfo
->cinfo
, COL_INFO
);
738 gbl_old_frame_num
= pinfo
->fd
->num
;
740 col_set_writable(pinfo
->cinfo
, TRUE
);
741 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", wmem_strbuf_get_str(colInfo
));
745 /* we are being asked for details */
748 proto_tree
*etch_tree
;
750 ti
= proto_tree_add_protocol_format(tree
, proto_etch
, tvb
, 0, -1,
751 "ETCH Protocol: %s", wmem_strbuf_get_str(colInfo
));
754 etch_tree
= proto_item_add_subtree(ti
, ett_etch
);
755 proto_tree_add_item(etch_tree
, hf_etch_sig
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
756 proto_tree_add_item(etch_tree
, hf_etch_length
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
757 proto_tree_add_item(etch_tree
, hf_etch_version
, tvb
, 8, 1, ENC_NA
);
758 read_struct(&offset
, tvb
, etch_tree
, 0);
761 return tvb_length(tvb
);
765 * determine PDU length of protocol etch
768 get_etch_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
)
770 /* length is at offset 4. we add magic bytes length + length size */
771 return tvb_get_ntohl(tvb
, offset
+ 4) + 8;
776 * main dissector function for the etch protocol
779 dissect_etch(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
781 if (tvb_length(tvb
) < 4) {
782 /* Too small for an etch packet. */
786 if (tvb_memeql(tvb
, 0, etch_magic
, 4) == -1) {
787 /* Not an etch packet. */
791 tcp_dissect_pdus(tvb
, pinfo
, tree
, TRUE
, 8, get_etch_message_len
,
792 dissect_etch_message
, data
);
794 if (gbl_pdu_counter
> 0) {
795 col_set_writable(pinfo
->cinfo
, TRUE
);
796 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "[%d] ", gbl_pdu_counter
+ 1);
803 etch_dissector_init(void)
806 gbl_old_frame_num
= 0xFFFFFFFF;
809 void proto_register_etch(void)
811 module_t
*etch_module
;
813 static hf_register_info hf
[] = {
815 {"Etch Signature", "etch.signature",
821 {"Etch Length", "etch.msglength",
827 {"Etch Dim", "etch.dim",
833 {"Etch Version", "etch.version",
840 {"Etch TypeCode", "etch.typecode",
841 FT_STRING
, BASE_NONE
, /* FT_INT8 */
847 {"Etch Value", "etch.value",
853 {"Etch Bytes", "etch.bytes",
859 {"Etch Byte", "etch.byte",
865 {"Etch Short", "etch.short",
871 {"Etch Int", "etch.int",
877 {"Etch Long", "etch.long",
883 {"Etch Float", "etch.float",
889 {"Etch Double", "etch.double",
890 FT_DOUBLE
, BASE_NONE
,
895 {"Etch keyValue", "etch.keyvalue",
902 {"Etch key", "etch.key",
909 {"Etch symbol", "etch.symbol",
915 {"Etch Struct", "etch.struct",
921 {"Etch String", "etch.string",
922 FT_STRING
, BASE_NONE
,
927 {"Etch key", "etch.keyname",
933 {"Etch value", "etch.valuename",
940 /* Setup protocol subtree array */
941 static gint
*ett
[] = {
949 proto_etch
= proto_register_protocol("Apache Etch Protocol", /* name */
950 "Etch", /* short name */
954 proto_register_field_array(proto_etch
, hf
, array_length(hf
));
955 proto_register_subtree_array(ett
, array_length(ett
));
956 etch_handle
= new_register_dissector("etch", dissect_etch
, proto_etch
);
958 register_init_routine(&etch_dissector_init
);
960 etch_module
= prefs_register_protocol(proto_etch
,
961 proto_reg_handoff_etch
);
963 prefs_register_directory_preference(etch_module
, "file",
964 "Apache Etch symbol folder",
965 "Place the hash/symbol files "
966 "(generated by the Apache Etch compiler) "
967 "ending with .ewh here",
969 prefs_register_uint_preference(etch_module
, "tcp.port",
976 void proto_reg_handoff_etch(void)
978 static gboolean etch_prefs_initialized
= FALSE
;
979 static guint old_etch_port
= 0;
981 /* create dissector handle only once */
982 if(!etch_prefs_initialized
) {
983 /* add heuristic dissector for tcp */
984 heur_dissector_add("tcp", dissect_etch
, proto_etch
);
985 etch_prefs_initialized
= TRUE
;
988 if(old_etch_port
!= 0 && old_etch_port
!= gbl_etch_port
){
989 dissector_delete_uint("tcp.port", old_etch_port
, etch_handle
);
992 if(gbl_etch_port
!= 0 && old_etch_port
!= gbl_etch_port
) {
993 dissector_add_uint("tcp.port", gbl_etch_port
, etch_handle
);
996 old_etch_port
= gbl_etch_port
;
998 /* read config folder files, if filename has changed
999 * (while protecting strcmp() from NULLs)
1001 if((gbl_keytab_folder
== NULL
) || (gbl_current_keytab_folder
== NULL
) ||
1002 (strcmp(gbl_keytab_folder
, gbl_current_keytab_folder
) != 0)) {
1003 read_hashed_symbols_from_dir(gbl_keytab_folder
);
1008 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1013 * indent-tabs-mode: nil
1016 * vi: set shiftwidth=2 tabstop=8 expandtab:
1017 * :indentSize=2:tabSize=8:noTabs=true: