wireshark/epan/dissectors/packet-etch.c

979 lines
25 KiB
C

/* 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 <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/prefs.h>
#include <wsutil/file_util.h>
#include <wsutil/report_message.h>
#include "packet-tcp.h"
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 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; i<gbl_symbols_array->len; 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("etch: %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://gitlab.com/wireshark/wireshark/-/issues/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_captured_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, " (%s)", wmem_strbuf_get_str(gbl_symbol_buffer));
}
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->num != gbl_old_frame_num) {
col_clear(pinfo->cinfo, COL_INFO);
gbl_pdu_counter = 0;
}
gbl_old_frame_num = pinfo->num;
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_captured_length(tvb);
}
/*
* determine PDU length of protocol etch
*/
static guint
get_etch_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
int offset, void *data _U_)
{
/* 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_captured_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_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 = 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);
}
void proto_reg_handoff_etch(void)
{
static gboolean etch_prefs_initialized = FALSE;
/* create dissector handle only once */
if(!etch_prefs_initialized) {
/* add heuristic dissector for tcp */
heur_dissector_add("tcp", dissect_etch, "Etch over TCP", "etch_tcp", proto_etch, HEURISTIC_ENABLE);
dissector_add_for_decode_as_with_preference("tcp.port", etch_handle);
etch_prefs_initialized = TRUE;
}
/* 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 - https://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:
*/