Use dynamically created value_string_ext to store hash/symbol value_strings;

Also: minor code reformatting and re-arrangement.

svn path=/trunk/; revision=34569
This commit is contained in:
Bill Meier 2010-10-19 14:31:05 +00:00
parent a3bf744a0f
commit 7ae3e56828
1 changed files with 166 additions and 139 deletions

View File

@ -52,7 +52,6 @@
* maximum numbers for symbols from config files
*/
#define ETCH_MAX_SYMBOL_LENGTH "256"
#define ETCH_MAX_SYMBOLS 1000
/*
* Magic Number for Etch
@ -143,17 +142,15 @@ static int hf_etch_symbol = 0;
* 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_symbols_count = 0;
static value_string* gbl_symbols = NULL;
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 emem_strbuf_t* gbl_symbol_buffer = NULL;
static gboolean gbl_have_symbol = FALSE;
static emem_strbuf_t *gbl_symbol_buffer = NULL;
static gboolean gbl_have_symbol = FALSE;
/***************************************************************************/
/* Methods */
@ -161,14 +158,80 @@ static gboolean gbl_have_symbol = FALSE;
/*
* 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,
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);
void proto_reg_handoff_etch(void);
/************************************************************************
* 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 match_strval_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) {
g_assert(gbl_symbols_array == NULL);
gbl_symbols_array = g_array_new(TRUE, TRUE, sizeof(value_string));
}
static void
gbl_symbols_free(void) {
g_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 *)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(int hash, gchar *symbol) {
value_string vs = {hash, symbol};
g_assert(gbl_symbols_array != NULL);
g_array_append_val(gbl_symbols_array, vs);
}
static gint
gbl_symbols_compare_vs(gconstpointer a, gconstpointer b)
{
value_string *vsa = (value_string *)a;
value_string *vsb = (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) {
g_assert(gbl_symbols_vs_ext == NULL);
g_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 *)gbl_symbols_array->data,
gbl_symbols_array->len+1,
"etch-global-symbols" );
}
/*********************************************************************************/
/* Aux Functions */
@ -180,15 +243,12 @@ get_byte_length(guint8 typecode)
{
switch (typecode) {
case ETCH_TC_NULL:
return 0;
break;
case ETCH_TC_NONE:
return 0;
break;
case ETCH_TC_BOOLEAN_FALSE:
return 0;
break;
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:
@ -198,58 +258,24 @@ get_byte_length(guint8 typecode)
return 2;
break;
case ETCH_TC_INT:
return 4;
break;
case ETCH_TC_LONG:
return 8;
break;
case ETCH_TC_FLOAT:
return 4;
break;
case ETCH_TC_LONG:
case ETCH_TC_DOUBLE:
return 8;
break;
case ETCH_TC_BYTES:
return -1;
break;
case ETCH_TC_ARRAY:
return -1;
break;
case ETCH_TC_EMPTY_STRING:
return 0;
break;
case ETCH_TC_STRING:
return -1;
break;
case ETCH_TC_STRUCT:
return -1;
break;
case ETCH_TC_CUSTOM:
return -1;
break;
case ETCH_TC_ANY:
return -1;
break;
case ETCH_TC_MIN_TINY_INT:
return 0;
default:
return 0;
break;
case ETCH_TC_MAX_TINY_INT:
return 0;
break;
}
return 0;
}
/*
* add a etch symbol to our symbol cache
*/
static void
add_symbol(int hash, const gchar *symbol)
{
if (gbl_symbols_count < ETCH_MAX_SYMBOLS - 1) {
gbl_symbols[gbl_symbols_count].value = hash;
gbl_symbols[gbl_symbols_count].strptr = g_strdup_printf("%." ETCH_MAX_SYMBOL_LENGTH "s", symbol);
gbl_symbols_count++;
}
}
@ -287,7 +313,8 @@ add_symbols_of_file(const char *filename)
/* And read the symbol */
pos = strcspn(line, ",");
if ((line[pos] != '\0') && (line[pos+1] !='\0')) /* require at least 1 char in symbol */
add_symbol(hash, &line[pos+1]);
gbl_symbols_array_append(hash,
g_strdup_printf("%." ETCH_MAX_SYMBOL_LENGTH "s", &line[pos+1]));
}
fclose(pFile);
}
@ -299,30 +326,25 @@ add_symbols_of_file(const char *filename)
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;
int i;
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;
}
for(i = 0; i < gbl_symbols_count; i++){
value_string tmp = {0, NULL};
g_free((gchar *)gbl_symbols[i].strptr);
gbl_symbols[i] = tmp;
}
/* Reset all symbols */
gbl_symbols_count = 0;
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);
@ -336,6 +358,7 @@ read_hashed_symbols_from_dir(const char *dirname)
}
}
ws_dir_close(dir);
gbl_symbols_vs_ext_new();
}else{
report_failure("%s", err_p->message);
g_error_free(err_p);
@ -343,17 +366,17 @@ read_hashed_symbols_from_dir(const char *dirname)
}
/***********************************************************************************/
/* Etch Protocol Functions*/
/* 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)
read_type(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
{
guint32 type_code;
const gchar* type_as_string;
guint32 type_code;
const gchar *type_as_string;
type_code = tvb_get_guint8(tvb, *offset);
type_as_string = val_to_str(type_code, tc_lookup_table, "Etch TypeCode: 0x%02x");
@ -366,14 +389,14 @@ read_type(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
* 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)
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 == (guint8) ETCH_TC_CUSTOM) {
if (type_code == ETCH_TC_CUSTOM) {
type_code = read_type(offset, tvb, etch_tree);
proto_tree_add_item(etch_tree, hf_etch_value, tvb, *offset, 4,
ENC_BIG_ENDIAN);
@ -386,7 +409,7 @@ read_array_type(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
* 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)
read_length(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
{
guint32 length;
int length_of_array_length_type;
@ -394,7 +417,7 @@ read_length(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
tiny = tvb_get_guint8(tvb, *offset);
/* Is this the value already?*/
/* Is this the value already? */
if ( tiny <= ETCH_TC_MAX_TINY_INT
|| tiny >= ETCH_TC_MIN_TINY_INT) {
length = tiny;
@ -406,16 +429,16 @@ read_length(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
switch (length_of_array_length_type) {
case 1:
length = (guint32) tvb_get_guint8(tvb, *offset);
length = tvb_get_guint8(tvb, *offset);
break;
case 2:
length = (guint32) tvb_get_ntohs(tvb, *offset);
length = tvb_get_ntohs(tvb, *offset);
break;
case 4:
length = (guint32) tvb_get_ntohl(tvb, *offset);
length = tvb_get_ntohl(tvb, *offset);
break;
default:
return 0; /* error!*/
return 0; /* error! */
}
}
proto_tree_add_item(etch_tree, hf_etch_length, tvb, *offset,
@ -429,27 +452,27 @@ read_length(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
* read an array from tvb and add it to tree
*/
static void
read_array(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
read_array(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
{
int length;
/* array type*/
/* array type */
read_type(offset, tvb, etch_tree);
/* Array of type:*/
/* Array of type: */
read_array_type(offset, tvb, etch_tree);
/* Array dim*/
/* Array dim */
proto_tree_add_item(etch_tree, hf_etch_dim, tvb, *offset, 1, ENC_NA);
(*offset)++;
/* Array length*/
/* Array length */
length = read_length(offset, tvb, etch_tree);
for (; length > 0; length--) {
read_value(offset, tvb, etch_tree, hf_etch_value);
}
/* terminaton*/
/* terminaton */
read_type(offset, tvb, etch_tree);
}
@ -458,7 +481,7 @@ read_array(unsigned int *offset, tvbuff_t * tvb, proto_tree * 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)
read_bytes(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
{
int length;
read_type(offset, tvb, etch_tree);
@ -472,7 +495,7 @@ read_bytes(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
* read a string and add it to tree
*/
static void
read_string(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
read_string(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
{
int byteLength;
read_type(offset, tvb, etch_tree);
@ -488,7 +511,7 @@ read_string(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
* read a number and add it to tree
*/
static void
read_number(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree,
read_number(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree,
int asWhat, guint8 type_code)
{
int byteLength;
@ -496,14 +519,14 @@ read_number(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree,
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;
proto_item *ti;
const gchar *symbol = NULL;
guint32 hash = 0;
gbl_symbol_buffer = ep_strbuf_new_label(""); /* no symbol found yet */
if (byteLength == 4) {
hash = tvb_get_ntohl(tvb, *offset);
symbol = match_strval((const guint32)hash, gbl_symbols);
symbol = match_strval_ext(hash, gbl_symbols_vs_ext);
if(symbol != NULL) {
asWhat = hf_etch_symbol;
gbl_have_symbol = TRUE;
@ -523,7 +546,7 @@ read_number(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree,
* read a value and add it to tree
*/
static int
read_value(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree,
read_value(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree,
int asWhat)
{
guint8 type_code;
@ -535,30 +558,40 @@ read_value(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree,
proto_tree_add_item(etch_tree, asWhat, tvb, *offset, 1, ENC_BIG_ENDIAN);
(*offset)++;
return type_code;
} else if (type_code == ETCH_TC_CUSTOM) {
}
switch(type_code) {
case ETCH_TC_CUSTOM:
read_struct(offset, tvb, etch_tree, 1);
return 0;
} else if (type_code == ETCH_TC_ARRAY) {
break;
case ETCH_TC_ARRAY:
read_array(offset, tvb, etch_tree);
return 0;
} else if (type_code == ETCH_TC_STRING) {
break;
case ETCH_TC_STRING:
read_string(offset, tvb, etch_tree);
return 0;
} else if (type_code == ETCH_TC_FLOAT) {
break;
case ETCH_TC_FLOAT:
read_number(offset, tvb, etch_tree, hf_etch_float, type_code);
} else if (type_code == ETCH_TC_DOUBLE) {
break;
case ETCH_TC_DOUBLE:
read_number(offset, tvb, etch_tree, hf_etch_double, type_code);
} else if (type_code == ETCH_TC_SHORT) {
break;
case ETCH_TC_SHORT:
read_number(offset, tvb, etch_tree, hf_etch_short, type_code);
} else if (type_code == ETCH_TC_INT) {
break;
case ETCH_TC_INT:
read_number(offset, tvb, etch_tree, hf_etch_int, type_code);
} else if (type_code == ETCH_TC_LONG) {
break;
case ETCH_TC_LONG:
read_number(offset, tvb, etch_tree, hf_etch_long, type_code);
} else if (type_code == ETCH_TC_BYTE) {
break;
case ETCH_TC_BYTE:
read_number(offset, tvb, etch_tree, hf_etch_byte, type_code);
} else if (type_code == ETCH_TC_BYTES) {
break;
case ETCH_TC_BYTES:
read_bytes(offset, tvb, etch_tree);
} else {
break;
default:
read_number(offset, tvb, etch_tree, asWhat, type_code);
}
return 0;
@ -568,7 +601,7 @@ read_value(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree,
* read a struct and add it to tree
*/
static void
read_struct(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree,
read_struct(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree,
int add_type_field)
{
proto_item *ti;
@ -583,10 +616,10 @@ read_struct(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree,
if (add_type_field) {
read_type(offset, tvb, new_tree);
}
/* struct type as hash*/
/* struct type as hash */
read_value(offset, tvb, new_tree, hf_etch_value);
/* struct length */
/* struct length */
length = read_value(offset, tvb, new_tree, hf_etch_length);
for (i = 0; i < length; i++) {
@ -601,7 +634,7 @@ read_struct(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_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)
read_key_value(unsigned int *offset, tvbuff_t *tvb, proto_tree *etch_tree)
{
proto_tree *new_tree;
proto_tree *new_tree_bck;
@ -633,17 +666,17 @@ read_key_value(unsigned int *offset, tvbuff_t * tvb, proto_tree * etch_tree)
read_value(offset, tvb, new_tree, hf_etch_value);
}
/****************************************************************************************************/
/*************************************************************************/
/*
* Preparse the message for the info column
*/
static emem_strbuf_t*
get_column_info(tvbuff_t * tvb)
get_column_info(tvbuff_t *tvb)
{
int byte_length;
guint8 type_code;
emem_strbuf_t* result_buf;
int my_offset = 0;
guint8 type_code;
emem_strbuf_t *result_buf;
int my_offset = 0;
/* We've a full PDU: 8 bytes + pdu_packetlen bytes */
result_buf = ep_strbuf_new_label("");
@ -655,10 +688,10 @@ get_column_info(tvbuff_t * tvb)
my_offset++;
if (byte_length == 4) {
const gchar* symbol;
guint32 hash;
const gchar *symbol;
guint32 hash;
hash = tvb_get_ntohl(tvb, my_offset);
symbol = val_to_str((const guint32) hash, gbl_symbols, "%x");
symbol = match_strval_ext(hash, gbl_symbols_vs_ext);
if (symbol != NULL) {
ep_strbuf_append_printf(result_buf, "%s()", symbol);
}
@ -673,10 +706,10 @@ get_column_info(tvbuff_t * tvb)
* main dissector function for an etch message
*/
static void
dissect_etch_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
dissect_etch_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* We've a full PDU: 8 bytes + pdu_packetlen bytes */
emem_strbuf_t* colInfo = NULL;
emem_strbuf_t *colInfo = NULL;
if (pinfo->cinfo || tree) {
colInfo = get_column_info(tvb); /* get current symbol */
@ -720,7 +753,7 @@ dissect_etch_message(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
* determine PDU length of protocol etch
*/
static guint
get_etch_message_len(packet_info * pinfo _U_, tvbuff_t * tvb, int offset)
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;
@ -731,7 +764,7 @@ get_etch_message_len(packet_info * pinfo _U_, tvbuff_t * tvb, int offset)
* main dissector function for the etch protocol
*/
static int
dissect_etch(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
dissect_etch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (tvb_length(tvb) < 4) {
/* Too small for an etch packet. */
@ -764,7 +797,6 @@ etch_dissector_init(void)
void proto_register_etch(void)
{
module_t *etch_module;
int i = 0;
static hf_register_info hf[] = {
{&hf_etch_sig,
@ -793,7 +825,7 @@ void proto_register_etch(void)
},
{&hf_etch_typecode,
{"Etch TypeCode", "etch.typecode",
FT_STRING, BASE_NONE, /* FT_INT8*/
FT_STRING, BASE_NONE, /* FT_INT8 */
NULL, 0x0,
NULL, HFILL}
},
@ -898,16 +930,9 @@ void proto_register_etch(void)
&ett_etch_value,
};
gbl_symbols = (value_string*) g_malloc(ETCH_MAX_SYMBOLS * sizeof(value_string));
for(i = 0; i < ETCH_MAX_SYMBOLS; i++){
value_string tmp = {0, NULL};
gbl_symbols[i] = tmp;
}
proto_etch = proto_register_protocol("Apache Etch Protocol", /* name */
"ETCH", /* short name */
"etch" /* abbrev */
proto_etch = proto_register_protocol("Apache Etch Protocol", /* name */
"ETCH", /* short name */
"etch" /* abbrev */
);
proto_register_field_array(proto_etch, hf, array_length(hf));
@ -921,7 +946,9 @@ void proto_register_etch(void)
prefs_register_string_preference(etch_module, "file",
"Apache Etch symbol folder",
"Place the hash/symbol files (generated by the Apache Etch compiler) ending with .ewh here",
"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",