From: Alan T. DeKok Date: Sat, 20 Nov 2021 19:59:15 +0000 (-0500) Subject: add preliminary support for and/or X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=58d2816e02c911f33a861de3b39e901ab96d1b51;p=thirdparty%2Ffreeradius-server.git add preliminary support for and/or we likely also want to allow ipaddr AND integer -> ipv4prefix tho that' a little more work to figure stuff out --- diff --git a/src/bin/unit_test_attribute.c b/src/bin/unit_test_attribute.c index ad289edd0d1..f11bdad7098 100644 --- a/src/bin/unit_test_attribute.c +++ b/src/bin/unit_test_attribute.c @@ -1174,6 +1174,8 @@ static const fr_token_t token2op[UINT8_MAX + 1] = { [ '/' ] = T_DIV, [ '^' ] = T_OP_PREPEND, [ '.' ] = T_ADD, + [ '&' ] = T_AND, + [ '|' ] = T_OR, }; /** Perform calculations diff --git a/src/lib/util/calc.c b/src/lib/util/calc.c index a6af2dea811..ec0b9446233 100644 --- a/src/lib/util/calc.c +++ b/src/lib/util/calc.c @@ -403,6 +403,38 @@ static int calc_octets(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t cons fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, a->tainted | b->tainted); break; + case T_AND: + if (a->vb_length != b->vb_length) { + length_error: + fr_strerror_const("Cannot perform operation on strings of different length"); + return -1; + } + + buf = talloc_array(ctx, uint8_t, a->vb_length); + if (!buf) goto oom; + + for (len = 0; len < a->vb_length; len++) { + buf[len] = a->vb_octets[len] & b->vb_octets[len]; + } + + fr_value_box_clear_value(dst); + fr_value_box_memdup_shallow(dst, dst->enumv, buf, a->vb_length, a->tainted | b->tainted); + break; + + case T_OR: + if (a->vb_length != b->vb_length) goto length_error; + + buf = talloc_array(ctx, uint8_t, a->vb_length); + if (!buf) goto oom; + + for (len = 0; len < a->vb_length; len++) { + buf[len] = a->vb_octets[len] | b->vb_octets[len]; + } + + fr_value_box_clear_value(dst); + fr_value_box_memdup_shallow(dst, dst->enumv, buf, a->vb_length, a->tainted | b->tainted); + break; + default: return ERR_INVALID; /* invalid operator */ } @@ -813,6 +845,14 @@ static int calc_float64(UNUSED TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_bo case T_DIV: \ dst->vb_ ## _t = in1->vb_ ## _t / in2->vb_ ## _t; \ break; \ + \ + case T_AND: \ + dst->vb_ ## _t = in1->vb_ ## _t & in2->vb_ ## _t; \ + break; \ + \ + case T_OR: \ + dst->vb_ ## _t = in1->vb_ ## _t | in2->vb_ ## _t; \ + break; \ \ default: \ return ERR_INVALID; \ @@ -1126,6 +1166,8 @@ int fr_value_calc_binary_op(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t hint case T_SUB: case T_MUL: case T_DIV: + case T_AND: + case T_OR: case T_OP_PREPEND: fr_assert(hint != FR_TYPE_NULL); diff --git a/src/lib/util/token.c b/src/lib/util/token.c index 2950cde0df1..706cb400acd 100644 --- a/src/lib/util/token.c +++ b/src/lib/util/token.c @@ -84,6 +84,8 @@ char const *fr_tokens[T_TOKEN_LAST] = { [T_SUB] = "-", [T_MUL] = "*", [T_DIV] = "/", + [T_AND] = "&", + [T_OR] = "|", [T_OP_INCRM] = "++", @@ -169,6 +171,8 @@ const bool fr_binary_op[T_TOKEN_LAST] = { T(SUB), T(MUL), T(DIV), + T(AND), + T(OR), }; diff --git a/src/lib/util/token.h b/src/lib/util/token.h index 6bf29f0eb88..13519353b92 100644 --- a/src/lib/util/token.h +++ b/src/lib/util/token.h @@ -49,6 +49,8 @@ typedef enum fr_token { T_SUB, /* - */ T_MUL, /* * */ T_DIV, /* / */ + T_AND, /* & */ + T_OR, /* | */ /* * Only used by LDAP ??? diff --git a/src/tests/unit/calc.txt b/src/tests/unit/calc.txt index 25537ca25cc..a410c5232bc 100644 --- a/src/tests/unit/calc.txt +++ b/src/tests/unit/calc.txt @@ -2,6 +2,10 @@ # Calculate various thingies. # +###################################################################### +# +# integers +# calc uint8 255 + uint8 255 -> uint8 match Value overflows/underflows when calculating answer for uint8 @@ -19,6 +23,9 @@ match 13 calc int32 -1 + uint8 14 -> int16 match 13 +calc int8 0x7f & uint8 0x40 -> uint8 +match 64 + # # Intermediate values are too large for destination, but the # resulting value can fit. @@ -26,6 +33,18 @@ match 13 calc uint32 1000 - uint32 999 -> uint8 match 1 +# this can be cast +calc string "1" < uint32 2 -> bool +match yes + +# this can't +calc string "stuff" < uint32 2 -> bool +match Failed parsing string as type 'uint32' + +###################################################################### +# +# strings +# # string append calc string "a" . string "b" -> string match ab @@ -34,6 +53,10 @@ match ab calc string "ab" - string "b" -> string match a +###################################################################### +# +# octets +# # octets prepend calc octets "a" ^ octets "b" -> octets match 0x6261 @@ -46,7 +69,20 @@ match 0x6162 calc octets "ab" - octets "b" -> octets match 0x61 +calc octets "a" & octets "b" -> octets +match 0x60 + +calc octets "a" | octets "b" -> octets +match 0x63 + +# we can "fake out" structs by just appending stuff +calc ipaddr 127.0.0.1 . ipaddr 127.0.0.2 -> octets +match 0x7f0000017f000002 +###################################################################### +# +# times and dates +# # time deltas calc time_delta 1 + time_delta 2 -> time_delta match 3 @@ -68,17 +104,10 @@ match Jan 10 1970 00:00:00 UTC calc date "Jan 11 1970 00:00:00 UTC" < date "Jan 1 1970 00:00:00 UTC" match no -# we can "fake out" structs by just appending stuff -calc ipaddr 127.0.0.1 . ipaddr 127.0.0.2 -> octets -match 0x7f0000017f000002 - -# this can be cast -calc string "1" < uint32 2 -> bool -match yes - -# this can't -calc string "stuff" < uint32 2 -> bool -match Failed parsing string as type 'uint32' +###################################################################### +# +# ip addresses and prefixes +# # # make an IP out of a prefix and an offset @@ -107,4 +136,4 @@ calc string "2" += string "test" match 2test count -match 48 +match 54