/* packet-etch.c * * Copyright (c) 2010, Holger Grandy, BMW Car IT GmbH (holger.grandy@bmw-carit.de) * * Apache Etch Protocol dissector * http://incubator.apache.org/etch/ * * This dissector reads configuration files (generated by Etch IDL compiler). * Configuration file directory path is given in dissector options. * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include void proto_register_etch(void); void proto_reg_handoff_etch(void); /* * maximum numbers for symbols from config files */ #define ETCH_MAX_SYMBOL_LENGTH "256" /* * Magic Number for Etch */ static const guint8 etch_magic[] = { 0xde, 0xad, 0xbe, 0xef }; /* * Typecodes in the Etch protocol, representing the field types */ #define ETCH_TC_NULL 0x80 #define ETCH_TC_NONE 0x81 #define ETCH_TC_BOOLEAN_FALSE 0x82 #define ETCH_TC_BOOLEAN_TRUE 0x83 #define ETCH_TC_BYTE 0x84 #define ETCH_TC_SHORT 0x85 #define ETCH_TC_INT 0x86 #define ETCH_TC_LONG 0x87 #define ETCH_TC_FLOAT 0x88 #define ETCH_TC_DOUBLE 0x89 #define ETCH_TC_BYTES 0x8B #define ETCH_TC_ARRAY 0x91 #define ETCH_TC_EMPTY_STRING 0x92 #define ETCH_TC_STRING 0x93 #define ETCH_TC_STRUCT 0x94 #define ETCH_TC_CUSTOM 0x95 #define ETCH_TC_ANY 0x96 #define ETCH_TC_MIN_TINY_INT 0xC0 #define ETCH_TC_MAX_TINY_INT 0x7F /***************************************************************************/ /* Variables */ /* * String representation of all Type Codes */ static const value_string tc_lookup_table[] = { { ETCH_TC_NULL, "Etch TypeCode: NULL"}, { ETCH_TC_NONE, "Etch TypeCode: NONE"}, { ETCH_TC_BOOLEAN_FALSE, "Etch TypeCode: BOOLEAN_FALSE" }, { ETCH_TC_BOOLEAN_TRUE, "Etch TypeCode: BOOLEAN_TRUE"}, { ETCH_TC_BYTE, "Etch TypeCode: BYTE"}, { ETCH_TC_SHORT, "Etch TypeCode: SHORT"}, { ETCH_TC_INT, "Etch TypeCode: INT"}, { ETCH_TC_LONG, "Etch TypeCode: LONG"}, { ETCH_TC_FLOAT, "Etch TypeCode: FLOAT"}, { ETCH_TC_DOUBLE, "Etch TypeCode: DOUBLE"}, { ETCH_TC_BYTES, "Etch TypeCode: BYTES"}, { ETCH_TC_ARRAY, "Etch TypeCode: ARRAY"}, { ETCH_TC_EMPTY_STRING, "Etch TypeCode: EMPTY_STRING"}, { ETCH_TC_STRING, "Etch TypeCode: STRING"}, { ETCH_TC_STRUCT, "Etch TypeCode: STRUCT"}, { ETCH_TC_CUSTOM, "Etch TypeCode: CUSTOM"}, { ETCH_TC_ANY, "Etch TypeCode: ANY"}, { 0, NULL} }; /* * Wireshark internal fields */ static int proto_etch = -1; static gint ett_etch = -1; static gint ett_etch_struct = -1; static gint ett_etch_keyvalue = -1; static gint ett_etch_key = -1; static gint ett_etch_value = -1; static int hf_etch_sig = -1; static int hf_etch_length = -1; static int hf_etch_version = -1; static int hf_etch_typecode = -1; static int hf_etch_value = -1; static int hf_etch_bytes = -1; static int hf_etch_byte = -1; static int hf_etch_short = -1; static int hf_etch_int = -1; static int hf_etch_long = -1; static int hf_etch_float = -1; static int hf_etch_double = -1; /* static int hf_etch_key = -1; */ static int hf_etch_valuename = -1; static int hf_etch_keyname = -1; static int hf_etch_string = -1; static int hf_etch_keyvalue = -1; static int hf_etch_struct = -1; static int hf_etch_dim = -1; static int hf_etch_symbol = -1; static dissector_handle_t etch_handle; /* * internal fields/defines for dissector */ static const char *gbl_keytab_folder = ""; static guint gbl_etch_port = 0; static char *gbl_current_keytab_folder = NULL; static int gbl_pdu_counter; static guint32 gbl_old_frame_num; static wmem_strbuf_t *gbl_symbol_buffer = NULL; static gboolean gbl_have_symbol = FALSE; /***************************************************************************/ /* Methods */ /* * forward declared dissector methods */ static void read_key_value(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree); static void read_struct(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree, int add_type_field); static int read_value(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree, int asWhat); /************************************************************************ * Symbol value-string functions * Essentially: Build a value_string_ext at runtime: * a. Upon startup & whenever symbol folder changed: Read from file(s) * and add all hash/symbol pairs to a GArray; * b. When file reads complete, sort the GArray and then create a * value_string_ext from the array for use by try_val_to_str_ext & friends. * (Code based upon code in packet-diameter.c) */ static GArray *gbl_symbols_array = NULL; static value_string_ext *gbl_symbols_vs_ext = NULL; static void gbl_symbols_new(void) { DISSECTOR_ASSERT(gbl_symbols_array == NULL); gbl_symbols_array = g_array_new(TRUE, TRUE, sizeof(value_string)); } static void gbl_symbols_free(void) { value_string_ext_free(gbl_symbols_vs_ext); gbl_symbols_vs_ext = NULL; if (gbl_symbols_array != NULL) { value_string *vs_p; guint i; vs_p = (value_string *)(void *)gbl_symbols_array->data; for (i=0; ilen; i++) { g_free((gchar *)vs_p[i].strptr); } g_array_free(gbl_symbols_array, TRUE); gbl_symbols_array = NULL; } } static void gbl_symbols_array_append(guint32 hash, gchar *symbol) { value_string vs = {hash, symbol}; DISSECTOR_ASSERT(gbl_symbols_array != NULL); g_array_append_val(gbl_symbols_array, vs); } static gint gbl_symbols_compare_vs(gconstpointer a, gconstpointer b) { const value_string *vsa = (const value_string *)a; const value_string *vsb = (const value_string *)b; if(vsa->value > vsb->value) return 1; if(vsa->value < vsb->value) return -1; return 0; } static void gbl_symbols_vs_ext_new(void) { DISSECTOR_ASSERT(gbl_symbols_vs_ext == NULL); DISSECTOR_ASSERT(gbl_symbols_array != NULL); g_array_sort(gbl_symbols_array, gbl_symbols_compare_vs); gbl_symbols_vs_ext = value_string_ext_new((value_string *)(void *)gbl_symbols_array->data, gbl_symbols_array->len+1, "etch-global-symbols" ); } /*********************************************************************************/ /* Aux Functions */ /* * get the length of a given typecode in bytes, -1 if to be derived from message */ static gint32 get_byte_length(guint8 typecode) { switch (typecode) { case ETCH_TC_NULL: case ETCH_TC_NONE: case ETCH_TC_BOOLEAN_FALSE: case ETCH_TC_BOOLEAN_TRUE: case ETCH_TC_EMPTY_STRING: case ETCH_TC_MIN_TINY_INT: case ETCH_TC_MAX_TINY_INT: return 0; break; case ETCH_TC_BYTE: return 1; break; case ETCH_TC_SHORT: return 2; break; case ETCH_TC_INT: case ETCH_TC_FLOAT: return 4; break; case ETCH_TC_LONG: case ETCH_TC_DOUBLE: return 8; break; case ETCH_TC_BYTES: case ETCH_TC_ARRAY: case ETCH_TC_STRING: case ETCH_TC_STRUCT: case ETCH_TC_CUSTOM: case ETCH_TC_ANY: return -1; break; default: return 0; break; } } /* * add all etch symbols from file to our symbol cache */ static void add_symbols_of_file(const char *filename) { FILE *pFile; pFile = ws_fopen(filename, "r"); if (pFile != NULL) { char line[256]; while (fgets(line, sizeof line, pFile) != NULL) { unsigned int hash; size_t length, pos; length = strlen(line); /* Must at least have a hash, else skip line */ if (length < 10) continue; pos = length - 1; while (pos > 0 && (line[pos] == 0xD || line[pos] == 0xA)) { pos--; } line[pos + 1] = '\0'; /* Parse the Hash */ if (sscanf(&line[0], "%x", &hash) != 1) continue; /* didn't find a valid hex value at the beginning of the line */ /* And read the symbol */ pos = strcspn(line, ","); if ((line[pos] != '\0') && (line[pos+1] !='\0')) /* require at least 1 char in symbol */ gbl_symbols_array_append(hash, g_strdup_printf("%." ETCH_MAX_SYMBOL_LENGTH "s", &line[pos+1])); } fclose(pFile); } } /* * add all etch symbol from directory to our symbol cache */ static void read_hashed_symbols_from_dir(const char *dirname) { WS_DIR *dir; WS_DIRENT *file; const char *name; char *filename; GError *err_p = NULL; if(gbl_current_keytab_folder != NULL) { g_free(gbl_current_keytab_folder); gbl_current_keytab_folder = NULL; } gbl_symbols_free(); if ((dirname == NULL) || (dirname[0] == '\0')) return; if ((dir = ws_dir_open(dirname, 0, &err_p)) != NULL) { gbl_symbols_new(); gbl_current_keytab_folder = g_strdup(dirname); while ((file = ws_dir_read_name(dir)) != NULL) { name = ws_dir_get_name(file); if (g_str_has_suffix(file, ".ewh")) { filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", dirname, name); add_symbols_of_file(filename); g_free(filename); } } ws_dir_close(dir); gbl_symbols_vs_ext_new(); }else{ report_failure("%s", err_p->message); g_error_free(err_p); } } /***********************************************************************************/ /* Etch Protocol Functions */ /* * read a type flag from tvb and add it to tree */ static guint8 read_type(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree) { guint32 type_code; type_code = tvb_get_guint8(tvb, *offset); proto_tree_add_item(etch_tree, hf_etch_typecode, tvb, *offset, 1, ENC_BIG_ENDIAN); (*offset)++; return type_code; } /* * read a array type flag and add it to tree */ static void read_array_type(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree) { guint32 type_code; type_code = tvb_get_guint8(tvb, *offset); read_type(offset, tvb, etch_tree); if (type_code == ETCH_TC_CUSTOM) { read_type(offset, tvb, etch_tree); proto_tree_add_item(etch_tree, hf_etch_value, tvb, *offset, 4, ENC_BIG_ENDIAN); (*offset) += 4; } } /* * read the length of an array and add it to tree */ static guint32 read_length(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree) { guint32 length; int length_of_array_length_type; guint8 tiny; tiny = tvb_get_guint8(tvb, *offset); /* Is this the value already? */ if ( tiny <= ETCH_TC_MAX_TINY_INT || tiny >= ETCH_TC_MIN_TINY_INT) { length = tiny; length_of_array_length_type = 1; } else { guint8 type_code; type_code = read_type(offset, tvb, etch_tree); length_of_array_length_type = get_byte_length(type_code); switch (length_of_array_length_type) { case 1: length = tvb_get_guint8(tvb, *offset); break; case 2: length = tvb_get_ntohs(tvb, *offset); break; case 4: length = tvb_get_ntohl(tvb, *offset); break; default: return 0; /* error! */ } } proto_tree_add_item(etch_tree, hf_etch_length, tvb, *offset, length_of_array_length_type, ENC_BIG_ENDIAN); (*offset) += length_of_array_length_type; if (*offset + length < *offset) { /* overflow case * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8464 */ length = tvb_reported_length_remaining(tvb, *offset); } return length; } /* * read an array from tvb and add it to tree */ static void read_array(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree) { int length; /* array type */ read_type(offset, tvb, etch_tree); /* Array of type: */ read_array_type(offset, tvb, etch_tree); /* Array dim */ proto_tree_add_item(etch_tree, hf_etch_dim, tvb, *offset, 1, ENC_BIG_ENDIAN); (*offset)++; /* Array length */ length = read_length(offset, tvb, etch_tree); for (; length > 0; length--) { read_value(offset, tvb, etch_tree, hf_etch_value); } /* terminaton */ read_type(offset, tvb, etch_tree); } /* * read a sequence of bytes and add them to tree */ static void read_bytes(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree) { int length; read_type(offset, tvb, etch_tree); length = read_length(offset, tvb, etch_tree); proto_tree_add_item(etch_tree, hf_etch_bytes, tvb, *offset, length, ENC_NA); (*offset) += length; } /* * read a string and add it to tree */ static void read_string(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree) { int byteLength; read_type(offset, tvb, etch_tree); byteLength = read_length(offset, tvb, etch_tree); proto_tree_add_item(etch_tree, hf_etch_string, tvb, *offset, byteLength, ENC_ASCII|ENC_NA); (*offset) += byteLength; } /* * read a number and add it to tree */ static void read_number(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree, int asWhat, guint8 type_code) { int byteLength; read_type(offset, tvb, etch_tree); byteLength = get_byte_length(type_code); if (byteLength > 0) { proto_item *ti; const gchar *symbol = NULL; guint32 hash = 0; gbl_symbol_buffer = wmem_strbuf_new_label(wmem_packet_scope()); /* no symbol found yet */ if (byteLength == 4) { hash = tvb_get_ntohl(tvb, *offset); symbol = try_val_to_str_ext(hash, gbl_symbols_vs_ext); if(symbol != NULL) { asWhat = hf_etch_symbol; gbl_have_symbol = TRUE; wmem_strbuf_append_printf(gbl_symbol_buffer,"%s",symbol); } } ti = proto_tree_add_item(etch_tree, asWhat, tvb, *offset, byteLength, ENC_BIG_ENDIAN); *offset += byteLength; if (symbol != NULL) { proto_item_append_text(ti, " (0x%08x) %s", hash, symbol); } } } /* * read a value and add it to tree */ static int read_value(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree, int asWhat) { guint8 type_code; type_code = tvb_get_guint8(tvb, *offset); if (type_code <= ETCH_TC_MAX_TINY_INT || type_code >= ETCH_TC_MIN_TINY_INT) { /* this is the value already */ proto_tree_add_item(etch_tree, asWhat, tvb, *offset, 1, ENC_BIG_ENDIAN); (*offset)++; return type_code; } switch(type_code) { case ETCH_TC_CUSTOM: read_struct(offset, tvb, etch_tree, 1); break; case ETCH_TC_ARRAY: read_array(offset, tvb, etch_tree); break; case ETCH_TC_STRING: read_string(offset, tvb, etch_tree); break; case ETCH_TC_FLOAT: read_number(offset, tvb, etch_tree, hf_etch_float, type_code); break; case ETCH_TC_DOUBLE: read_number(offset, tvb, etch_tree, hf_etch_double, type_code); break; case ETCH_TC_SHORT: read_number(offset, tvb, etch_tree, hf_etch_short, type_code); break; case ETCH_TC_INT: read_number(offset, tvb, etch_tree, hf_etch_int, type_code); break; case ETCH_TC_LONG: read_number(offset, tvb, etch_tree, hf_etch_long, type_code); break; case ETCH_TC_BYTE: read_number(offset, tvb, etch_tree, hf_etch_byte, type_code); break; case ETCH_TC_BYTES: read_bytes(offset, tvb, etch_tree); break; default: read_number(offset, tvb, etch_tree, asWhat, type_code); } return 0; } /* * read a struct and add it to tree */ static void read_struct(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree, int add_type_field) { proto_item *ti; proto_tree *new_tree; int length; int i; ti = proto_tree_add_item(etch_tree, hf_etch_struct, tvb, *offset, tvb_length(tvb) - *offset, ENC_NA); new_tree = proto_item_add_subtree(ti, ett_etch_struct); if (add_type_field) { read_type(offset, tvb, new_tree); } /* struct type as hash */ read_value(offset, tvb, new_tree, hf_etch_value); /* struct length */ length = read_value(offset, tvb, new_tree, hf_etch_length); for (i = 0; i < length; i++) { read_key_value(offset, tvb, new_tree); } /* termination */ read_type(offset, tvb, new_tree); } /* * read a key value pair and add it to tree */ static void read_key_value(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree) { proto_tree *new_tree; proto_tree *new_tree_bck; proto_item *ti, *parent_ti; gbl_have_symbol = FALSE; parent_ti = proto_tree_add_item(etch_tree, hf_etch_keyvalue, tvb, *offset, 1, ENC_NA); new_tree_bck = new_tree = proto_item_add_subtree(parent_ti, ett_etch_keyvalue); ti = proto_tree_add_item(new_tree, hf_etch_keyname, tvb, *offset, 0, ENC_NA); new_tree = proto_item_add_subtree(ti, ett_etch_key); read_value(offset, tvb, new_tree, hf_etch_value); /* append the symbol of the key */ if(gbl_have_symbol == TRUE){ proto_item_append_text(parent_ti, " ("); proto_item_append_text(parent_ti, "%s", wmem_strbuf_get_str(gbl_symbol_buffer)); proto_item_append_text(parent_ti, ")"); } ti = proto_tree_add_item(new_tree_bck, hf_etch_valuename, tvb, *offset, 0, ENC_NA); new_tree = proto_item_add_subtree(ti, ett_etch_value); read_value(offset, tvb, new_tree, hf_etch_value); } /*************************************************************************/ /* * Preparse the message for the info column */ static wmem_strbuf_t* get_column_info(tvbuff_t *tvb) { int byte_length; guint8 type_code; wmem_strbuf_t *result_buf; int my_offset = 0; /* We've a full PDU: 8 bytes + pdu_packetlen bytes */ result_buf = wmem_strbuf_new_label(wmem_packet_scope()); my_offset += (4 + 4 + 1); /* skip Magic, Length, Version */ type_code = tvb_get_guint8(tvb, my_offset); byte_length = get_byte_length(type_code); my_offset++; if (byte_length == 4) { const gchar *symbol; guint32 hash; hash = tvb_get_ntohl(tvb, my_offset); symbol = try_val_to_str_ext(hash, gbl_symbols_vs_ext); if (symbol != NULL) { wmem_strbuf_append_printf(result_buf, "%s()", symbol); } } return result_buf; } /****************************************************************************************************/ /* * main dissector function for an etch message */ static int dissect_etch_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { /* We've a full PDU: 8 bytes + pdu_packetlen bytes */ wmem_strbuf_t *colInfo = NULL; if (pinfo->cinfo || tree) { colInfo = get_column_info(tvb); /* get current symbol */ } if (pinfo->cinfo) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "ETCH"); gbl_pdu_counter++; /* Switch to another frame? => Clear column */ if (pinfo->fd->num != gbl_old_frame_num) { col_clear(pinfo->cinfo, COL_INFO); gbl_pdu_counter = 0; } gbl_old_frame_num = pinfo->fd->num; col_set_writable(pinfo->cinfo, TRUE); col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", wmem_strbuf_get_str(colInfo)); } if (tree) { /* we are being asked for details */ unsigned int offset; proto_item *ti; proto_tree *etch_tree; ti = proto_tree_add_protocol_format(tree, proto_etch, tvb, 0, -1, "ETCH Protocol: %s", wmem_strbuf_get_str(colInfo)); offset = 9; etch_tree = proto_item_add_subtree(ti, ett_etch); proto_tree_add_item(etch_tree, hf_etch_sig, tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(etch_tree, hf_etch_length, tvb, 4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(etch_tree, hf_etch_version, tvb, 8, 1, ENC_BIG_ENDIAN); read_struct(&offset, tvb, etch_tree, 0); } return tvb_length(tvb); } /* * determine PDU length of protocol etch */ static guint get_etch_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) { /* length is at offset 4. we add magic bytes length + length size */ return tvb_get_ntohl(tvb, offset + 4) + 8; } /* * main dissector function for the etch protocol */ static int dissect_etch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { if (tvb_length(tvb) < 4) { /* Too small for an etch packet. */ return 0; } if (tvb_memeql(tvb, 0, etch_magic, 4) == -1) { /* Not an etch packet. */ return 0; } tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 8, get_etch_message_len, dissect_etch_message, data); if (gbl_pdu_counter > 0) { col_set_writable(pinfo->cinfo, TRUE); col_prepend_fstr(pinfo->cinfo, COL_INFO, "[%d] ", gbl_pdu_counter + 1); } return 1; } static void etch_dissector_init(void) { gbl_pdu_counter = 0; gbl_old_frame_num = 0xFFFFFFFF; } void proto_register_etch(void) { module_t *etch_module; static hf_register_info hf[] = { {&hf_etch_sig, {"Etch Signature", "etch.signature", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} }, {&hf_etch_length, {"Etch Length", "etch.msglength", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_etch_dim, {"Etch Dim", "etch.dim", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_etch_version, {"Etch Version", "etch.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_etch_typecode, {"Etch TypeCode", "etch.typecode", FT_UINT8, BASE_HEX, VALS(tc_lookup_table), 0x0, NULL, HFILL} }, {&hf_etch_value, {"Etch Value", "etch.value", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_etch_bytes, {"Etch Bytes", "etch.bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} }, {&hf_etch_byte, {"Etch Byte", "etch.byte", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_etch_short, {"Etch Short", "etch.short", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_etch_int, {"Etch Int", "etch.int", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_etch_long, {"Etch Long", "etch.long", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_etch_float, {"Etch Float", "etch.float", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL} }, {&hf_etch_double, {"Etch Double", "etch.double", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL} }, {&hf_etch_keyvalue, {"Etch keyValue", "etch.keyvalue", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL} }, #if 0 {&hf_etch_key, {"Etch key", "etch.key", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} }, #endif {&hf_etch_symbol, {"Etch symbol", "etch.symbol", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} }, {&hf_etch_struct, {"Etch Struct", "etch.struct", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} }, {&hf_etch_string, {"Etch String", "etch.string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, {&hf_etch_keyname, {"Etch key", "etch.keyname", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL} }, {&hf_etch_valuename, {"Etch value", "etch.valuename", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL} }, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_etch, &ett_etch_struct, &ett_etch_keyvalue, &ett_etch_key, &ett_etch_value, }; proto_etch = proto_register_protocol("Apache Etch Protocol", /* name */ "Etch", /* short name */ "etch" /* abbrev */ ); proto_register_field_array(proto_etch, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); etch_handle = new_register_dissector("etch", dissect_etch, proto_etch); register_init_routine(&etch_dissector_init); etch_module = prefs_register_protocol(proto_etch, proto_reg_handoff_etch); prefs_register_directory_preference(etch_module, "file", "Apache Etch symbol folder", "Place the hash/symbol files " "(generated by the Apache Etch compiler) " "ending with .ewh here", &gbl_keytab_folder); prefs_register_uint_preference(etch_module, "tcp.port", "Etch TCP Port", "Etch TCP port", 10, &gbl_etch_port); } void proto_reg_handoff_etch(void) { static gboolean etch_prefs_initialized = FALSE; static guint old_etch_port = 0; /* create dissector handle only once */ if(!etch_prefs_initialized) { /* add heuristic dissector for tcp */ heur_dissector_add("tcp", dissect_etch, proto_etch); etch_prefs_initialized = TRUE; } if(old_etch_port != 0 && old_etch_port != gbl_etch_port){ dissector_delete_uint("tcp.port", old_etch_port, etch_handle); } if(gbl_etch_port != 0 && old_etch_port != gbl_etch_port) { dissector_add_uint("tcp.port", gbl_etch_port, etch_handle); } old_etch_port = gbl_etch_port; /* read config folder files, if filename has changed * (while protecting strcmp() from NULLs) */ if((gbl_keytab_folder == NULL) || (gbl_current_keytab_folder == NULL) || (strcmp(gbl_keytab_folder, gbl_current_keytab_folder) != 0)) { read_hashed_symbols_from_dir(gbl_keytab_folder); } } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 2 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=2 tabstop=8 expandtab: * :indentSize=2:tabSize=8:noTabs=true: */