From: Alan T. DeKok Date: Mon, 2 Sep 2024 21:33:49 +0000 (-0400) Subject: enable expressions in attribute array indexes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e35195a6b0839637be6c056f1cd7c5a2d6687044;p=thirdparty%2Ffreeradius-server.git enable expressions in attribute array indexes alonw with test and documentation --- diff --git a/doc/antora/modules/reference/pages/unlang/attr.adoc b/doc/antora/modules/reference/pages/unlang/attr.adoc index bb6080fef1d..ca3e06e93d3 100644 --- a/doc/antora/modules/reference/pages/unlang/attr.adoc +++ b/doc/antora/modules/reference/pages/unlang/attr.adoc @@ -51,7 +51,7 @@ you to address the attributes as if they were array entries. The refers to the first attributes, `[1]` refers to the second attribute, etc. -The `` can be an integer (0..1000), as in the example below. +The `` can be an integer (0..1000). The indexes are limited to 1000, because there are essentially no protocols which have more than 1000 attributes. @@ -63,7 +63,15 @@ protocols which have more than 1000 attributes. &reply.NAS-IP-Address[2] ---- -The `` can also be a reference to a numerical attribute, as in the example below. +The `` can also be a special value `n`, which means "the last attribute in the list. + +.Last attribute in a list +[source,unlang] +---- +&EAP-Message[n] +---- + +The `` can also be a reference to a numerical attribute. The reference *must* be to an attribute of numerical data type. Structural data types and `string` or `octets` types are not allowed. If the index is out of bounds (e.g. negative), then the reference fails. @@ -79,12 +87,18 @@ uint32 foo &EAP-Message[&foo] ---- -The `` can also be a special value `n`, which means "the last attribute in the list. +The `` can also be an expression which is calculated at run time. The expression _must_ not cause the server to call an external database, script, etc. The main purpose of these expressions is to calculated an index without first placing it into another attribute. -.Last attribute in a list +If the index must be calculated from an external database call or script, simply place that value into an attribute first, and then use that attribute as in index. + +The expression _must_ be in an expansion block: `%{...}`. + +.Expression as an Array index [source,unlang] ---- -&EAP-Message[n] +&index = 0 + +&EAP-Message[%{&index + 1}] ---- === Array References in lists diff --git a/src/lib/server/tmpl_dcursor.c b/src/lib/server/tmpl_dcursor.c index 18f1d13d7a1..375e55b909f 100644 --- a/src/lib/server/tmpl_dcursor.c +++ b/src/lib/server/tmpl_dcursor.c @@ -175,6 +175,19 @@ fr_pair_t *_tmpl_cursor_eval(fr_pair_t *curr, tmpl_dcursor_ctx_t *cc) if (ar_filter_is_none(ar)) { num = 0; + } else if (ar_filter_is_expr(ar)) { + fr_value_box_t box; + request_t *request = cc->request; + + if (unlang_xlat_eval_type(request, &box, FR_TYPE_UINT8, NULL, request, ar->ar_expr) < 0) { + RPEDEBUG("Failed evaluating expression"); + vp = NULL; + pop = true; + goto done; + } + + num = box.vb_uint8; + } else if (!ar_filter_is_num(ar)) { request_t *request = cc->request; diff --git a/src/tests/keywords/attr-index-expr b/src/tests/keywords/attr-index-expr new file mode 100644 index 00000000000..c7e883c44e8 --- /dev/null +++ b/src/tests/keywords/attr-index-expr @@ -0,0 +1,29 @@ +# +# PRE: attr-index +# +# Tests for using attribute references as array index +# +uint32 index + +&request += { + &Class = 0x01020304, + &Class = 0x05060708, + &Class = 0x090a0b0c, +} + +# +# Computed indexes, with some limitations +# +&index := 1 + +if (&Class[%{&index - 1}] != 0x01020304) { + test_fail +} + +&index := 4 + +if (&Class[%{&index - 2}] != 0x090a0b0c) { + test_fail +} + +success