HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-etch.c
blob2588475ee22000d2c8dcfe28ce9711a59ad091f3
1 /* packet-etch.c
3 * Copyright (c) 2010, Holger Grandy, BMW Car IT GmbH (holger.grandy@bmw-carit.de)
5 * $Id$
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.
33 #include "config.h"
35 #include <glib.h>
37 #include <stdio.h>
38 #include <string.h>
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 /***************************************************************************/
81 /* Variables */
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"},
104 { 0, NULL}
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 /***************************************************************************/
154 /* Methods */
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,
164 int asWhat);
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;
179 static void
180 gbl_symbols_new(void)
182 DISSECTOR_ASSERT(gbl_symbols_array == NULL);
183 gbl_symbols_array = g_array_new(TRUE, TRUE, sizeof(value_string));
186 static void
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) {
193 value_string *vs_p;
194 guint i;
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;
204 static void
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);
212 static gint
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)
219 return 1;
220 if(vsa->value < vsb->value)
221 return -1;
223 return 0;
226 static void
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 /*********************************************************************************/
238 /* Aux Functions */
241 * get the length of a given typecode in bytes, -1 if to be derived from message
243 static gint32
244 get_byte_length(guint8 typecode)
246 switch (typecode) {
247 case ETCH_TC_NULL:
248 case ETCH_TC_NONE:
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:
254 return 0;
255 break;
256 case ETCH_TC_BYTE:
257 return 1;
258 break;
259 case ETCH_TC_SHORT:
260 return 2;
261 break;
262 case ETCH_TC_INT:
263 case ETCH_TC_FLOAT:
264 return 4;
265 break;
266 case ETCH_TC_LONG:
267 case ETCH_TC_DOUBLE:
268 return 8;
269 break;
270 case ETCH_TC_BYTES:
271 case ETCH_TC_ARRAY:
272 case ETCH_TC_STRING:
273 case ETCH_TC_STRUCT:
274 case ETCH_TC_CUSTOM:
275 case ETCH_TC_ANY:
276 return -1;
277 break;
278 default:
279 return 0;
280 break;
285 * add all etch symbols from file to our symbol cache
287 static void
288 add_symbols_of_file(const char *filename)
290 FILE *pFile;
292 pFile = ws_fopen(filename, "r");
294 if (pFile != NULL) {
295 char line[256];
296 while (fgets(line, sizeof line, pFile) != NULL) {
297 unsigned int hash;
298 size_t length, pos;
300 length = strlen(line);
302 /* Must at least have a hash, else skip line */
303 if (length < 10)
304 continue;
306 pos = length - 1;
307 while (pos > 0 && (line[pos] == 0xD || line[pos] == 0xA)) {
308 pos--;
310 line[pos + 1] = '\0';
312 /* Parse the Hash */
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]));
322 fclose(pFile);
327 * add all etch symbol from directory to our symbol cache
329 static void
330 read_hashed_symbols_from_dir(const char *dirname)
332 WS_DIR *dir;
333 WS_DIRENT *file;
334 const char *name;
335 char *filename;
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;
343 gbl_symbols_free();
345 if ((dirname == NULL) || (dirname[0] == '\0'))
346 return;
348 if ((dir = ws_dir_open(dirname, 0, &err_p)) != NULL) {
349 gbl_symbols_new();
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")) {
356 filename =
357 g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname,
358 name);
359 add_symbols_of_file(filename);
360 g_free(filename);
363 ws_dir_close(dir);
364 gbl_symbols_vs_ext_new();
365 }else{
366 report_failure("%s", err_p->message);
367 g_error_free(err_p);
371 /***********************************************************************************/
372 /* Etch Protocol Functions */
375 * read a type flag from tvb and add it to tree
377 static guint8
378 read_type(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
381 guint32 type_code;
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);
387 (*offset)++;
388 return type_code;
392 * read a array type flag and add it to tree
394 static void
395 read_array_type(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
397 guint32 type_code;
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,
405 ENC_BIG_ENDIAN);
406 (*offset) += 4;
412 * read the length of an array and add it to tree
414 static guint32
415 read_length(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
417 guint32 length;
418 int length_of_array_length_type;
419 guint8 tiny;
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) {
426 length = tiny;
427 length_of_array_length_type = 1;
428 } else {
429 guint8 type_code;
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) {
434 case 1:
435 length = tvb_get_guint8(tvb, *offset);
436 break;
437 case 2:
438 length = tvb_get_ntohs(tvb, *offset);
439 break;
440 case 4:
441 length = tvb_get_ntohl(tvb, *offset);
442 break;
443 default:
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) {
452 /* overflow case
453 * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8464 */
454 length = tvb_reported_length_remaining(tvb, *offset);
456 return length;
461 * read an array from tvb and add it to tree
463 static void
464 read_array(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
466 int length;
468 /* array type */
469 read_type(offset, tvb, etch_tree);
471 /* Array of type: */
472 read_array_type(offset, tvb, etch_tree);
474 /* Array dim */
475 proto_tree_add_item(etch_tree, hf_etch_dim, tvb, *offset, 1, ENC_NA);
476 (*offset)++;
478 /* Array length */
479 length = read_length(offset, tvb, etch_tree);
481 for (; length > 0; length--) {
482 read_value(offset, tvb, etch_tree, hf_etch_value);
484 /* terminaton */
485 read_type(offset, tvb, etch_tree);
490 * read a sequence of bytes and add them to tree
492 static void
493 read_bytes(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
495 int length;
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,
500 ENC_NA);
501 (*offset) += length;
505 * read a string and add it to tree
507 static void
508 read_string(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
510 int byteLength;
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
524 static void
525 read_number(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree,
526 int asWhat, guint8 type_code)
528 int byteLength;
530 read_type(offset, tvb, etch_tree);
531 byteLength = get_byte_length(type_code);
532 if (byteLength > 0) {
533 proto_item *ti;
534 const gchar *symbol = NULL;
535 guint32 hash = 0;
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);
541 if(symbol != NULL) {
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
559 static int
560 read_value(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree,
561 int asWhat)
563 guint8 type_code;
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);
570 (*offset)++;
571 return type_code;
574 switch(type_code) {
575 case ETCH_TC_CUSTOM:
576 read_struct(offset, tvb, etch_tree, 1);
577 break;
578 case ETCH_TC_ARRAY:
579 read_array(offset, tvb, etch_tree);
580 break;
581 case ETCH_TC_STRING:
582 read_string(offset, tvb, etch_tree);
583 break;
584 case ETCH_TC_FLOAT:
585 read_number(offset, tvb, etch_tree, hf_etch_float, type_code);
586 break;
587 case ETCH_TC_DOUBLE:
588 read_number(offset, tvb, etch_tree, hf_etch_double, type_code);
589 break;
590 case ETCH_TC_SHORT:
591 read_number(offset, tvb, etch_tree, hf_etch_short, type_code);
592 break;
593 case ETCH_TC_INT:
594 read_number(offset, tvb, etch_tree, hf_etch_int, type_code);
595 break;
596 case ETCH_TC_LONG:
597 read_number(offset, tvb, etch_tree, hf_etch_long, type_code);
598 break;
599 case ETCH_TC_BYTE:
600 read_number(offset, tvb, etch_tree, hf_etch_byte, type_code);
601 break;
602 case ETCH_TC_BYTES:
603 read_bytes(offset, tvb, etch_tree);
604 break;
605 default:
606 read_number(offset, tvb, etch_tree, asWhat, type_code);
608 return 0;
612 * read a struct and add it to tree
614 static void
615 read_struct(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree,
616 int add_type_field)
618 proto_item *ti;
619 proto_tree *new_tree;
620 int length;
621 int i;
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);
633 /* struct length */
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);
640 /* termination */
641 read_type(offset, tvb, new_tree);
645 * read a key value pair and add it to tree
647 static void
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;
656 parent_ti =
657 proto_tree_add_item(etch_tree, hf_etch_keyvalue, tvb, *offset, 1,
658 ENC_NA);
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,
663 ENC_NA);
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,
675 0, ENC_NA);
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)
687 int byte_length;
688 guint8 type_code;
689 wmem_strbuf_t *result_buf;
690 int my_offset = 0;
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);
699 my_offset++;
701 if (byte_length == 4) {
702 const gchar *symbol;
703 guint32 hash;
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);
711 return result_buf;
715 /****************************************************************************************************/
717 * main dissector function for an etch message
719 static int
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 */
729 if (pinfo->cinfo) {
730 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ETCH");
731 gbl_pdu_counter++;
733 /* Switch to another frame? => Clear column */
734 if (pinfo->fd->num != gbl_old_frame_num) {
735 col_clear(pinfo->cinfo, COL_INFO);
736 gbl_pdu_counter = 0;
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));
744 if (tree) {
745 /* we are being asked for details */
746 unsigned int offset;
747 proto_item *ti;
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));
753 offset = 9;
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
767 static guint
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
778 static int
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. */
783 return 0;
786 if (tvb_memeql(tvb, 0, etch_magic, 4) == -1) {
787 /* Not an etch packet. */
788 return 0;
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);
799 return 1;
802 static void
803 etch_dissector_init(void)
805 gbl_pdu_counter = 0;
806 gbl_old_frame_num = 0xFFFFFFFF;
809 void proto_register_etch(void)
811 module_t *etch_module;
813 static hf_register_info hf[] = {
814 {&hf_etch_sig,
815 {"Etch Signature", "etch.signature",
816 FT_UINT32, BASE_HEX,
817 NULL, 0x0,
818 NULL, HFILL}
820 {&hf_etch_length,
821 {"Etch Length", "etch.msglength",
822 FT_UINT64, BASE_DEC,
823 NULL, 0x0,
824 NULL, HFILL}
826 {&hf_etch_dim,
827 {"Etch Dim", "etch.dim",
828 FT_UINT8, BASE_DEC,
829 NULL, 0x0,
830 NULL, HFILL}
832 {&hf_etch_version,
833 {"Etch Version", "etch.version",
834 FT_UINT8, BASE_DEC,
835 NULL, 0x0,
836 NULL, HFILL}
838 #if 0
839 {&hf_etch_typecode,
840 {"Etch TypeCode", "etch.typecode",
841 FT_STRING, BASE_NONE, /* FT_INT8 */
842 NULL, 0x0,
843 NULL, HFILL}
845 #endif
846 {&hf_etch_value,
847 {"Etch Value", "etch.value",
848 FT_UINT64, BASE_DEC,
849 NULL, 0x0,
850 NULL, HFILL}
852 {&hf_etch_bytes,
853 {"Etch Bytes", "etch.bytes",
854 FT_BYTES, BASE_NONE,
855 NULL, 0x0,
856 NULL, HFILL}
858 {&hf_etch_byte,
859 {"Etch Byte", "etch.byte",
860 FT_INT8, BASE_DEC,
861 NULL, 0x0,
862 NULL, HFILL}
864 {&hf_etch_short,
865 {"Etch Short", "etch.short",
866 FT_INT16, BASE_DEC,
867 NULL, 0x0,
868 NULL, HFILL}
870 {&hf_etch_int,
871 {"Etch Int", "etch.int",
872 FT_INT32, BASE_DEC,
873 NULL, 0x0,
874 NULL, HFILL}
876 {&hf_etch_long,
877 {"Etch Long", "etch.long",
878 FT_INT64, BASE_DEC,
879 NULL, 0x0,
880 NULL, HFILL}
882 {&hf_etch_float,
883 {"Etch Float", "etch.float",
884 FT_FLOAT, BASE_NONE,
885 NULL, 0x0,
886 NULL, HFILL}
888 {&hf_etch_double,
889 {"Etch Double", "etch.double",
890 FT_DOUBLE, BASE_NONE,
891 NULL, 0x0,
892 NULL, HFILL}
894 {&hf_etch_keyvalue,
895 {"Etch keyValue", "etch.keyvalue",
896 FT_NONE, BASE_NONE,
897 NULL, 0x0,
898 NULL, HFILL}
900 #if 0
901 {&hf_etch_key,
902 {"Etch key", "etch.key",
903 FT_BYTES, BASE_NONE,
904 NULL, 0x0,
905 NULL, HFILL}
907 #endif
908 {&hf_etch_symbol,
909 {"Etch symbol", "etch.symbol",
910 FT_UINT32, BASE_HEX,
911 NULL, 0x0,
912 NULL, HFILL}
914 {&hf_etch_struct,
915 {"Etch Struct", "etch.struct",
916 FT_BYTES, BASE_NONE,
917 NULL, 0x0,
918 NULL, HFILL}
920 {&hf_etch_string,
921 {"Etch String", "etch.string",
922 FT_STRING, BASE_NONE,
923 NULL, 0x0,
924 NULL, HFILL}
926 {&hf_etch_keyname,
927 {"Etch key", "etch.keyname",
928 FT_NONE, BASE_NONE,
929 NULL, 0x0,
930 NULL, HFILL}
932 {&hf_etch_valuename,
933 {"Etch value", "etch.valuename",
934 FT_NONE, BASE_NONE,
935 NULL, 0x0,
936 NULL, HFILL}
940 /* Setup protocol subtree array */
941 static gint *ett[] = {
942 &ett_etch,
943 &ett_etch_struct,
944 &ett_etch_keyvalue,
945 &ett_etch_key,
946 &ett_etch_value,
949 proto_etch = proto_register_protocol("Apache Etch Protocol", /* name */
950 "Etch", /* short name */
951 "etch" /* abbrev */
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",
968 &gbl_keytab_folder);
969 prefs_register_uint_preference(etch_module, "tcp.port",
970 "Etch TCP Port",
971 "Etch TCP port",
973 &gbl_etch_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
1010 * Local variables:
1011 * c-basic-offset: 2
1012 * tab-width: 8
1013 * indent-tabs-mode: nil
1014 * End:
1016 * vi: set shiftwidth=2 tabstop=8 expandtab:
1017 * :indentSize=2:tabSize=8:noTabs=true: