dfilter: Add abs() function

Add an absolute value function for ftypes.
This commit is contained in:
João Valverde 2022-04-13 15:30:36 +01:00
parent 8889d8c78b
commit eb2a9889c3
20 changed files with 196 additions and 7 deletions

View File

@ -130,6 +130,7 @@ The filter language has the following functions:
string(field) - converts a non-string field to string
max(f1,...,fn) - return the maximum value
min(f1,...,fn) - return the minimum value
abs(field) - return the absolute value of numeric fields
upper() and lower() are useful for performing case-insensitive string
comparisons. For example:

View File

@ -68,7 +68,7 @@ They previously shipped with Npcap 1.55.
** Arithmetic is supported for numeric fields with the usual operators: +, -, *, /, %. Arithmetic expressions must be grouped using
curly brackets (not parenthesis).
** Logical AND now has higher precedence than logical OR, in line with most programming languages.
** Adds new display filter functions max() and min().
** Adds new display filter functions max(), min() and abs().
* text2pcap and "Import from Hex Dump":
** text2pcap supports writing the output file in all the capture file formats

View File

@ -813,6 +813,7 @@ The display filter language has a number of functions to convert fields, see
|string |Converts a non-string field to a 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.
|===
The `upper` and `lower` functions can used to force case-insensitive matches:

View File

@ -224,6 +224,43 @@ df_func_min(GSList **args, guint32 arg_count, GSList **retval)
return df_func_compare(args, arg_count, retval, fvalue_lt);
}
static gboolean
df_func_abs(GSList **args, guint32 arg_count, GSList **retval)
{
GSList *arg1;
fvalue_t *fv_arg, *new_fv;
char *err_msg = NULL;
GSList *result = NULL;
ws_assert(arg_count == 1);
arg1 = args[0];
if (arg1 == NULL)
return FALSE;
while (arg1) {
fv_arg = arg1->data;
if (fvalue_is_negative(fv_arg)) {
new_fv = fvalue_unary_minus(fv_arg, &err_msg);
if (new_fv == NULL) {
ws_debug("abs: %s", err_msg);
g_free(err_msg);
err_msg = NULL;
}
}
else {
new_fv = fvalue_dup(fv_arg);
}
result = g_slist_prepend(result, new_fv);
arg1 = arg1->next;
}
if (g_slist_length(result) == 0)
return FALSE;
*retval = result;
return TRUE;
}
/* For upper() and lower() checks that the parameter passed to
* it is an FT_STRING */
static void
@ -379,6 +416,35 @@ ul_semcheck_compare(dfwork_t *dfw, const char *func_name,
}
}
static void
ul_semcheck_absolute_value(dfwork_t *dfw, const char *func_name,
GSList *param_list, stloc_t *func_loc _U_)
{
ws_assert(g_slist_length(param_list) == 1);
stnode_t *st_node;
ftenum_t ftype;
const header_field_info *hfinfo;
st_node = param_list->data;
dfw_resolve_unparsed(dfw, st_node);
switch (stnode_type_id(st_node)) {
case STTYPE_FIELD:
case STTYPE_REFERENCE:
hfinfo = stnode_data(st_node);
ftype = hfinfo->type;
break;
default:
FAIL(dfw, st_node, "Type %s is not valid for %s",
stnode_type_name(st_node), func_name);
}
if (!ftype_can_is_negative(ftype)) {
FAIL(dfw, st_node, "'%s' is not a valid argument to '%s'()",
stnode_todisplay(st_node), func_name);
}
}
/* The table of all display-filter functions */
static df_func_def_t
df_functions[] = {
@ -387,8 +453,9 @@ df_functions[] = {
{ "len", df_func_len, FT_UINT32, 1, 1, ul_semcheck_is_field },
{ "count", df_func_count, FT_UINT32, 1, 1, ul_semcheck_is_field },
{ "string", df_func_string, FT_STRING, 1, 1, ul_semcheck_string_param },
{ "max", df_func_max, /*Any*/ 0, 1, 0, ul_semcheck_compare },
{ "min", df_func_min, /*Any*/ 0, 1, 0, ul_semcheck_compare },
{ "max", df_func_max, 0, 1, 0, ul_semcheck_compare },
{ "min", df_func_min, 0, 1, 0, ul_semcheck_compare },
{ "abs", df_func_abs, 0, 1, 1, ul_semcheck_absolute_value },
{ NULL, NULL, FT_NONE, 0, 0, NULL }
};

View File

@ -633,6 +633,7 @@ ftype_register_bytes(void)
cmp_matches,
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
@ -665,6 +666,7 @@ ftype_register_bytes(void)
NULL, /* cmp_matches */
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
@ -697,6 +699,7 @@ ftype_register_bytes(void)
cmp_matches,
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
@ -729,6 +732,7 @@ ftype_register_bytes(void)
cmp_matches,
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
@ -761,6 +765,7 @@ ftype_register_bytes(void)
cmp_matches,
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
@ -793,6 +798,7 @@ ftype_register_bytes(void)
NULL, /* cmp_matches */
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
@ -825,6 +831,7 @@ ftype_register_bytes(void)
NULL, /* cmp_matches */
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
@ -857,6 +864,7 @@ ftype_register_bytes(void)
NULL, /* cmp_matches */
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */
@ -889,6 +897,7 @@ ftype_register_bytes(void)
cmp_matches,
bytes_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
bytes_bitwise_and, /* bitwise_and */

View File

@ -116,6 +116,18 @@ cmp_order(const fvalue_t *a, const fvalue_t *b)
return 0;
}
static gboolean
val_is_zero(const fvalue_t *fv_a)
{
return fv_a->value.floating == 0;
}
static gboolean
val_is_negative(const fvalue_t *fv_a)
{
return fv_a->value.floating < 0;
}
void
ftype_register_double(void)
{
@ -140,7 +152,8 @@ ftype_register_double(void)
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL, /* is_zero */
val_is_zero, /* is_zero */
val_is_negative, /* is_negative */
NULL,
NULL,
NULL, /* bitwise_and */
@ -172,7 +185,8 @@ ftype_register_double(void)
NULL, /* cmp_contains */
NULL, /* cmp_matches */
NULL, /* is_zero */
val_is_zero, /* is_zero */
val_is_negative, /* is_negative */
NULL,
NULL,
NULL, /* bitwise_and */

View File

@ -121,6 +121,7 @@ ftype_register_guid(void)
NULL,
NULL,
NULL,
NULL,
NULL, /* unary_minus */
NULL, /* add */
NULL, /* subtract */

View File

@ -919,6 +919,7 @@ Example: 114 is 0x0072
NULL, /* cmp_matches */
sfloat_ieee_11073_is_zero, /* is_zero */
NULL, /* is_negative */
NULL, /* len */
NULL, /* slice */
NULL, /* bitwise_and */
@ -978,6 +979,7 @@ Example: 36.4 is 0xFF00016C
NULL, /* cmp_matches */
float_ieee_11073_is_zero, /* is_zero */
NULL, /* is_negative */
NULL, /* len */
NULL, /* slice */
NULL, /* bitwise_and */

View File

@ -679,6 +679,12 @@ uint_is_zero(const fvalue_t *fv)
return fv->value.uinteger == 0;
}
gboolean
uint_is_negative(const fvalue_t *fv _U_)
{
return FALSE;
}
enum ft_result
uint_unary_minus(fvalue_t *dst, const fvalue_t *src, char **err_ptr)
{
@ -707,6 +713,12 @@ uint64_is_zero(const fvalue_t *fv)
return fv->value.uinteger64 == 0;
}
gboolean
uint64_is_negative(const fvalue_t *fv _U_)
{
return FALSE;
}
enum ft_result
uint64_unary_minus(fvalue_t *dst, const fvalue_t *src, char **err_ptr)
{
@ -735,6 +747,12 @@ sint_is_zero(const fvalue_t *fv)
return fv->value.sinteger == 0;
}
gboolean
sint_is_negative(const fvalue_t *fv)
{
return fv->value.sinteger < 0;
}
enum ft_result
sint_unary_minus(fvalue_t * dst, const fvalue_t *src, char **err_ptr _U_)
{
@ -755,6 +773,12 @@ sint64_is_zero(const fvalue_t *fv)
return fv->value.sinteger64 == 0;
}
gboolean
sint64_is_negative(const fvalue_t *fv)
{
return fv->value.sinteger64 < 0;
}
enum ft_result
sint64_unary_minus(fvalue_t * dst, const fvalue_t *src, char **err_ptr _U_)
{
@ -1158,6 +1182,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint_is_zero, /* is_zero */
uint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
@ -1189,6 +1214,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint_is_zero, /* is_zero */
uint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
@ -1220,6 +1246,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint_is_zero, /* is_zero */
uint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
@ -1251,6 +1278,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint_is_zero, /* is_zero */
uint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
@ -1282,6 +1310,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint_is_zero, /* is_zero */
uint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
@ -1313,6 +1342,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint64_is_zero, /* is_zero */
uint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
@ -1344,6 +1374,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint64_is_zero, /* is_zero */
uint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
@ -1375,6 +1406,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint64_is_zero, /* is_zero */
uint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
@ -1406,6 +1438,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint64_is_zero, /* is_zero */
uint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
@ -1437,6 +1470,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
sint_is_zero, /* is_zero */
sint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
@ -1468,6 +1502,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
sint_is_zero, /* is_zero */
sint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
@ -1499,6 +1534,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
sint_is_zero, /* is_zero */
sint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
@ -1530,6 +1566,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
sint_is_zero, /* is_zero */
sint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
@ -1561,6 +1598,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
sint64_is_zero, /* is_zero */
sint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
@ -1592,6 +1630,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
sint64_is_zero, /* is_zero */
sint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
@ -1623,6 +1662,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
sint64_is_zero, /* is_zero */
sint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
@ -1654,6 +1694,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
sint64_is_zero, /* is_zero */
sint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
@ -1685,6 +1726,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint64_is_zero, /* is_zero */
uint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
NULL, /* bitwise_and */
@ -1717,6 +1759,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint_is_zero, /* is_zero */
uint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
@ -1749,6 +1792,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint_is_zero, /* is_zero */
uint_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
@ -1781,6 +1825,7 @@ ftype_register_integers(void)
NULL, /* cmp_matches */
uint64_is_zero, /* is_zero */
uint64_is_negative, /* is_negative */
NULL, /* len */
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */

View File

@ -171,6 +171,7 @@ ftype_register_ipv4(void)
is_zero,
NULL,
NULL,
slice,
bitwise_and,
NULL, /* unary_minus */

View File

@ -194,6 +194,7 @@ ftype_register_ipv6(void)
is_zero,
NULL,
NULL,
slice,
bitwise_and,
NULL, /* unary_minus */

View File

@ -36,6 +36,7 @@ ftype_register_none(void)
NULL, /* cmp_matches */
NULL, /* is_zero */
NULL, /* is_negative */
NULL, /* len */
NULL, /* slice */
NULL, /* biwise_and */

View File

@ -339,6 +339,7 @@ ftype_register_tvbuff(void)
cmp_matches,
is_zero,
NULL,
len,
slice,
NULL,

View File

@ -190,6 +190,7 @@ ftype_register_string(void)
cmp_matches,
string_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
NULL, /* bitwise_and */
@ -221,6 +222,7 @@ ftype_register_string(void)
cmp_matches,
string_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
NULL, /* bitwise_and */
@ -252,6 +254,7 @@ ftype_register_string(void)
cmp_matches,
string_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
NULL, /* bitwise_and */
@ -283,6 +286,7 @@ ftype_register_string(void)
cmp_matches,
string_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
NULL, /* bitwise_and */
@ -314,6 +318,7 @@ ftype_register_string(void)
cmp_matches,
string_is_zero, /* is_zero */
NULL, /* is_negative */
len,
slice,
NULL, /* bitwise_and */

View File

@ -417,6 +417,12 @@ time_is_zero(const fvalue_t *fv)
return nstime_is_zero(&fv->value.time);
}
static gboolean
time_is_negative(const fvalue_t *fv)
{
return fv->value.time.secs < 0;
}
static enum ft_result
time_unary_minus(fvalue_t * dst, const fvalue_t *src, char **err_ptr _U_)
{
@ -464,6 +470,7 @@ ftype_register_time(void)
NULL, /* cmp_matches */
time_is_zero, /* is_zero */
NULL, /* is_negative */
NULL,
NULL,
NULL, /* bitwise_and */
@ -495,6 +502,7 @@ ftype_register_time(void)
NULL, /* cmp_matches */
time_is_zero, /* is_zero */
time_is_negative, /* is_negative */
NULL,
NULL,
NULL, /* bitwise_and */

View File

@ -59,7 +59,7 @@ typedef int (*FvalueCmp)(const fvalue_t*, const fvalue_t*);
typedef gboolean (*FvalueContains)(const fvalue_t*, const fvalue_t*);
typedef gboolean (*FvalueMatches)(const fvalue_t*, const ws_regex_t*);
typedef gboolean (*FvalueIsZero)(const fvalue_t*);
typedef gboolean (*FvalueIs)(const fvalue_t*);
typedef guint (*FvalueLen)(fvalue_t*);
typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint offset, guint length);
typedef enum ft_result (*FvalueUnaryOp)(fvalue_t *, const fvalue_t*, gchar **);
@ -105,7 +105,8 @@ struct _ftype_t {
FvalueContains cmp_contains;
FvalueMatches cmp_matches;
FvalueIsZero is_zero;
FvalueIs is_zero;
FvalueIs is_negative;
FvalueLen len;
FvalueSlice slice;
FvalueBinaryOp bitwise_and;

View File

@ -290,6 +290,15 @@ ftype_can_is_zero(enum ftenum ftype)
return ft->is_zero ? TRUE : FALSE;
}
gboolean
ftype_can_is_negative(enum ftenum ftype)
{
ftype_t *ft;
FTYPE_LOOKUP(ftype, ft);
return ft->is_negative ? TRUE : FALSE;
}
/* ---------------------------------------------------------- */
/* Allocate and initialize an fvalue_t, given an ftype */
@ -844,6 +853,12 @@ fvalue_is_zero(const fvalue_t *a)
return a->ftype->is_zero(a);
}
gboolean
fvalue_is_negative(const fvalue_t *a)
{
return a->ftype->is_negative(a);
}
static fvalue_t *
_fvalue_binop(FvalueBinaryOp op, const fvalue_t *a, const fvalue_t *b, char **err_msg)
{

View File

@ -215,6 +215,10 @@ WS_DLL_PUBLIC
gboolean
ftype_can_is_zero(enum ftenum ftype);
WS_DLL_PUBLIC
gboolean
ftype_can_is_negative(enum ftenum ftype);
/* ---------------- FVALUE ----------------- */
#include <epan/ipv4.h>
@ -380,6 +384,9 @@ fvalue_matches(const fvalue_t *a, const ws_regex_t *re);
gboolean
fvalue_is_zero(const fvalue_t *a);
gboolean
fvalue_is_negative(const fvalue_t *a);
guint
fvalue_length(fvalue_t *fv);

View File

@ -730,6 +730,7 @@ libwireshark.so.0 libwireshark0 #MINVER#
ftype_can_cmp@Base 3.7.0
ftype_can_contains@Base 1.9.1
ftype_can_eq@Base 1.9.1
ftype_can_is_negative@Base 3.7.0
ftype_can_is_zero@Base 3.7.0
ftype_can_matches@Base 1.9.1
ftype_can_slice@Base 1.9.1

View File

@ -65,3 +65,11 @@ class case_dfunction_maxmin(unittest.TestCase):
def test_max_3(self, checkDFilterCount):
dfilter = 'max(udp.srcport, udp.dstport) < 5060'
checkDFilterCount(dfilter, 1)
@fixtures.uses_fixtures
class case_dfunction_abs(unittest.TestCase):
trace_file = "dhcp.pcapng"
def test_function_abs_1(self, checkDFilterCount):
dfilter = 'udp.dstport == abs(-67)'
checkDFilterCount(dfilter, 2)