dfilter: Add functions to override field base
Add field expression functions to convert unsigned integer and char fields to hex or decimal. (BASE_OCT is handled somewhat different currently now, presumably because it can't be used in filters, so leave that commented until it is handled as a display representation.) Currently string() always converts unsigned integers to their decimal representation so it is the same as dec(), but possibly in the future string() might use the native base. These can be used in columns thanks to the fix for #15990 Fix #5308
This commit is contained in:
parent
ac90d8c834
commit
e5168435b5
|
@ -77,6 +77,9 @@ The following features are new (or have been significantly updated) since versio
|
|||
** Added new display filter functions to test various IP address properties.
|
||||
Check the wireshark-filter(5) manpage for more information.
|
||||
|
||||
** Added new display filter functions to convert unsigned integer types to
|
||||
decimal or hexadecimal. Check the wireshark-filter(5) manpage for more information.
|
||||
|
||||
** Display filter macros can be written with a semicolon after the macro
|
||||
name before the argument list, e.g. `${mymacro;arg1;...;argN}`, instead
|
||||
of `${mymacro:arg1;...;argN}`. The version with semicolons works better
|
||||
|
|
|
@ -138,6 +138,8 @@ The filter language has the following functions:
|
|||
len(field) - returns the byte length of a string or bytes field
|
||||
count(field) - returns the number of field occurrences in a frame
|
||||
string(field) - converts a non-string field to string
|
||||
dec(field) - converts an unsigned integer to a decimal string
|
||||
hex(field) - converts an unsigned integer to a hexadecimal string
|
||||
max(f1,...,fn) - return the maximum value
|
||||
min(f1,...,fn) - return the minimum value
|
||||
abs(field) - return the absolute value of numeric fields
|
||||
|
@ -157,6 +159,11 @@ byte fields. For example:
|
|||
|
||||
gives you all the odd packets.
|
||||
|
||||
dec() and hex() convert unsigned integer fields to decimal or hexadecimal
|
||||
representation. Currently dec() and string() give same result for an unsigned
|
||||
integer, but it is possible that in the future string() will use the native
|
||||
base of the field.
|
||||
|
||||
max() and min() take any number of arguments and returns one value, respectively
|
||||
the largest/smallest. The arguments must all have the same type.
|
||||
|
||||
|
|
|
@ -956,6 +956,8 @@ The display filter language has a number of functions to convert fields, see
|
|||
|len |Returns the byte length of a string or bytes field.
|
||||
|count |Returns the number of field occurrences in a frame.
|
||||
|string |Converts a non-string field to a string.
|
||||
|dec |Converts an unsigned integer field to a decimal string.
|
||||
|hex |Converts an unsigned integer field to a hexadecimal string.
|
||||
|max |Return the maximum value for the arguments.
|
||||
|min |Return the minimum value for the arguments.
|
||||
|abs |Return the absolute value for the argument.
|
||||
|
|
|
@ -165,6 +165,69 @@ df_func_string(GSList *stack, uint32_t arg_count _U_, df_cell_t *retval)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* dfilter functions: dec(), hex(), */
|
||||
static bool
|
||||
df_func_base(GSList *stack, uint32_t arg_count _U_, df_cell_t *retval, int base)
|
||||
{
|
||||
GPtrArray *arg1;
|
||||
fvalue_t *arg_fvalue;
|
||||
fvalue_t *new_ft_string;
|
||||
char *s;
|
||||
|
||||
ws_assert(arg_count == 1);
|
||||
arg1 = stack->data;
|
||||
if (arg1 == NULL)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < arg1->len; i++) {
|
||||
arg_fvalue = arg1->pdata[i];
|
||||
|
||||
if (FT_IS_UINT(fvalue_type_ftenum(arg_fvalue))) {
|
||||
s = fvalue_to_string_repr(NULL, arg_fvalue, FTREPR_DFILTER, base);
|
||||
/* Ensure we have an allocated string here */
|
||||
if (!s)
|
||||
s = wmem_strdup(NULL, "");
|
||||
} else {
|
||||
/* XXX - We have, unfortunately, some field abbreviations which are
|
||||
* re-used with incompatible types, some of which support different
|
||||
* bases and some which don't.
|
||||
*/
|
||||
s = wmem_strdup(NULL, "");
|
||||
}
|
||||
|
||||
new_ft_string = fvalue_new(FT_STRING);
|
||||
fvalue_set_string(new_ft_string, s);
|
||||
wmem_free(NULL, s);
|
||||
df_cell_append(retval, new_ft_string);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
df_func_hex(GSList *stack, uint32_t arg_count _U_, df_cell_t *retval)
|
||||
{
|
||||
return df_func_base(stack, arg_count, retval, BASE_HEX);
|
||||
}
|
||||
|
||||
static bool
|
||||
df_func_dec(GSList *stack, uint32_t arg_count _U_, df_cell_t *retval)
|
||||
{
|
||||
return df_func_base(stack, arg_count, retval, BASE_DEC);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// XXX - BASE_OCT isn't handled by fvalue_to_string_repr; it probably
|
||||
// should at least for FTREPR_DISPLAY (the filter language doesn't
|
||||
// support it due to possible notation confusion, I assume.)
|
||||
// Add that first before offering it.
|
||||
static bool
|
||||
df_func_oct(GSList *stack, uint32_t arg_count _U_, df_cell_t *retval)
|
||||
{
|
||||
return df_func_base(stack, arg_count, retval, BASE_OCT);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
df_func_compare(GSList *stack, uint32_t arg_count, df_cell_t *retval,
|
||||
bool (*fv_cmp)(const fvalue_t *a, const fvalue_t *b))
|
||||
|
@ -410,6 +473,34 @@ ul_semcheck_string(dfwork_t *dfw, const char *func_name, ftenum_t logical_ftype
|
|||
dfunc_fail(dfw, param, "Only fields can be used as parameter for %s()", func_name);
|
||||
}
|
||||
|
||||
static ftenum_t
|
||||
ul_semcheck_base(dfwork_t *dfw, const char *func_name, ftenum_t logical_ftype _U_,
|
||||
GSList *param_list, df_loc_t func_loc _U_)
|
||||
{
|
||||
header_field_info *hfinfo;
|
||||
|
||||
ws_assert(g_slist_length(param_list) == 1);
|
||||
stnode_t *param = param_list->data;
|
||||
|
||||
resolve_unparsed(dfw, param, true);
|
||||
|
||||
if (stnode_type_id(param) == STTYPE_FIELD) {
|
||||
dfw->field_count++;
|
||||
hfinfo = sttype_field_hfinfo(param);
|
||||
/* FT_CHAR also supports BASE_, but for what sort of escaped
|
||||
* values to use for non-printable ASCII. BASE_HEX uses hex,
|
||||
* all other bases will use octal.
|
||||
* That's a little confusing, so don't support it for now.
|
||||
* More useful might be to display all possible values as
|
||||
* HEX or DEC, i.e. convert to a FT_UINT8 first. */
|
||||
if (FT_IS_UINT(hfinfo->type)) {
|
||||
return FT_STRING;
|
||||
}
|
||||
dfunc_fail(dfw, param, "Base conversion for field \"%s\" is not supported", hfinfo->abbrev);
|
||||
}
|
||||
dfunc_fail(dfw, param, "Only fields can be used as parameter for %s()", func_name);
|
||||
}
|
||||
|
||||
/* Check arguments are all the same type and they can be compared. */
|
||||
static ftenum_t
|
||||
ul_semcheck_compare(dfwork_t *dfw, const char *func_name, ftenum_t logical_ftype,
|
||||
|
@ -460,6 +551,9 @@ df_functions[] = {
|
|||
{ "len", NULL, 1, 1, FT_UINT32, ul_semcheck_can_length },
|
||||
{ "count", df_func_count, 1, 1, FT_UINT32, ul_semcheck_is_field },
|
||||
{ "string", df_func_string, 1, 1, FT_STRING, ul_semcheck_string },
|
||||
{ "dec", df_func_dec, 1, 1, FT_STRING, ul_semcheck_base },
|
||||
{ "hex", df_func_hex, 1, 1, FT_STRING, ul_semcheck_base },
|
||||
//{ "oct", df_func_oct, 1, 1, FT_STRING, ul_semcheck_base },
|
||||
{ "max", df_func_max, 1, 0, FT_NONE, ul_semcheck_compare },
|
||||
{ "min", df_func_min, 1, 0, FT_NONE, ul_semcheck_compare },
|
||||
{ "abs", df_func_abs, 1, 1, FT_NONE, ul_semcheck_absolute_value },
|
||||
|
|
Loading…
Reference in New Issue