aboutsummaryrefslogtreecommitdiffstats
path: root/epan/ftypes
diff options
context:
space:
mode:
authorJoão Valverde <j@v6e.pt>2022-02-27 14:47:31 +0000
committerJoão Valverde <j@v6e.pt>2022-03-31 11:27:34 +0100
commit2a9cb588aa6fe2322d37cbe39604dd54b8477292 (patch)
treed5ced7003cf14f84dff4704c57566c518a0abf2d /epan/ftypes
parentae537e24f03b3f06952276fce3c09b5f8a46bd79 (diff)
dfilter: Add binary arithmetic (add/subtract)
Add support for display filter binary addition and subtraction. The grammar is intentionally kept simple for now. The use case is to add a constant to a protocol field, or (maybe) add two fields in an expression. We use signed arithmetic with unsigned numbers, checking for overflow and casting where necessary to do the conversion. We could legitimately opt to use traditional modular arithmetic instead (like C) and if it turns out that that is more useful for some reason we may want to in the future. Fixes #15504.
Diffstat (limited to 'epan/ftypes')
-rw-r--r--epan/ftypes/ftype-bytes.c18
-rw-r--r--epan/ftypes/ftype-double.c18
-rw-r--r--epan/ftypes/ftype-guid.c2
-rw-r--r--epan/ftypes/ftype-ieee-11073-float.c4
-rw-r--r--epan/ftypes/ftype-integer.c169
-rw-r--r--epan/ftypes/ftype-ipv4.c2
-rw-r--r--epan/ftypes/ftype-ipv6.c2
-rw-r--r--epan/ftypes/ftype-none.c2
-rw-r--r--epan/ftypes/ftype-protocol.c2
-rw-r--r--epan/ftypes/ftype-string.c10
-rw-r--r--epan/ftypes/ftype-time.c18
-rw-r--r--epan/ftypes/ftypes-int.h6
-rw-r--r--epan/ftypes/ftypes.c50
-rw-r--r--epan/ftypes/ftypes.h12
14 files changed, 312 insertions, 3 deletions
diff --git a/epan/ftypes/ftype-bytes.c b/epan/ftypes/ftype-bytes.c
index 3f5d75ebb7..b056ccb3bc 100644
--- a/epan/ftypes/ftype-bytes.c
+++ b/epan/ftypes/ftype-bytes.c
@@ -615,6 +615,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t uint_bytes_type = {
@@ -642,6 +644,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t ax25_type = {
@@ -669,6 +673,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t vines_type = {
@@ -696,6 +702,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t ether_type = {
@@ -723,6 +731,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t oid_type = {
@@ -750,6 +760,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t rel_oid_type = {
@@ -777,6 +789,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t system_id_type = {
@@ -804,6 +818,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t fcwwn_type = {
@@ -831,6 +847,8 @@ ftype_register_bytes(void)
slice,
bytes_bitwise_and, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
ftype_register(FT_BYTES, &bytes_type);
diff --git a/epan/ftypes/ftype-double.c b/epan/ftypes/ftype-double.c
index fe04999bd0..c81f0c0e77 100644
--- a/epan/ftypes/ftype-double.c
+++ b/epan/ftypes/ftype-double.c
@@ -92,6 +92,20 @@ val_unary_minus(fvalue_t * dst, const fvalue_t *src, char **err_ptr _U_)
return FT_OK;
}
+enum ft_result
+val_add(fvalue_t * dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr _U_)
+{
+ dst->value.floating = a->value.floating + b->value.floating;
+ return FT_OK;
+}
+
+enum ft_result
+val_subtract(fvalue_t * dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr _U_)
+{
+ dst->value.floating = a->value.floating - b->value.floating;
+ return FT_OK;
+}
+
static int
cmp_order(const fvalue_t *a, const fvalue_t *b)
{
@@ -131,6 +145,8 @@ ftype_register_double(void)
NULL,
NULL, /* bitwise_and */
val_unary_minus, /* unary_minus */
+ val_add, /* add */
+ val_subtract, /* subtract */
};
static ftype_t double_type = {
@@ -158,6 +174,8 @@ ftype_register_double(void)
NULL,
NULL, /* bitwise_and */
val_unary_minus, /* unary_minus */
+ val_add, /* add */
+ val_subtract, /* subtract */
};
ftype_register(FT_FLOAT, &float_type);
diff --git a/epan/ftypes/ftype-guid.c b/epan/ftypes/ftype-guid.c
index 7dcbdea231..d6db8810c1 100644
--- a/epan/ftypes/ftype-guid.c
+++ b/epan/ftypes/ftype-guid.c
@@ -122,6 +122,8 @@ ftype_register_guid(void)
NULL,
NULL,
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
ftype_register(FT_GUID, &guid_type);
diff --git a/epan/ftypes/ftype-ieee-11073-float.c b/epan/ftypes/ftype-ieee-11073-float.c
index 4e94b32b62..0c64368451 100644
--- a/epan/ftypes/ftype-ieee-11073-float.c
+++ b/epan/ftypes/ftype-ieee-11073-float.c
@@ -923,6 +923,8 @@ Example: 114 is 0x0072
NULL, /* slice */
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
/*
@@ -977,6 +979,8 @@ Example: 36.4 is 0xFF00016C
NULL, /* slice */
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
ftype_register(FT_IEEE_11073_SFLOAT, &sfloat_type);
diff --git a/epan/ftypes/ftype-integer.c b/epan/ftypes/ftype-integer.c
index 4877578efb..7c4e0e892e 100644
--- a/epan/ftypes/ftype-integer.c
+++ b/epan/ftypes/ftype-integer.c
@@ -16,6 +16,7 @@
#include <epan/to_str.h>
#include <wsutil/pint.h>
+#include <wsutil/safe-math.h>
static void
int_fvalue_new(fvalue_t *fv)
@@ -686,7 +687,7 @@ uint_unary_minus(fvalue_t *dst, const fvalue_t *src, char **err_ptr)
if (err_ptr)
*err_ptr = ws_strdup_printf("%"G_GUINT32_FORMAT" overflows gint32",
src->value.uinteger);
- return FT_ERR_OVERFLOW;
+ return FT_ERROR;
}
FTYPE_LOOKUP(FT_INT32, dst->ftype);
dst->value.sinteger = -(gint32)src->value.uinteger;
@@ -714,7 +715,7 @@ uint64_unary_minus(fvalue_t *dst, const fvalue_t *src, char **err_ptr)
if (err_ptr)
*err_ptr = ws_strdup_printf("%"G_GUINT64_FORMAT" overflows gint64",
src->value.uinteger64);
- return FT_ERR_OVERFLOW;
+ return FT_ERROR;
}
FTYPE_LOOKUP(FT_INT64, dst->ftype);
dst->value.sinteger64 = -(gint64)src->value.uinteger64;
@@ -761,6 +762,128 @@ sint64_unary_minus(fvalue_t * dst, const fvalue_t *src, char **err_ptr _U_)
return FT_OK;
}
+static enum ft_result
+sint_add(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr)
+{
+ if (!psnip_safe_add(&dst->value.sinteger, a->value.sinteger, b->value.sinteger)) {
+ /* Overflow */
+ *err_ptr = ws_strdup_printf("sint_add: overflow");
+ return FT_ERROR;
+ }
+ return FT_OK;
+}
+
+static enum ft_result
+_sint_subtract(gint32 *sint_dst, gint32 sint_a, gint32 sint_b, char **err_ptr)
+{
+ if (!psnip_safe_sub(sint_dst, sint_a, sint_b)) {
+ /* Overflow */
+ *err_ptr = ws_strdup_printf("sint_sub: overflow");
+ return FT_ERROR;
+ }
+ return FT_OK;
+}
+
+static enum ft_result
+sint_subtract(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr)
+{
+ return _sint_subtract(&dst->value.sinteger, a->value.sinteger, b->value.sinteger, err_ptr);
+}
+
+static enum ft_result
+uint_add(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr)
+{
+ if (!psnip_safe_add(&dst->value.uinteger, a->value.uinteger, b->value.uinteger)) {
+ /* Overflow */
+ *err_ptr = ws_strdup_printf("uint_add: overflow");
+ return FT_ERROR;
+ }
+ return FT_OK;
+}
+
+static enum ft_result
+uint_subtract(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr)
+{
+ if (b->value.uinteger > a->value.uinteger) {
+ /* Uses signed arithmetic. */
+ if (a->value.uinteger > G_MAXINT32 ||
+ b->value.uinteger > G_MAXINT32) {
+ *err_ptr = ws_strdup_printf("uint_subtract: signed overflow");
+ return FT_ERROR;
+ }
+ FTYPE_LOOKUP(FT_INT32, dst->ftype);
+ return _sint_subtract(&dst->value.sinteger, (gint32)a->value.uinteger, (gint32)b->value.uinteger, err_ptr);
+ }
+
+ if (!psnip_safe_sub(&dst->value.uinteger, a->value.uinteger, b->value.uinteger)) {
+ /* Overflow */
+ *err_ptr = ws_strdup_printf("uint_subtract: overflow");
+ return FT_ERROR;
+ }
+ return FT_OK;
+}
+
+static enum ft_result
+sint64_add(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr)
+{
+ if (!psnip_safe_add(&dst->value.sinteger64, a->value.sinteger64, b->value.sinteger64)) {
+ /* Overflow */
+ *err_ptr = ws_strdup_printf("sint64_add: overflow");
+ return FT_ERROR;
+ }
+ return FT_OK;
+}
+
+static enum ft_result
+_sint64_subtract(gint64 *sint_dst, gint64 sint_a, gint64 sint_b, char **err_ptr)
+{
+ if (!psnip_safe_sub(sint_dst, sint_a, sint_b)) {
+ /* Overflow */
+ *err_ptr = ws_strdup_printf("sint64_sub: overflow");
+ return FT_ERROR;
+ }
+ return FT_OK;
+}
+
+static enum ft_result
+sint64_subtract(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr)
+{
+ return _sint64_subtract(&dst->value.sinteger64, a->value.sinteger64, b->value.sinteger64, err_ptr);
+}
+
+static enum ft_result
+uint64_add(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr)
+{
+ if (!psnip_safe_add(&dst->value.uinteger64, a->value.uinteger64, b->value.uinteger64)) {
+ /* Overflow */
+ *err_ptr = ws_strdup_printf("uint64_add: overflow");
+ return FT_ERROR;
+ }
+ return FT_OK;
+}
+
+static enum ft_result
+uint64_subtract(fvalue_t *dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr)
+{
+ if (b->value.uinteger64 > a->value.uinteger64) {
+ /* Uses signed arithmetic. */
+ if (a->value.uinteger64 > G_MAXINT64 ||
+ b->value.uinteger64 > G_MAXINT64) {
+ *err_ptr = ws_strdup_printf("uint64_subtract: signed overflow");
+ return FT_ERROR;
+ }
+ FTYPE_LOOKUP(FT_INT64, dst->ftype);
+ return _sint64_subtract(&dst->value.sinteger64, (gint64)a->value.uinteger64, (gint64)b->value.uinteger64, err_ptr);
+ }
+
+ if (!psnip_safe_sub(&dst->value.uinteger64, a->value.uinteger64, b->value.uinteger64)) {
+ /* Overflow */
+ *err_ptr = ws_strdup_printf("uint64_sub: overflow");
+ return FT_ERROR;
+ }
+ return FT_OK;
+}
+
/* BOOLEAN-specific */
static gboolean
@@ -887,6 +1010,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
uint_unary_minus, /* unary_minus */
+ uint_add, /* add */
+ uint_subtract, /* subtract */
};
static ftype_t uint8_type = {
FT_UINT8, /* ftype */
@@ -913,6 +1038,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
uint_unary_minus, /* unary_minus */
+ uint_add, /* add */
+ uint_subtract, /* subtract */
};
static ftype_t uint16_type = {
FT_UINT16, /* ftype */
@@ -939,6 +1066,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
uint_unary_minus, /* unary_minus */
+ uint_add, /* add */
+ uint_subtract, /* subtract */
};
static ftype_t uint24_type = {
FT_UINT24, /* ftype */
@@ -965,6 +1094,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
uint_unary_minus, /* unary_minus */
+ uint_add, /* add */
+ uint_subtract, /* subtract */
};
static ftype_t uint32_type = {
FT_UINT32, /* ftype */
@@ -991,6 +1122,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
uint_unary_minus, /* unary_minus */
+ uint_add, /* add */
+ uint_subtract, /* subtract */
};
static ftype_t uint40_type = {
FT_UINT40, /* ftype */
@@ -1017,6 +1150,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
uint64_unary_minus, /* unary_minus */
+ uint64_add, /* add */
+ uint64_subtract, /* subtract */
};
static ftype_t uint48_type = {
FT_UINT48, /* ftype */
@@ -1043,6 +1178,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
uint64_unary_minus, /* unary_minus */
+ uint64_add, /* add */
+ uint64_subtract, /* subtract */
};
static ftype_t uint56_type = {
FT_UINT56, /* ftype */
@@ -1069,6 +1206,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
uint64_unary_minus, /* unary_minus */
+ uint64_add, /* add */
+ uint64_subtract, /* subtract */
};
static ftype_t uint64_type = {
FT_UINT64, /* ftype */
@@ -1095,6 +1234,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
uint64_unary_minus, /* unary_minus */
+ uint64_add, /* add */
+ uint64_subtract, /* subtract */
};
static ftype_t int8_type = {
FT_INT8, /* ftype */
@@ -1121,6 +1262,8 @@ ftype_register_integers(void)
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
sint_unary_minus, /* unary_minus */
+ sint_add, /* add */
+ sint_subtract, /* subtract */
};
static ftype_t int16_type = {
FT_INT16, /* ftype */
@@ -1147,6 +1290,8 @@ ftype_register_integers(void)
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
sint_unary_minus, /* unary_minus */
+ sint_add, /* add */
+ sint_subtract, /* subtract */
};
static ftype_t int24_type = {
FT_INT24, /* ftype */
@@ -1173,6 +1318,8 @@ ftype_register_integers(void)
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
sint_unary_minus, /* unary_minus */
+ sint_add, /* add */
+ sint_subtract, /* subtract */
};
static ftype_t int32_type = {
FT_INT32, /* ftype */
@@ -1199,6 +1346,8 @@ ftype_register_integers(void)
NULL, /* slice */
sint_bitwise_and, /* bitwise_and */
sint_unary_minus, /* unary_minus */
+ sint_add, /* add */
+ sint_subtract, /* subtract */
};
static ftype_t int40_type = {
FT_INT40, /* ftype */
@@ -1225,6 +1374,8 @@ ftype_register_integers(void)
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
sint64_unary_minus, /* unary_minus */
+ sint64_add, /* add */
+ sint64_subtract, /* subtract */
};
static ftype_t int48_type = {
FT_INT48, /* ftype */
@@ -1251,6 +1402,8 @@ ftype_register_integers(void)
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
sint64_unary_minus, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t int56_type = {
FT_INT56, /* ftype */
@@ -1277,6 +1430,8 @@ ftype_register_integers(void)
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
sint64_unary_minus, /* unary_minus */
+ sint64_add, /* add */
+ sint64_subtract, /* subtract */
};
static ftype_t int64_type = {
FT_INT64, /* ftype */
@@ -1303,6 +1458,8 @@ ftype_register_integers(void)
NULL, /* slice */
sint64_bitwise_and, /* bitwise_and */
sint64_unary_minus, /* unary_minus */
+ sint64_add, /* add */
+ sint64_subtract, /* subtract */
};
static ftype_t boolean_type = {
FT_BOOLEAN, /* ftype */
@@ -1329,6 +1486,8 @@ ftype_register_integers(void)
NULL, /* slice */
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t ipxnet_type = {
@@ -1356,6 +1515,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
uint_unary_minus, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t framenum_type = {
@@ -1383,6 +1544,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint_bitwise_and, /* bitwise_and */
uint_unary_minus, /* unary_minus */
+ uint_add, /* add */
+ uint_subtract, /* subtract */
};
static ftype_t eui64_type = {
@@ -1410,6 +1573,8 @@ ftype_register_integers(void)
NULL, /* slice */
uint64_bitwise_and, /* bitwise_and */
uint64_unary_minus, /* unary_minus */
+ uint64_add, /* add */
+ uint64_subtract, /* subtract */
};
ftype_register(FT_CHAR, &char_type);
diff --git a/epan/ftypes/ftype-ipv4.c b/epan/ftypes/ftype-ipv4.c
index e66b485240..cae0ede4c8 100644
--- a/epan/ftypes/ftype-ipv4.c
+++ b/epan/ftypes/ftype-ipv4.c
@@ -174,6 +174,8 @@ ftype_register_ipv4(void)
slice,
bitwise_and,
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
ftype_register(FT_IPv4, &ipv4_type);
diff --git a/epan/ftypes/ftype-ipv6.c b/epan/ftypes/ftype-ipv6.c
index 2c92caec63..dee1825a17 100644
--- a/epan/ftypes/ftype-ipv6.c
+++ b/epan/ftypes/ftype-ipv6.c
@@ -197,6 +197,8 @@ ftype_register_ipv6(void)
slice,
bitwise_and,
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
ftype_register(FT_IPv6, &ipv6_type);
diff --git a/epan/ftypes/ftype-none.c b/epan/ftypes/ftype-none.c
index d79e58ccec..257d534d24 100644
--- a/epan/ftypes/ftype-none.c
+++ b/epan/ftypes/ftype-none.c
@@ -40,6 +40,8 @@ ftype_register_none(void)
NULL, /* slice */
NULL, /* biwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
ftype_register(FT_NONE, &none_type);
}
diff --git a/epan/ftypes/ftype-protocol.c b/epan/ftypes/ftype-protocol.c
index 60673580bc..48c3af812b 100644
--- a/epan/ftypes/ftype-protocol.c
+++ b/epan/ftypes/ftype-protocol.c
@@ -343,6 +343,8 @@ ftype_register_tvbuff(void)
slice,
NULL,
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
diff --git a/epan/ftypes/ftype-string.c b/epan/ftypes/ftype-string.c
index 3267f07e82..f42ac968f9 100644
--- a/epan/ftypes/ftype-string.c
+++ b/epan/ftypes/ftype-string.c
@@ -194,6 +194,8 @@ ftype_register_string(void)
slice,
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t stringz_type = {
FT_STRINGZ, /* ftype */
@@ -220,6 +222,8 @@ ftype_register_string(void)
slice,
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t uint_string_type = {
FT_UINT_STRING, /* ftype */
@@ -246,6 +250,8 @@ ftype_register_string(void)
slice,
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t stringzpad_type = {
FT_STRINGZPAD, /* ftype */
@@ -272,6 +278,8 @@ ftype_register_string(void)
slice,
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t stringztrunc_type = {
FT_STRINGZTRUNC, /* ftype */
@@ -298,6 +306,8 @@ ftype_register_string(void)
slice,
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
ftype_register(FT_STRING, &string_type);
diff --git a/epan/ftypes/ftype-time.c b/epan/ftypes/ftype-time.c
index c210ca3d72..3db1fcbe84 100644
--- a/epan/ftypes/ftype-time.c
+++ b/epan/ftypes/ftype-time.c
@@ -425,6 +425,20 @@ time_unary_minus(fvalue_t * dst, const fvalue_t *src, char **err_ptr _U_)
return FT_OK;
}
+static enum ft_result
+time_add(fvalue_t * dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr _U_)
+{
+ nstime_sum(&dst->value.time, &a->value.time, &b->value.time);
+ return FT_OK;
+}
+
+static enum ft_result
+time_subtract(fvalue_t * dst, const fvalue_t *a, const fvalue_t *b, char **err_ptr _U_)
+{
+ nstime_delta(&dst->value.time, &a->value.time, &b->value.time);
+ return FT_OK;
+}
+
void
ftype_register_time(void)
{
@@ -454,6 +468,8 @@ ftype_register_time(void)
NULL,
NULL, /* bitwise_and */
NULL, /* unary_minus */
+ NULL, /* add */
+ NULL, /* subtract */
};
static ftype_t reltime_type = {
FT_RELATIVE_TIME, /* ftype */
@@ -480,6 +496,8 @@ ftype_register_time(void)
NULL,
NULL, /* bitwise_and */
time_unary_minus, /* unary_minus */
+ time_add, /* add */
+ time_subtract, /* subtract */
};
ftype_register(FT_ABSOLUTE_TIME, &abstime_type);
diff --git a/epan/ftypes/ftypes-int.h b/epan/ftypes/ftypes-int.h
index 156462df28..6f6f21590a 100644
--- a/epan/ftypes/ftypes-int.h
+++ b/epan/ftypes/ftypes-int.h
@@ -24,7 +24,7 @@ extern ftype_t* type_list[FT_NUM_TYPES];
enum ft_result {
FT_OK,
- FT_ERR_OVERFLOW,
+ FT_ERROR,
};
typedef void (*FvalueNewFunc)(fvalue_t*);
@@ -64,6 +64,8 @@ typedef guint (*FvalueLen)(fvalue_t*);
typedef void (*FvalueSlice)(fvalue_t*, GByteArray *, guint offset, guint length);
typedef enum ft_result (*FvalueBitwiseAnd)(fvalue_t *, const fvalue_t*, const fvalue_t*, gchar **);
typedef enum ft_result (*FvalueUnaryMinus)(fvalue_t *, const fvalue_t*, gchar **);
+typedef enum ft_result (*FvalueAdd)(fvalue_t *, const fvalue_t*, const fvalue_t*, gchar **);
+typedef enum ft_result (*FvalueSubtract)(fvalue_t *, const fvalue_t*, const fvalue_t*, gchar **);
struct _ftype_t {
ftenum_t ftype;
@@ -110,6 +112,8 @@ struct _ftype_t {
FvalueSlice slice;
FvalueBitwiseAnd bitwise_and;
FvalueUnaryMinus unary_minus;
+ FvalueAdd add;
+ FvalueSubtract subtract;
};
void ftype_register(enum ftenum ftype, ftype_t *ft);
diff --git a/epan/ftypes/ftypes.c b/epan/ftypes/ftypes.c
index 8c33eb081f..b255461af3 100644
--- a/epan/ftypes/ftypes.c
+++ b/epan/ftypes/ftypes.c
@@ -219,6 +219,24 @@ ftype_can_unary_minus(enum ftenum ftype)
}
gboolean
+ftype_can_add(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ FTYPE_LOOKUP(ftype, ft);
+ return ft->add != NULL;
+}
+
+gboolean
+ftype_can_subtract(enum ftenum ftype)
+{
+ ftype_t *ft;
+
+ FTYPE_LOOKUP(ftype, ft);
+ return ft->subtract != NULL;
+}
+
+gboolean
ftype_can_contains(enum ftenum ftype)
{
ftype_t *ft;
@@ -822,6 +840,38 @@ fvalue_bitwise_and(const fvalue_t *a, const fvalue_t *b, char **err_msg)
return result;
}
+fvalue_t *
+fvalue_add(const fvalue_t *a, const fvalue_t *b, gchar **err_msg)
+{
+ fvalue_t *result;
+
+ /* XXX - check compatibility of a and b */
+ ws_assert(a->ftype->add);
+
+ result = fvalue_new(a->ftype->ftype);
+ if (a->ftype->add(result, a, b, err_msg) != FT_OK) {
+ fvalue_free(result);
+ return NULL;
+ }
+ return result;
+}
+
+fvalue_t *
+fvalue_subtract(const fvalue_t *a, const fvalue_t *b, gchar **err_msg)
+{
+ fvalue_t *result;
+
+ /* XXX - check compatibility of a and b */
+ ws_assert(a->ftype->subtract);
+
+ result = fvalue_new(a->ftype->ftype);
+ if (a->ftype->subtract(result, a, b, err_msg) != FT_OK) {
+ fvalue_free(result);
+ return NULL;
+ }
+ return result;
+}
+
fvalue_t*
fvalue_unary_minus(const fvalue_t *fv, char **err_msg)
{
diff --git a/epan/ftypes/ftypes.h b/epan/ftypes/ftypes.h
index 3d87dc25de..01336b524a 100644
--- a/epan/ftypes/ftypes.h
+++ b/epan/ftypes/ftypes.h
@@ -188,6 +188,12 @@ ftype_can_bitwise_and(enum ftenum ftype);
gboolean
ftype_can_unary_minus(enum ftenum ftype);
+gboolean
+ftype_can_add(enum ftenum ftype);
+
+gboolean
+ftype_can_subtract(enum ftenum ftype);
+
WS_DLL_PUBLIC
gboolean
ftype_can_contains(enum ftenum ftype);
@@ -377,6 +383,12 @@ fvalue_bitwise_and(const fvalue_t *a, const fvalue_t *b, char **err_msg);
fvalue_t*
fvalue_unary_minus(const fvalue_t *fv, char **err_msg);
+fvalue_t*
+fvalue_add(const fvalue_t *a, const fvalue_t *b, gchar **err_msg);
+
+fvalue_t*
+fvalue_subtract(const fvalue_t *a, const fvalue_t *b, gchar **err_msg);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */