diff options
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dfilter/semcheck.c | 3 | ||||
-rw-r--r-- | epan/dissectors/packet-diameter.c | 63 | ||||
-rw-r--r-- | epan/libwireshark.def | 2 | ||||
-rw-r--r-- | epan/proto.c | 2 | ||||
-rw-r--r-- | epan/value_string.c | 209 | ||||
-rw-r--r-- | epan/value_string.h | 87 |
6 files changed, 254 insertions, 112 deletions
diff --git a/epan/dfilter/semcheck.c b/epan/dfilter/semcheck.c index 82cde98243..45b6f7127c 100644 --- a/epan/dfilter/semcheck.c +++ b/epan/dfilter/semcheck.c @@ -232,9 +232,8 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s) } else { const value_string *vals = hfinfo->strings; - if (hfinfo->display & BASE_EXT_STRING) - vals = ((value_string_ext *) vals)->vals; + vals = VALUE_STRING_EXT_VS_P((value_string_ext *) vals); while (vals->strptr != NULL) { if (g_ascii_strcasecmp(s, vals->strptr) == 0) { diff --git a/epan/dissectors/packet-diameter.c b/epan/dissectors/packet-diameter.c index 6f55a9d8b1..ee7be3366d 100644 --- a/epan/dissectors/packet-diameter.c +++ b/epan/dissectors/packet-diameter.c @@ -130,8 +130,9 @@ struct _diam_avp_t { void* type_data; }; -#define VND_AVP_VS(v) ((value_string*)(void*)((v)->vs_avps->data)) -#define VND_CMD_VS(v) ((value_string*)(void*)((v)->vs_cmds->data)) +#define VND_AVP_VS(v) ((value_string*)(void*)((v)->vs_avps->data)) +#define VND_AVP_VS_LEN(v) ((v)->vs_avps->len) +#define VND_CMD_VS(v) ((value_string*)(void*)((v)->vs_cmds->data)) typedef struct _diam_dictionary_t { emem_tree_t* avps; @@ -182,9 +183,8 @@ typedef struct _proto_avp_t { static const char* simple_avp(diam_ctx_t*, diam_avp_t*, tvbuff_t*); static const value_string no_vs[] = {{0, NULL} }; -static GArray no_garr = { (void*)no_vs, 1 }; -static value_string_ext no_vs_avps_ext = { (value_string_match_t) match_strval_ext_init, 0, (void*)no_vs}; -static diam_vnd_t unknown_vendor = { 0xffffffff, &no_garr, &no_vs_avps_ext, &no_garr }; +static GArray no_garr = { (void*)no_vs, 0 }; +static diam_vnd_t unknown_vendor = { 0xffffffff, &no_garr, NULL, &no_garr }; static diam_vnd_t no_vnd = { 0, NULL, NULL, NULL }; static diam_avp_t unknown_avp = {0, &unknown_vendor, simple_avp, simple_avp, -1, -1, NULL }; static GArray* all_cmds; @@ -344,28 +344,24 @@ dissect_diameter_eap_payload(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tr static int dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset) { - guint32 code = tvb_get_ntohl(tvb,offset); - guint32 len = tvb_get_ntohl(tvb,offset+4); - guint32 vendor_flag = len & 0x80000000; + guint32 code = tvb_get_ntohl(tvb,offset); + guint32 len = tvb_get_ntohl(tvb,offset+4); + guint32 vendor_flag = len & 0x80000000; guint32 flags_bits_idx = (len & 0xE0000000) >> 29; - guint32 flags_bits = (len & 0xFF000000) >> 24; - guint32 vendorid = vendor_flag ? tvb_get_ntohl(tvb,offset+8) : 0 ; - emem_tree_key_t k[] = { + guint32 flags_bits = (len & 0xFF000000) >> 24; + guint32 vendorid = vendor_flag ? tvb_get_ntohl(tvb,offset+8) : 0 ; + emem_tree_key_t k[] = { {1,&code}, {1,&vendorid}, {0,NULL} }; - diam_avp_t* a = emem_tree_lookup32_array(dictionary.avps,k); + diam_avp_t* a = emem_tree_lookup32_array(dictionary.avps,k); proto_item *pi, *avp_item; proto_tree *avp_tree, *save_tree; tvbuff_t* subtvb; - const diam_vnd_t* vendor; - value_string* vendor_avp_vs; + diam_vnd_t* vendor; const char* code_str; const char* avp_str; -#if 0 - gint i = 0; -#endif len &= 0x00ffffff; if (!a) { @@ -378,24 +374,23 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset) vendor = &no_vnd; } } else { - vendor = a->vendor; + vendor = (diam_vnd_t *)a->vendor; } - if(vendor->vs_avps_ext->vals == NULL){ + if(vendor->vs_avps_ext == NULL) { g_array_sort(vendor->vs_avps, compare_avps); - /* Get dictionary of AVPs matching found vendor */ - vendor_avp_vs = VND_AVP_VS(vendor); - vendor->vs_avps_ext->vals = vendor_avp_vs; + vendor->vs_avps_ext = value_string_ext_new(VND_AVP_VS(vendor), VND_AVP_VS_LEN(vendor)+1, + "diameter_vendor"); #if 0 - Debug code - while(vendor_avp_vs[i].strptr!=NULL){ - g_warning("%u %s",vendor_avp_vs[i].value,vendor_avp_vs[i].strptr); - i++; + { /* Debug code */ + value_string* vendor_avp_vs=VALUE_STRING_EXT_VS_P(vendor->vs_avps_ext); + gint i = 0; + while(vendor_avp_vs[i].strptr!=NULL){ + g_warning("%u %s",vendor_avp_vs[i].value,vendor_avp_vs[i].strptr); + i++; + } } #endif - }else{ - /* Get dictionary of AVPs matching found vendor */ - vendor_avp_vs = VND_AVP_VS(vendor); } /* Add root of tree for this AVP */ @@ -403,7 +398,7 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset) avp_tree = proto_item_add_subtree(avp_item,a->ett); pi = proto_tree_add_item(avp_tree,hf_diameter_avp_code,tvb,offset,4,FALSE); - code_str = val_to_str_ext(code, vendor->vs_avps_ext, "Unknown"); + code_str = val_to_str_ext_const(code, vendor->vs_avps_ext, "Unknown"); proto_item_append_text(pi," %s", code_str); /* Code */ @@ -1230,9 +1225,6 @@ dictionary_load(void) no_vnd.vs_cmds = g_array_new(TRUE,TRUE,sizeof(value_string)); no_vnd.vs_avps = g_array_new(TRUE,TRUE,sizeof(value_string)); - no_vnd.vs_avps_ext = g_malloc0(sizeof(value_string_ext)); - no_vnd.vs_avps_ext->match = (value_string_match_t) match_strval_ext_init; - no_vnd.vs_avps_ext->length = 0; all_cmds = g_array_new(TRUE,TRUE,sizeof(value_string)); @@ -1296,9 +1288,13 @@ dictionary_load(void) vnd->code = v->code; vnd->vs_cmds = g_array_new(TRUE,TRUE,sizeof(value_string)); vnd->vs_avps = g_array_new(TRUE,TRUE,sizeof(value_string)); +#if 0 vnd->vs_avps_ext = g_malloc0(sizeof(value_string_ext)); vnd->vs_avps_ext->match = (value_string_match_t) match_strval_ext_init; + vnd->vs_avps_ext->offset= 0; vnd->vs_avps_ext->length= 0; +#endif + vnd->vs_avps_ext = NULL; pe_tree_insert32(dictionary.vnds,vnd->code,vnd); g_hash_table_insert(vendors,v->name,vnd); } @@ -1331,7 +1327,6 @@ dictionary_load(void) if ((vnd = g_hash_table_lookup(vendors,vend))) { value_string vndvs = {a->code,a->name}; g_array_append_val(vnd->vs_avps,vndvs); - vnd->vs_avps_ext->length++; } else { fprintf(stderr,"Diameter Dictionary: No Vendor: %s",vend); vnd = &unknown_vendor; diff --git a/epan/libwireshark.def b/epan/libwireshark.def index a8f3a0d3e4..2ac377fa31 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -631,7 +631,7 @@ match_strrval match_strrval_idx match_strval match_strval_ext -match_strval_ext_init +_match_strval_ext_init match_strval_idx md5_append md5_finish diff --git a/epan/proto.c b/epan/proto.c index 7a2a690254..d04ee42a15 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -6007,7 +6007,7 @@ proto_registrar_dump_values(void) hfinfo->type == FT_INT64)) { if ((hfinfo->display & BASE_EXT_STRING)) { - vals = ((value_string_ext *) hfinfo->strings)->vals; + vals = VALUE_STRING_EXT_VS_P((value_string_ext *) hfinfo->strings); } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) { vals = hfinfo->strings; } else { diff --git a/epan/value_string.c b/epan/value_string.c index 91c22bbda7..53bdb10436 100644 --- a/epan/value_string.c +++ b/epan/value_string.c @@ -33,6 +33,7 @@ #include "value_string.h" #include <string.h> +/* --------------------------------------------------------------------*/ /* Tries to match val against each element in the value_string array vs. Returns the associated string ptr on a match. Formats val with fmt, and returns the resulting string, on failure. */ @@ -49,19 +50,7 @@ val_to_str(const guint32 val, const value_string *vs, const char *fmt) { return ep_strdup_printf(fmt, val); } -const gchar* -val_to_str_ext(const guint32 val, const value_string_ext *vs, const char *fmt) { - const gchar *ret; - - g_assert(fmt != NULL); - - ret = match_strval_ext(val, vs); - if (ret != NULL) - return ret; - - return ep_strdup_printf(fmt, val); -} - +/* --------------------------------------------------------------------*/ /* Tries to match val against each element in the value_string array vs. Returns the associated string ptr on a match. Returns 'unknown_str', on failure. */ @@ -78,19 +67,7 @@ val_to_str_const(const guint32 val, const value_string *vs, const char *unknown_ return unknown_str; } -const gchar* -val_to_str_ext_const(const guint32 val, const value_string_ext *vs, const char *unknown_str) { - const gchar *ret; - - g_assert(unknown_str != NULL); - - ret = match_strval_ext(val, vs); - if (ret != NULL) - return ret; - - return unknown_str; -} - +/* --------------------------------------------------------------------*/ /* Tries to match val against each element in the value_string array vs. Returns the associated string ptr, and sets "*idx" to the index in that table, on a match, and returns NULL, and sets "*idx" to -1, @@ -120,89 +97,205 @@ match_strval(const guint32 val, const value_string *vs) { return match_strval_idx(val, vs, &ignore_me); } +/* --------------------------------------------------------------------*/ +/* value_string_ext functions + * + * Extended value strings allow fast(er) value_string array lookups by + * using (if possible) direct access or a binary search of the array. + * + * If the values in the value_string array are a contiguous range of values + * from min to max, the value will be used as as a direct index into the array. + * + * If the values in the array are not contiguous (ie: there are "gaps"), + * but are in assending order a binary search will be used. + * + * If direct access or binary search cannot be used, then a linear search + * is used. + * + * Note that the value_string array used with VALUE_STRING_EXT_INIT + * *must* be terminated with {0, NULL}). + * + * Extended value strings are defined at compile time as follows: + * static const value_string vs[] = { {value1, "string1"}, {value2, "string2"}, ..., {0, NULL}}; + * static value_string_ext vse = VALUE_STRING_EXT_INIT(vs); + * + * Extended value strings can be created at runtime by calling + * value_string_ext_new(<ptr to value_string array>, + * <total number of entries in the value_string_array>, + * <value_string_name>); + * Note: <total number of entries in the value_string_array> should include the {0, NULL} entry + * + */ + +/* --------------------------------------------------------------------*/ + +/* Create a value_string_ext given a ptr to a value_string array and the total number of entries. */ +/* Note: The total number of entries should include the required {0, NULL} terminating entry of the array. */ +/* Return: a pointer to a gmalloc'd and initialized value_string_ext struct. */ +value_string_ext * +value_string_ext_new(value_string *vs, guint vs_tot_num_entries, gchar *vs_name) { + value_string_ext *vse; + g_assert (vs_name != NULL); + g_assert (vs_tot_num_entries > 0); + g_assert (vs[vs_tot_num_entries-1].strptr == NULL); /* Null-terminated value-string ? */ + vse = g_malloc(sizeof (value_string_ext)); + vse->_vs_p = vs; + vse->_vs_num_entries = vs_tot_num_entries - 1; /* remember the actual number of entries */ + vse->_vs_first_value = 0; /* initialized in _match_strval_ext_init */ + vse->_vs_match = (_value_string_match_t) _match_strval_ext_init; + vse->_vs_name = vs_name; + return vse; +} + +/* Looks up val in a value_string array using access method (direct, binary search + * or linear) determined at rutime during the initial access); (see _match_strval_ext_init) + * Returns the associated string ptr on a match, and returns NULL on failure. + */ +const gchar* +match_strval_ext(const guint32 val, const value_string_ext *vse) { + if (vse) + return vse->_vs_match(val, vse); + return NULL; +} + +/* Similar to match_strval_ext except that on failure + * Formats val with fmt, and returns the resulting string + */ +const gchar* +val_to_str_ext(const guint32 val, const value_string_ext *vse, const char *fmt) { + const gchar *ret; + + g_assert(fmt != NULL); + + ret = match_strval_ext(val, vse); + if (ret != NULL) + return ret; + + return ep_strdup_printf(fmt, val); +} + +/* Similar to match_strval_ext except that on failure + * Returns 'unknown_str' + */ +const gchar* +val_to_str_ext_const(const guint32 val, const value_string_ext *vse, const char *unknown_str) { + const gchar *ret; + + g_assert(unknown_str != NULL); + + ret = match_strval_ext(val, vse); + if (ret != NULL) + return ret; + + return unknown_str; +} + static const gchar * -_match_strval_linear(const guint32 val, const value_string_ext *vs) +_match_strval_linear(const guint32 val, const value_string_ext *vse) { - return match_strval(val, vs->vals); + const value_string *vs_p = vse->_vs_p; + guint i; + for (i=0; i<vse->_vs_num_entries; i++) { + if (vs_p[i].value == val) { + return vs_p[i].strptr; + } + } + return NULL; } static const gchar * -_match_strval_index(const guint32 val, const value_string_ext *vs) +_match_strval_index(const guint32 val, const value_string_ext *vse) { - return (val < vs->length) ? vs->vals[val].strptr : NULL; + if ((val - vse->_vs_first_value) < vse->_vs_num_entries) { + g_assert (val == vse->_vs_p[val - vse->_vs_first_value].value); + return vse->_vs_p[val - vse->_vs_first_value].strptr; + } + return NULL; } static const gchar * -_match_strval_bsearch(const guint32 val, const value_string_ext *vs) +_match_strval_bsearch(const guint32 val, const value_string_ext *vse) { guint low, idx, max; guint32 item; - for (low = 0, max = vs->length; low < max; ) { + for (low = 0, max = vse->_vs_num_entries; low < max; ) { idx = (low + max) / 2; - item = vs->vals[idx].value; + item = vse->_vs_p[idx].value; if (val < item) max = idx; else if (val > item) low = idx + 1; else - return vs->vals[idx].strptr; + return vse->_vs_p[idx].strptr; } return NULL; } +/* Init value_string_ext struct + - Go thru the value_string array to determine whether indexed access + or binary search access is possible; + - Verify that the value_string array does not contain any + NULL string pointers; + - Verify that the value_string array is terminated + by {0, NULL}; +*/ const gchar * -match_strval_ext_init(const guint32 val, value_string_ext *vse) +_match_strval_ext_init(const guint32 val, value_string_ext *vse) { - const value_string *vals = vse->vals; + const value_string *vs_p = vse->_vs_p; + const guint vs_num_entries = vse->_vs_num_entries; /* The way matching of value is done in a value_string: * 0 Sequential search (as in a normal value string) * 1 Binary search, the values MUST be in numerical order. - * 2 The value used as an index(the value string MUST have all values 0-max defined) + * 2 The value used as an index(the value string MUST have all values between first and last defined in numerical order) */ enum { VS_SEARCH = 0, VS_BIN_TREE, VS_INDEX } type = VS_INDEX; - guint32 prev = 0; - guint i; + guint32 prev_value; + guint first_value; + guint i; - for (i = 0; i < vse->length; i++) { - if (type == VS_INDEX && vals[i].value != i) - type = VS_BIN_TREE; + g_assert((vs_p[vs_num_entries].value==0) && (vs_p[vs_num_entries].strptr==NULL)); - if (type == VS_BIN_TREE && prev > vals[i].value) { + vse->_vs_first_value = vs_p[0].value; + first_value = vs_p[0].value; + prev_value = first_value; + + for (i = 0; i < vs_num_entries; i++) { + g_assert(vs_p[i].strptr != NULL); + if ((type == VS_INDEX) && (vs_p[i].value != (i + first_value))) { + type = VS_BIN_TREE; + } + if ((type == VS_BIN_TREE) && (prev_value > vs_p[i].value)) { type = VS_SEARCH; break; } - prev = vals[i].value; + prev_value = vs_p[i].value; } - + switch (type) { case VS_SEARCH: - vse->match = _match_strval_linear; - break; - case VS_INDEX: - vse->match = _match_strval_index; + vse->_vs_match = _match_strval_linear; + g_warning("Extended value string: %s not sorted; accessing linearly", vse->_vs_name); break; case VS_BIN_TREE: - vse->match = _match_strval_bsearch; + vse->_vs_match = _match_strval_bsearch; + break; + case VS_INDEX: + vse->_vs_match = _match_strval_index; break; default: g_assert_not_reached(); break; } - return vse->match(val, vse); -} - -const gchar* -match_strval_ext(const guint32 val, const value_string_ext *vs) { - if (vs) - return vs->match(val, vs); - return NULL; + return vse->_vs_match(val, vse); } +/* ----------- */ /* Tries to match val against each element in the value_string array vs. Returns the associated string ptr on a match. diff --git a/epan/value_string.h b/epan/value_string.h index cd30e9eb69..35c64b3507 100644 --- a/epan/value_string.h +++ b/epan/value_string.h @@ -34,18 +34,6 @@ typedef struct _value_string { const gchar *strptr; } value_string; -struct _value_string_ext; -typedef const char *(*value_string_match_t)(const guint32, const struct _value_string_ext *); - -typedef struct _value_string_ext { - value_string_match_t match; - guint length; /* length of the array */ - const value_string *vals; /* the value string */ -} value_string_ext; - -const gchar *match_strval_ext_init(const guint32 val, value_string_ext *vse); -#define VALUE_STRING_EXT_INIT(x) { (value_string_match_t) match_strval_ext_init, array_length(x)-1, x } - /* Struct for the str_to_str, match_strstr_idx, and match_strstr functions */ typedef struct _string_string { @@ -71,19 +59,17 @@ extern const gchar* match_strval_idx(const guint32 val, const value_string *vs, /* Like match_strval_idx(), but doesn't return the index. */ extern const gchar* match_strval(const guint32 val, const value_string *vs); -extern const gchar* match_strval_ext(const guint32 val, const value_string_ext *vs); /* Tries to match val against each element in the value_string array vs. Returns the associated string ptr on a match. Formats val with fmt, and returns the resulting string, on failure. */ extern const gchar* val_to_str(const guint32 val, const value_string *vs, const char *fmt); -extern const gchar* val_to_str_ext(const guint32 val, const value_string_ext *vs, const char *fmt); + /* Tries to match val against each element in the value_string array vs. Returns the associated string ptr on a match. Returns 'unknown_str', on failure. */ extern const gchar* val_to_str_const(const guint32 val, const value_string *vs, const char *unknown_str); -extern const gchar* val_to_str_ext_const(const guint32 val, const value_string_ext *vs, const char *unknown_str); /* Tries to match val against each element in the string_string array vs. Returns the associated string ptr, and sets "*idx" to the index in @@ -91,7 +77,7 @@ extern const gchar* val_to_str_ext_const(const guint32 val, const value_string_e on failure. */ extern const gchar* match_strstr_idx(const gchar *val, const string_string *vs, gint *idx); -/* Like match_strval_idx(), but doesn't return the index. */ +/* Like match_strstr_idx(), but doesn't return the index. */ extern const gchar* match_strstr(const gchar *val, const string_string *vs); /* Tries to match val against each element in the string_string array vs. @@ -99,6 +85,75 @@ extern const gchar* match_strstr(const gchar *val, const string_string *vs); Formats val with fmt, and returns the resulting string, on failure. */ extern const gchar* str_to_str(const gchar *val, const string_string *vs, const char *fmt); +/* --------------------------------------------------------------------*/ +/* value_string_ext functions + * + * Extended value strings allow fast(er) value_string array lookups by + * using (if possible) direct access or a binary search of the array. + * + * If the values in the value_string array are a contiguous range of values + * from min to max, the value will be used as as a direct index into the array. + * + * If the values in the array are not contiguous (ie: there are "gaps"), + * but are in assending order a binary search will be used. + * + * If direct access or binary search cannot be used, then a linear search + * is used. + * + * Note that the value_string array used with VALUE_STRING_EXT_INIT + * *must* be terminated with {0, NULL}). + * + * Extended value strings are defined at compile time as follows: + * static const value_string vs[] = { {value1, "string1"}, {value2, "string2"}, ..., {0, NULL}}; + * static value_string_ext vse = VALUE_STRING_EXT_INIT(vs); + * + * Extended value strings can be created at runtime by calling + * value_string_ext_new(<ptr to value_string array>, + * <total number of entries in the value_string_array>, + * <value_string_name>); + * Note: <total number of entries in the value_string_array> should include the {0, NULL} entry + */ +/* --------------------------------------------------------------------*/ +struct _value_string_ext; +typedef const char *(*_value_string_match_t)(const guint32, const struct _value_string_ext *); + +typedef struct _value_string_ext { + _value_string_match_t _vs_match; + guint32 _vs_first_value; /* first value of the value_string array */ + guint _vs_num_entries; /* number of entries in the value_string array */ + /* (excluding final {0, NULL}) */ + const value_string *_vs_p; /* the value string array address */ + const gchar *_vs_name; /* vse "Name" (for error messages) */ +} value_string_ext; + +#define VALUE_STRING_EXT_VS_P(x) (x)->_vs_p + +extern const gchar *_match_strval_ext_init(const guint32 val, value_string_ext *vse); +#define VALUE_STRING_EXT_INIT(x) { (_value_string_match_t) _match_strval_ext_init, 0, array_length(x)-1, x, #x } + +/* Create a value_string_ext given a ptr to a value_string array and the total number of entries. */ +/* Note: vs_tot_num_entries should include the required {0, NULL} terminating entry of the array. */ +/* Return: a pointer to a gmalloc'd and initialized value_string_ext struct. */ +extern value_string_ext *value_string_ext_new(value_string *vs, guint vs_tot_num_entries, gchar *vs_name); + +/* Looks up val in a value_string array using access method (direct, binary search + * or linear) determined at rutime during the initial access); (see _match_strval_ext_init) + * Returns the associated string ptr on a match or NULL on failure. + */ +extern const gchar* match_strval_ext(const guint32 val, const value_string_ext *vse); + +/* Similar to match_strval_ext except that on failure + * Formats val with fmt, and returns the resulting string + */ +extern const gchar* val_to_str_ext(const guint32 val, const value_string_ext *vs, const char *fmt); + +/* Similar to match_strval_ext except that on failure + * Returns 'unknown_str' + */ +extern const gchar* val_to_str_ext_const(const guint32 val, const value_string_ext *vs, const char *unknown_str); + +/* ---- ---- */ + /* Generate a string describing an enumerated bitfield (an N-bit field with various specific values having particular names). */ extern const char *decode_enumerated_bitfield(const guint32 val, const guint32 mask, |