]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add t_rules flag "list_as_attr"
authorAlan T. DeKok <aland@freeradius.org>
Mon, 6 Dec 2021 17:27:16 +0000 (12:27 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 7 Dec 2021 13:32:22 +0000 (08:32 -0500)
which encodes the list in the tmpl attribute reference structure

@todo - if there's no list prefix AND the flag is set, the
tokenizer should statically determine the list prefix, and set
the correct attribute reference.  This would prevent those checks
being done at run-time in tmpl_pair_cursor_init()

src/lib/server/tmpl.h
src/lib/server/tmpl_eval.c
src/lib/server/tmpl_tokenize.c
src/lib/unlang/compile.c

index d917916a55b66076a1893193f1cb17d22dd0a57a..f572edcc9070252708f73a7e7f0e017190ccfc11 100644 (file)
@@ -317,6 +317,8 @@ struct tmpl_rules_s {
        bool                    at_runtime;             //!< Produce an ephemeral/runtime tmpl.
                                                        ///< Instantiated xlats are not added to the global
                                                        ///< trees, regexes are not JIT'd.
+       bool                    list_as_attr;           //!< return #TMPL_TYPE_ATTR for lists, and not #TMPL_TYPE_LIST
+
 
        fr_event_list_t         *runtime_el;            //!< The eventlist to use for runtime instantiation
                                                        ///< of xlats.
index be24e382a390d9eee1dd7d0ed02cce6dfeb6a5e5..9962e5b44c12f92176f19abea2e962e6b69f36f7 100644 (file)
@@ -1081,7 +1081,7 @@ fr_pair_t *tmpl_pair_cursor_init(int *err, TALLOC_CTX *ctx, tmpl_pair_cursor_ctx
                                 fr_dcursor_t *cursor, request_t *request, tmpl_t const *vpt)
 {
        fr_pair_t               *vp = NULL;
-       fr_pair_list_t          *list_head;
+       fr_pair_list_t          *list_head = NULL;
        tmpl_request_t          *rr = NULL;
        TALLOC_CTX              *list_ctx;
 
@@ -1108,18 +1108,44 @@ fr_pair_t *tmpl_pair_cursor_init(int *err, TALLOC_CTX *ctx, tmpl_pair_cursor_ctx
        }
 
        /*
-        *      Get the right list in the specified context
+        *      If the rules say "return the list as an attribute",
+        *      then check for that.  But if the first da isn't a
+        *      list, then default to whatever list ref is given.
+        *
+        *      @todo - for the future, have the tokenizer (or
+        *      whatever) always add the list head to the list of
+        *      attribute references.
         */
-       list_head = tmpl_list_head(request, tmpl_list(vpt));
+       if (vpt->rules.list_as_attr) {
+               tmpl_attr_t const *ar;
+
+               ar = fr_dlist_head(&vpt->data.attribute.ar);
+               fr_assert(ar != NULL);
+
+               if ((ar->ar_da == request_attr_request) ||
+                   (ar->ar_da == request_attr_reply) ||
+                   (ar->ar_da == request_attr_control) ||
+                   (ar->ar_da == request_attr_state)) {
+                       list_head = &request->pair_root->vp_group;
+                       list_ctx = request->pair_root;
+               }
+       }
+
        if (!list_head) {
-               if (err) {
-                       *err = -2;
-                       fr_strerror_printf("List \"%s\" not available in this context",
-                                          fr_table_str_by_value(pair_list_table, tmpl_list(vpt), "<INVALID>"));
+               /*
+                *      Get the right list in the specified context
+                */
+               list_head = tmpl_list_head(request, tmpl_list(vpt));
+               if (!list_head) {       
+                       if (err) {
+                               *err = -2;
+                               fr_strerror_printf("List \"%s\" not available in this context",
+                                                  fr_table_str_by_value(pair_list_table, tmpl_list(vpt), "<INVALID>"));
+                       }
+                       goto error;
                }
-               goto error;
+               list_ctx = tmpl_list_ctx(request, tmpl_list(vpt));
        }
-       list_ctx = tmpl_list_ctx(request, tmpl_list(vpt));
 
        /*
         *      Initialise the temporary cursor context
index b7583f5bd594828a75adc94965b7c3138b7e0f04..9b10002fec227c818ef7ac78ca153327982c1e1a 100644 (file)
@@ -1830,7 +1830,7 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
                               tmpl_rules_t const *t_rules)
 {
        int                     ret;
-       size_t                  list_len;
+       size_t                  list_len = 0;
        tmpl_t                  *vpt;
        fr_sbuff_t              our_name = FR_SBUFF(name);      /* Take a local copy in case we need to back track */
        bool                    ref_prefix = false;
@@ -1896,37 +1896,39 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
 
        fr_sbuff_marker(&m_l, &our_name);
 
-       /*
-        *      Parse the list reference
-        *
-        *      This code should be removed when lists
-        *      are integrated into attribute references.
-        */
-       fr_sbuff_out_by_longest_prefix(&list_len, &vpt->data.attribute.list, pair_list_table,
-                                      &our_name, t_rules->list_def);
+       if (!t_rules->list_as_attr) {
+               /*
+                *      Parse the list reference
+                *
+                *      This code should be removed when lists
+                *      are integrated into attribute references.
+                */
+               fr_sbuff_out_by_longest_prefix(&list_len, &vpt->data.attribute.list, pair_list_table,
+                                              &our_name, t_rules->list_def);
 
-       /*
-        *      Check if we need to backtrack
-        *
-        *      Lists can be followed by a '.', '[', or the end of the attribute reference
-        *
-        *      If we don't find any of those things it wasn't an actual list match
-        *      but one of the list identifiers matched part of an attribute reference.
-        *
-        *      i.e. reply with reply-message.
-        */
-       if ((list_len > 0) && !fr_sbuff_is_char(&our_name, '.') &&
-           !fr_sbuff_is_char(&our_name, '[') && !tmpl_substr_terminal_check(&our_name, p_rules)) {
-               fr_sbuff_set(&our_name, &m_l);
-               list_len = 0;
-               vpt->data.attribute.list = t_rules->list_def;
-       }
+               /*
+                *      Check if we need to backtrack
+                *
+                *      Lists can be followed by a '.', '[', or the end of the attribute reference
+                *
+                *      If we don't find any of those things it wasn't an actual list match
+                *      but one of the list identifiers matched part of an attribute reference.
+                *
+                *      i.e. reply with reply-message.
+                */
+               if ((list_len > 0) && !fr_sbuff_is_char(&our_name, '.') &&
+                   !fr_sbuff_is_char(&our_name, '[') && !tmpl_substr_terminal_check(&our_name, p_rules)) {
+                       fr_sbuff_set(&our_name, &m_l);
+                       list_len = 0;
+                       vpt->data.attribute.list = t_rules->list_def;
+               }
 
-       if ((t_rules->attr_parent || t_rules->disallow_qualifiers) && (list_len > 0)) {
-               fr_strerror_const("It is not permitted to specify a pair list here");
-               if (err) *err = TMPL_ATTR_ERROR_INVALID_LIST_QUALIFIER;
-               talloc_free(vpt);
-               FR_SBUFF_ERROR_RETURN(&our_name);
+               if ((t_rules->attr_parent || t_rules->disallow_qualifiers) && (list_len > 0)) {
+                       fr_strerror_const("It is not permitted to specify a pair list here");
+                       if (err) *err = TMPL_ATTR_ERROR_INVALID_LIST_QUALIFIER;
+                       talloc_free(vpt);
+                       FR_SBUFF_ERROR_RETURN(&our_name);
+               }
        }
 
        /*
index 6bd568fe9972b350c3a6e261edd2380b9aeb5b73..ab598c6771b9f44e14800c121d0686c37ce46611 100644 (file)
@@ -1546,6 +1546,7 @@ static unlang_t *compile_edit(unlang_t *parent, unlang_compile_t *unlang_ctx, un
         */
        t_rules = *(unlang_ctx->rules);
        t_rules.allow_unknown = true;
+       t_rules.list_as_attr = true;
        RULES_VERIFY(&t_rules);
 
        c = *prev;