]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
v4: Convert lists of fr_value_box_t to doubly linked lists (#3964)
authorNick Porter <nick@portercomputing.co.uk>
Mon, 1 Mar 2021 17:13:41 +0000 (17:13 +0000)
committerGitHub <noreply@github.com>
Mon, 1 Mar 2021 17:13:41 +0000 (17:13 +0000)
* Typo in dlist.h

* Make fr_value_box_list_t a dlist header

* Add initialisation function for list of fr_value_box_t

* Amend other structs containing lists of value boxes to use fr_value_box_list_t

* Replace fr_cursor use with fr_dcursors

* Amend exiting fr_value_box_list helper functions to use dlist properties

* Initialise lists of fr_value_box_t

* Use fr_dlist_empty() to test for empty lists of fr_value_box_t

* Alter fr_value_box_clear_value() to correctly clear child lists.

* Amend fr_vasprintf() to correctly take fr_value_box_list_t for %pM parameter

and differentiate between logging a single fr_value_box_t and a
fr_value_box_list_t.

* Use fr_dlist_talloc_free() to free fr_value_box_list_t

* Use dlist functions to walk fr_value_box_list_t

* Amend unlang_xlat_push() to take fr_value_box_list_t

* Amend definition of xlat_func_t and xlat_funct_resume_t ...

... to take fr_value_box_list_t

* Amend xlat_func_base64_encode() to take fr_value_box_list_t

* Amend xlat_func_base64_decode() to take fr_value_box_list_t

* Amend xlat_func_bin() to take fr_value_box_list_t

* Amend xlat_func_concat() to take fr_value_box_list_t

* Amend xlat_func_hex() to take fr_value_box_list_t

* Amend xlat_hmac() to take fr_value_box_list_t

* Amend xlat_func_hmac_* to use fr_value_box_list_t

* Amend xlat_func_length() to take fr_value_box_list_t

* Amend xlat_func_md4() to take fr_value_box_list_t

* Amend xlat_func_md5() to take fr_value_box_list_t

* Amend xlat_func_pairs() to take fr_value_box_list_t

* Amend xlat_func_rand() to take fr_value_box_list_t

* Amend xlat_func_randstr() to take fr_value_box_list_t

* Amend xlat_func_regex() to take fr_value_box_list_t

* Amend xlat_func_sha1() to take fr_value_box_list_t

* Amend xlat_func_##_md to take fr_value_pair_list_t

* Amend xlat_func_string() to take fr_value_box_list_t

* Amend xlat_func_strlen() to take fr_value_box_list_t

* Amend xlat_func_sub_regex() to take fr_value_box_list_t

* Amend xlat_func_sub() to take fr_value_box_list_t

* Amend case change xlat_funcs to take fr_value_box_list_t

* Amend xlat_func_urlquote() to take fr_value_box_list_t

* Amend xlat_func_urlunquote() to take fr_value_box_list_t

* Amend remaining builtin xlat funcs to take fr_value_box_list_t

* Amend always_xlat() to take fr_value_box_list_t

* Amend xlat_func_chap_password() to take fr_value_box_list_t

* Amend cipher_rsa_encrypt_xlat() to take fr_value_box_list_t

* Amend cipher_rsa_sign_xlat() to take fr_value_box_list_t

* Amend cipher_rsa_decrypt_xlat() to take fr_value_box_list_t

* Amend cipher_rsa_verify_xlat() to take fr_value_box_list_t

* Amend xlat_delay() and xlat_delay_resume() to take fr_value_box_list_t

* Amend dhcp4_decode_xlat and dhcpv4_encode_xlat to take fr_value_box_list_t

* Amend xlat_icmp_resume() and xlat_icmp() to take fr_value_box_list_t

* Amend rest_xlat() and rest_xlat_resume() to take fr_value_box_list_t

* Amend redis_remap_xlat() to take fr_value_box_list_t

* Amend redis_node_xlat() to take fr_value_box_list_t

* Amend json_quote_xlat() to take fr_value_box_list_t

* Amend json_encode_xlat() to take fr_value_box_list_t

* Correctly initialise dlist entry in fr_value_box_copy_meta()

* Amend fr_value_box_list_concat() to take fr_value_box_list_t

* Amend fr_value_box_list_aprint() to take fr_value_box_list_t

* Amend fr_value_box_list_acopy() to take fr_value_box_list_t

* Amend fr_value_box_list_tainted() to take fr_value_box_list_t

* Remove unused function fr_value_box_list_get()

* Amend fr_value_box_list_flatten_argv() to take fr_value_box_list_t

* Amend map_proc() to take fr_value_box_list_t

* Amend definition of map_proc_func_t to take fr_value_box_list_t

* Amend rlm_client map_proc_client() to take fr_value_box_list_t

* Amend rlm_csv mod_map_proc() to take fr_value_box_list_t

* Amend rlm_json mod_map_proc() to take fr_value_box_list_t

* Amend rlm_ldap mod_map_proc() to take fr_value_box_list_t

* Amend map_to_list_mod() to take fr_value_box_list_t

* Maintain list pointers when performing cast in place on fr_value_box_t

* Amend unlang_module_yield_to_*() to take fr_value_box_list_t

* Amend rlm_sql mod_map_proc() to take fr_value_box_list_t

* Initialise list entry pointers correctly

* Amend fr_jpath_evaluate_leaf to take fr_value_box_list_t

* Amend unlang_tmpl_push() to take fr_value_box_list_t

* Amend unlang_tmpl_resume() to add fr_value_box_t to new list header

* Amend unlang_tmpl_exec_wait_final() to populate box and add to list header

* Alter fr_exec_nowait() to take fr_value_box_list_t

* Amend fr_exec_wait_start() to take fr_value_box_list_t

* Amend unit_test_module mod_map_proc() to take fr_value_box_list_t

* Handle fr_value_box_list_t in list_mod_create(), map_proc_apply() ...

... and unlang_map_state_init()

* Amend xlat_frame_eval_resume() to take fr_value_box_list_t

* Amend xlat_frame_eval_repeat() to handle fr_value_box_list_t

* Amend xlat_sync_eval() to hand fr_value_box_list_t

* Amend _json_map_proc_get_value() to take handle fr_value_box_list_t

* Pass parent to fr_value_box_cast_to_strvalue() to extract children as string

* Amend mod_exec_nowait_resume(), mod_exec_wait_resume() and mod_exec_dispatch()

... to handle fr_value_box_list_t

* Comment out code which allows for a fr_value_box_t in a fr_tmpl_t ...

... to be the head of a singly linked list.

Now that lists of fr_value_box_t are doubly linked lists, this will
no-longer work.

Code left in place commented out as a reminder as to where this
behaviour was used.

39 files changed:
src/bin/unit_test_module.c
src/lib/json/base.h
src/lib/json/jpath.c
src/lib/server/exec.c
src/lib/server/exec.h
src/lib/server/map.h
src/lib/server/map_async.c
src/lib/server/map_proc.c
src/lib/server/map_proc.h
src/lib/server/trigger.c
src/lib/unlang/map.c
src/lib/unlang/module.c
src/lib/unlang/module.h
src/lib/unlang/tmpl.c
src/lib/unlang/tmpl.h
src/lib/unlang/tmpl_priv.h
src/lib/unlang/xlat.c
src/lib/unlang/xlat.h
src/lib/unlang/xlat_builtin.c
src/lib/unlang/xlat_eval.c
src/lib/unlang/xlat_priv.h
src/lib/util/base.h
src/lib/util/print.c
src/lib/util/value.c
src/lib/util/value.h
src/modules/rlm_always/rlm_always.c
src/modules/rlm_chap/rlm_chap.c
src/modules/rlm_cipher/rlm_cipher.c
src/modules/rlm_client/rlm_client.c
src/modules/rlm_csv/rlm_csv.c
src/modules/rlm_delay/rlm_delay.c
src/modules/rlm_dhcpv4/rlm_dhcpv4.c
src/modules/rlm_exec/rlm_exec.c
src/modules/rlm_icmp/rlm_icmp.c
src/modules/rlm_json/rlm_json.c
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_redis/rlm_redis.c
src/modules/rlm_rest/rlm_rest.c
src/modules/rlm_sql/rlm_sql.c

index a3d9149afd8b682c7d301f9a3157c62bdb035a44..9b5c27982de3293e1db6f4be6c1ed7ff3d191519 100644 (file)
@@ -451,7 +451,7 @@ static int map_proc_verify(CONF_SECTION *cs, UNUSED void *mod_inst, UNUSED void
 }
 
 static rlm_rcode_t mod_map_proc(UNUSED void *mod_inst, UNUSED void *proc_inst, UNUSED request_t *request,
-                               UNUSED fr_value_box_t **src, UNUSED fr_map_list_t const *maps)
+                               UNUSED fr_value_box_list_t *src, UNUSED fr_map_list_t const *maps)
 {
        return RLM_MODULE_FAIL;
 }
index 729fae87fe147122d0f0ca5d8807c0f288463d7a..195c211c0e25452276b915ec6c274557a43cd967 100644 (file)
@@ -241,7 +241,7 @@ typedef struct fr_jpath_node fr_jpath_node_t;
 size_t         fr_jpath_escape_func(UNUSED request_t *request, char *out, size_t outlen,
                                     char const *in, UNUSED void *arg);
 
-int            fr_jpath_evaluate_leaf(TALLOC_CTX *ctx, fr_value_box_t **out,
+int            fr_jpath_evaluate_leaf(TALLOC_CTX *ctx, fr_value_box_list_t *out,
                                       fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
                                       json_object *root, fr_jpath_node_t const *jpath);
 
index 5e72a91c290cb639ec7e6854cb90cae818e7db8c..ef385cb0692717eb7511532f035503bc40f861c3 100644 (file)
@@ -128,7 +128,7 @@ size_t fr_jpath_escape_func(UNUSED request_t *request, char *out, size_t outlen,
 /** Recursive function for jpath_expr_evaluate
  *
  * @param[in,out] ctx to allocate fr_value_box_t in.
- * @param[out] tail Where to write fr_value_box_t (**).
+ * @param[out] tail Where to write fr_value_box_t.
  * @param[in] dst_type FreeRADIUS type to convert to.
  * @param[in] dst_enumv Enumeration values to allow string to integer conversions.
  * @param[in] object current node in the json tree.
@@ -138,7 +138,7 @@ size_t fr_jpath_escape_func(UNUSED request_t *request, char *out, size_t outlen,
  *     - 0 on no match.
  *     - -1 on error.
  */
-static int jpath_evaluate(TALLOC_CTX *ctx, fr_value_box_t ***tail,
+static int jpath_evaluate(TALLOC_CTX *ctx, fr_value_box_list_t *tail,
                          fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
                          json_object *object, fr_jpath_node_t const *jpath)
 {
@@ -360,8 +360,7 @@ static int jpath_evaluate(TALLOC_CTX *ctx, fr_value_box_t ***tail,
                return -1;
        }
 
-       **tail = value;
-       *tail = &(**tail)->next;
+       fr_dlist_insert_tail(tail, value);
        return 1;
 }
 
@@ -381,14 +380,10 @@ static int jpath_evaluate(TALLOC_CTX *ctx, fr_value_box_t ***tail,
  *     - 0 on no match.
  *     - -1 on error.
  */
-int fr_jpath_evaluate_leaf(TALLOC_CTX *ctx, fr_value_box_t **out,
+int fr_jpath_evaluate_leaf(TALLOC_CTX *ctx, fr_value_box_list_t *out,
                           fr_type_t dst_type, fr_dict_attr_t const *dst_enumv,
                           json_object *root, fr_jpath_node_t const *jpath)
 {
-       fr_value_box_t **tail = out;
-
-       *tail = NULL;
-
        if (!root) return -1;
 
        switch (jpath->selector->type) {
@@ -401,7 +396,7 @@ int fr_jpath_evaluate_leaf(TALLOC_CTX *ctx, fr_value_box_t **out,
                return -1;
        }
 
-       return jpath_evaluate(ctx, &tail, dst_type, dst_enumv, root, jpath->next);
+       return jpath_evaluate(ctx, out, dst_type, dst_enumv, root, jpath->next);
 }
 
 /** Print a node list to a string for debugging
index 18a73815834babf2ce2f96795e7fa27b3035c5f4..f50db3ff229a144c74d8d4f8b399bc1160ef8417 100644 (file)
@@ -598,7 +598,7 @@ wait:
 /** Execute a program without waiting for the program to finish.
  *
  * @param request      the request
- * @param vb           as returned by xlat_frame_eval()
+ * @param vb_list      as returned by xlat_frame_eval()
  * @param env_pairs    VPs to put into into the environment.  May be NULL.
  * @return
  *     - <0 on error
@@ -608,7 +608,7 @@ wait:
  *  would allow finer-grained control over the attributes to put into
  *  the environment.
  */
-int fr_exec_nowait(request_t *request, fr_value_box_t *vb, fr_pair_list_t *env_pairs)
+int fr_exec_nowait(request_t *request, fr_value_box_list_t *vb_list, fr_pair_list_t *env_pairs)
 {
        int             argc;
        char            **envp;
@@ -619,8 +619,8 @@ int fr_exec_nowait(request_t *request, fr_value_box_t *vb, fr_pair_list_t *env_p
        /*
         *      Ensure that we don't do anything stupid.
         */
-       first =  fr_value_box_list_get(vb, 0);
-       if (first->type == FR_TYPE_GROUP) first = first->vb_group;
+       first =  fr_dlist_head(vb_list);
+       if (first->type == FR_TYPE_GROUP) first = fr_dlist_head(&first->vb_group);
        if (first->tainted) {
                fr_strerror_printf("Program to run comes from tainted source - %pV", first);
                return -1;
@@ -637,7 +637,7 @@ int fr_exec_nowait(request_t *request, fr_value_box_t *vb, fr_pair_list_t *env_p
                envp[0] = NULL;
        }
 
-       argc = fr_value_box_list_flatten_argv(request, &argv, vb);
+       argc = fr_value_box_list_flatten_argv(request, &argv, vb_list);
        if (argc < 0) {
                talloc_free(envp);
                return -1;
@@ -688,7 +688,7 @@ int fr_exec_nowait(request_t *request, fr_value_box_t *vb, fr_pair_list_t *env_p
  *  and closing it.
  *
  * @param request      the request
- * @param vb           as returned by xlat_frame_eval()
+ * @param vb_list      as returned by xlat_frame_eval()
  * @param env_pairs    VPs to put into into the environment.  May be NULL.
  * @param[out] pid_p   The PID of the child
  * @param[out] input_fd        The stdin FD of the child
@@ -701,7 +701,7 @@ int fr_exec_nowait(request_t *request, fr_value_box_t *vb, fr_pair_list_t *env_p
  *  would allow finer-grained control over the attributes to put into
  *  the environment.
  */
-int fr_exec_wait_start(request_t *request, fr_value_box_t *vb, fr_pair_list_t *env_pairs, pid_t *pid_p, int *input_fd, int *output_fd)
+int fr_exec_wait_start(request_t *request, fr_value_box_list_t *vb_list, fr_pair_list_t *env_pairs, pid_t *pid_p, int *input_fd, int *output_fd)
 {
        int             argc;
        char            **envp;
@@ -714,8 +714,8 @@ int fr_exec_wait_start(request_t *request, fr_value_box_t *vb, fr_pair_list_t *e
        /*
         *      Ensure that we don't do anything stupid.
         */
-       first =  fr_value_box_list_get(vb, 0);
-       if (first->type == FR_TYPE_GROUP) first = first->vb_group;
+       first =  fr_dlist_head(vb_list);
+       if (first->type == FR_TYPE_GROUP) first = fr_dlist_head(&first->vb_group);
        if (first->tainted) {
                fr_strerror_printf("Program to run comes from tainted source - %pV", first);
                return -1;
@@ -732,7 +732,7 @@ int fr_exec_wait_start(request_t *request, fr_value_box_t *vb, fr_pair_list_t *e
                envp[0] = NULL;
        }
 
-       argc = fr_value_box_list_flatten_argv(request, &argv, vb);
+       argc = fr_value_box_list_flatten_argv(request, &argv, vb_list);
        if (argc < 0) {
        error:
                talloc_free(envp);
index a3aeae1b130e698dfe6806057d9dd85b4594aa32..7baae851dada568342cb5a858d9c73c377789872 100644 (file)
@@ -56,9 +56,9 @@ int   radius_exec_program(TALLOC_CTX *ctx, char *out, size_t outlen, fr_pair_list_
                            request_t *request, char const *cmd, fr_pair_list_t *input_pairs,
                            bool exec_wait, bool shell_escape, fr_time_delta_t timeout) CC_HINT(nonnull (5, 6));
 
-int    fr_exec_nowait(request_t *request, fr_value_box_t *vb, fr_pair_list_t *env_pairs);
+int    fr_exec_nowait(request_t *request, fr_value_box_list_t *vb_list, fr_pair_list_t *env_pairs);
 
-int    fr_exec_wait_start(request_t *request, fr_value_box_t *vb, fr_pair_list_t *env_pairs, pid_t *pid_p, int *input_fd, int *output_fd);
+int    fr_exec_wait_start(request_t *request, fr_value_box_list_t *vb_list, fr_pair_list_t *env_pairs, pid_t *pid_p, int *input_fd, int *output_fd);
 
 void   fr_exec_waitpid(pid_t pid);
 
index 5af0cfb695b6d535c9d53588794ab98b4df01267..b8790b6e44857777482c091458f20b6fd4cbcbe1 100644 (file)
@@ -143,7 +143,7 @@ int         map_list_mod_apply(request_t *request, vp_list_mod_t const *vlm);
 
 int            map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                                request_t *request, map_t const *map,
-                               fr_value_box_t **lhs_result, fr_value_box_t **rhs_result);
+                               fr_value_box_list_t *lhs_result, fr_value_box_list_t *rhs_result);
 
 int            map_to_request(request_t *request, map_t const *map,
                               radius_map_getvalue_t func, void *ctx);
index 7c3ff8060de220a6778f47375a56b7f6a9705ede..252fe79edee323f471832e48571a68a2bf3220cc 100644 (file)
@@ -258,15 +258,14 @@ static inline fr_pair_list_t *map_check_src_or_dst(request_t *request, map_t con
  */
 int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                    request_t *request, map_t const *original,
-                   fr_value_box_t **lhs_result, fr_value_box_t **rhs_result)
+                   fr_value_box_list_t *lhs_result, fr_value_box_list_t *rhs_result)
 {
        vp_list_mod_t   *n = NULL;
-       map_t   map_tmp;
+       map_t           map_tmp;
        map_t const     *mutated = original;
 
-       fr_cursor_t     values;
-       fr_value_box_t  *head = NULL;
-
+       fr_dcursor_t    values;
+       fr_value_box_list_t     head;
        TALLOC_CTX      *tmp_ctx = NULL;
 
        MAP_VERIFY(original);
@@ -279,6 +278,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                   tmpl_is_xlat(original->lhs));
 
        *out = NULL;
+       fr_value_box_list_init(&head);
 
        /*
         *      Preprocessing of the LHS of the map.
@@ -301,6 +301,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
        case TMPL_TYPE_XLAT:
        {
                ssize_t slen;
+               fr_value_box_t *lhs_result_head = fr_dlist_head(lhs_result);
 
                /*
                 *      Get our own mutable copy of the original so we can
@@ -311,27 +312,27 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
 
                tmp_ctx = talloc_new(NULL);
 
-               fr_assert(lhs_result && *lhs_result);
+               fr_assert(!fr_dlist_empty(lhs_result));
 
                /*
                 *      This should always be a noop, but included
                 *      here for robustness.
                 */
-               if (fr_value_box_list_concat(*lhs_result, *lhs_result, lhs_result, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat(lhs_result_head, lhs_result_head, lhs_result, FR_TYPE_STRING, true) < 0) {
                        RPEDEBUG("Left side expansion failed");
-                       TALLOC_FREE(*lhs_result);
+                       fr_dlist_talloc_free(lhs_result);
                        goto error;
                }
 
-               slen = tmpl_afrom_attr_str(tmp_ctx, NULL, &map_tmp.lhs, (*lhs_result)->vb_strvalue,
+               slen = tmpl_afrom_attr_str(tmp_ctx, NULL, &map_tmp.lhs, lhs_result_head->vb_strvalue,
                                           &(tmpl_rules_t){
                                                .dict_def = request->dict,
                                                .prefix = TMPL_ATTR_REF_PREFIX_NO
                                           });
                if (slen <= 0) {
                        RPEDEBUG("Left side expansion result \"%s\" is not an attribute reference",
-                                (*lhs_result)->vb_strvalue);
-                       TALLOC_FREE(*lhs_result);
+                                lhs_result_head->vb_strvalue);
+                       fr_dlist_talloc_free(lhs_result);
                        goto error;
                }
                fr_assert(tmpl_is_attr(mutated->lhs) || tmpl_is_list(mutated->lhs));
@@ -448,7 +449,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                n = list_mod_generic_afrom_map(ctx, original, mutated);
                if (!n) goto error;
 
-               fr_cursor_init(&values, &head);
+               fr_dcursor_init(&values, &head);
 
                if (fr_value_box_from_str(fr_dlist_head(&n->mod),
                                          tmpl_value(fr_map_list_head(&n->mod)->rhs), &type,
@@ -465,13 +466,13 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
         */
        if (!map_check_src_or_dst(request, mutated, mutated->lhs)) goto error;
 
-       (void)fr_cursor_init(&values, &head);
+       (void)fr_dcursor_init(&values, &head);
 
        switch (mutated->rhs->type) {
        case TMPL_TYPE_XLAT:
        {
                fr_assert(tmpl_xlat(mutated->rhs) != NULL);
-               fr_cursor_t     from;
+               fr_dcursor_t    from;
                fr_value_box_t  *vb, *n_vb;
 
        assign_values:
@@ -484,13 +485,13 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                 *      happens.  This is only for XLATs and in future
                 *      EXECs.
                 */
-               if (!rhs_result || !*rhs_result) {
+               if (fr_dlist_empty(rhs_result)) {
                        n = list_mod_empty_string_afrom_map(ctx, original, mutated);
                        if (!n) {
                                RPEDEBUG("Assigning value to \"%s\" failed", tmpl_da(mutated->lhs)->name);
                        xlat_error:
-                               fr_cursor_head(&values);
-                               fr_cursor_free_list(&values);
+                               fr_dcursor_head(&values);
+                               fr_dcursor_free_list(&values);
                                goto error;
                        }
                        goto finish;
@@ -502,13 +503,13 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                n = list_mod_generic_afrom_map(ctx, original, mutated);
                if (!n) goto error;
 
-               (void)fr_cursor_init(&from, rhs_result);
-               while ((vb = fr_cursor_remove(&from))) {
+               (void)fr_dcursor_init(&from, rhs_result);
+               while ((vb = fr_dcursor_remove(&from))) {
                        if (vb->type != tmpl_da(mutated->lhs)->type) {
                                n_vb = fr_value_box_alloc_null(fr_map_list_head(&n->mod)->rhs);
                                if (!n_vb) {
-                                       fr_cursor_head(&from);
-                                       fr_cursor_free_list(&from);
+                                       fr_dcursor_head(&from);
+                                       fr_dcursor_free_list(&from);
                                        goto xlat_error;
                                }
 
@@ -517,15 +518,15 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                                                      tmpl_da(mutated->lhs), vb) < 0) {
                                        RPEDEBUG("Assigning value to \"%s\" failed", tmpl_da(mutated->lhs)->name);
 
-                                       fr_cursor_head(&from);
-                                       fr_cursor_free_list(&from);
+                                       fr_dcursor_head(&from);
+                                       fr_dcursor_free_list(&from);
                                        goto xlat_error;
                                }
                                talloc_free(vb);
                        } else {
                                n_vb = talloc_steal(n, vb);     /* Should already be in ctx of n's parent */
                        }
-                       fr_cursor_append(&values, n_vb);
+                       fr_dcursor_append(&values, n_vb);
                }
        }
                break;
@@ -538,7 +539,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                fr_value_box_t          *n_vb;
                int                     err;
 
-               fr_assert(!rhs_result || !*rhs_result);
+               fr_assert(fr_dlist_empty(rhs_result));
                fr_assert((tmpl_is_attr(mutated->lhs) && tmpl_da(mutated->lhs)) ||
                           (tmpl_is_list(mutated->lhs) && !tmpl_da(mutated->lhs)));
 
@@ -586,8 +587,8 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                        n_vb = fr_value_box_alloc_null(fr_map_list_head(&n->mod)->rhs);
                        if (!n_vb) {
                        attr_error:
-                               fr_cursor_head(&values);
-                               fr_cursor_free_list(&values);
+                               fr_dcursor_head(&values);
+                               fr_dcursor_free_list(&values);
                                tmpl_cursor_clear(&cc_attr);
                                goto error;
                        }
@@ -603,7 +604,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                        } else {
                                fr_value_box_copy(n_vb, n_vb, &vp->data);
                        }
-                       fr_cursor_append(&values, n_vb);
+                       fr_dcursor_append(&values, n_vb);
                } while ((vp = fr_dcursor_next(&from)));
 
                tmpl_cursor_clear(&cc_attr);
@@ -612,26 +613,29 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
 
        case TMPL_TYPE_DATA:
        {
-               fr_cursor_t     from;
-               fr_value_box_t  *vb, *vb_head, *n_vb;
+               /*
+                *      Commented out lines below are due to fr_value_box_t
+                *      now being in a dlist - so value box entries in a fr_tmpl_t
+                *      can no-longer be treated as the head of a list
+                */
+               fr_value_box_t  *vb, *n_vb;
+//             fr_value_box_t  *vb_head;
 
-               fr_assert(!rhs_result || !*rhs_result);
+               fr_assert(fr_dlist_empty(rhs_result));
                fr_assert(tmpl_da(mutated->lhs));
                fr_assert(tmpl_is_attr(mutated->lhs));
 
                n = list_mod_generic_afrom_map(ctx, original, mutated);
                if (!n) goto error;
 
-               vb_head = tmpl_value(mutated->rhs);
+               vb = tmpl_value(mutated->rhs);
 
-               for (vb = fr_cursor_init(&from, &vb_head);
-                    vb;
-                    vb = fr_cursor_next(&from)) {
+//             while ((vb = fr_dlist_next(vb_head, vb))) {
                        n_vb = fr_value_box_alloc_null(fr_map_list_head(&n->mod)->rhs);
                        if (!n_vb) {
                        data_error:
-                               fr_cursor_head(&values);
-                               fr_cursor_free_list(&values);
+                               fr_dcursor_head(&values);
+                               fr_dcursor_free_list(&values);
                                goto error;
                        }
                        /*
@@ -656,8 +660,8 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                                 */
                                if (fr_value_box_copy(n_vb, n_vb, vb) < 0) goto data_error;
                        }
-                       fr_cursor_append(&values, n_vb);
-               }
+                       fr_dcursor_append(&values, n_vb);
+//             }
        }
                break;
 
@@ -673,6 +677,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                fr_dcursor_t    from;
                fr_pair_list_t  vp_head;
                fr_pair_t       *vp;
+               fr_value_box_t  *rhs_result_head = fr_dlist_head(rhs_result);
 
                fr_pair_list_init(&vp_head);
                /*
@@ -689,7 +694,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                 *      happens.  This is only for XLATs and in future
                 *      EXECs.
                 */
-               if (!rhs_result || !*rhs_result) {
+               if (fr_dlist_empty(rhs_result)) {
                        RPEDEBUG("Cannot assign empty value to \"%s\"", mutated->lhs->name);
                        goto error;
                }
@@ -698,9 +703,9 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                 *      This should always be a noop, but included
                 *      here for robustness.
                 */
-               if (fr_value_box_list_concat(*rhs_result, *rhs_result, rhs_result, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat(rhs_result_head, rhs_result_head, rhs_result, FR_TYPE_STRING, true) < 0) {
                        RPEDEBUG("Right side expansion failed");
-                       TALLOC_FREE(*rhs_result);
+                       fr_dlist_talloc_free(rhs_result);
                        goto error;
                }
 
@@ -712,7 +717,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                /*
                 *      Parse the VPs from the RHS.
                 */
-               fr_pair_list_afrom_box(ctx, &vp_head, request->dict, *rhs_result);
+               fr_pair_list_afrom_box(ctx, &vp_head, request->dict, rhs_result_head);
                if (fr_pair_list_empty(&vp_head)) {
                        talloc_free(n);
                        RDEBUG2("No pairs returned by exec");
@@ -762,7 +767,7 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                goto error;
        }
 
-       fr_assert(head || !n);
+       fr_assert(!fr_dlist_empty(&head) || !n);
 
        /*
         *      FIXME: This is only required because
@@ -771,9 +776,13 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
         *      If tmpl_value were a pointer we could
         *      assign values directly.
         */
-       fr_value_box_copy(fr_map_list_head(&n->mod)->rhs, tmpl_value(fr_map_list_head(&n->mod)->rhs), head);
-       tmpl_value(fr_map_list_head(&n->mod)->rhs)->next = head->next;
-       talloc_free(head);
+       fr_value_box_copy(fr_map_list_head(&n->mod)->rhs, tmpl_value(fr_map_list_head(&n->mod)->rhs), fr_dlist_head(&head));
+       /*
+        *      value boxes in tmpls cannot now be the head of a list
+        *
+        *tmpl_value(fr_map_list_head(&n->mod)->rhs)->next = head->next;
+        */
+       fr_dlist_talloc_free(&head);
 
 finish:
        if (n) {
@@ -823,7 +832,7 @@ static void map_list_mod_to_vps(TALLOC_CTX *ctx, fr_pair_list_t *list, vp_list_m
         *      Fast path...
         */
        mod = fr_dlist_head(&vlm->mod);
-       if ((vlm->mod.num_elements == 1) && !tmpl_value(mod->rhs)->next) {
+       if (vlm->mod.num_elements == 1) {
                fr_pair_t *vp;
                vp = map_list_mod_to_vp(ctx, mod->lhs, tmpl_value(mod->rhs));
                fr_pair_add(list, vp);
@@ -836,18 +845,22 @@ static void map_list_mod_to_vps(TALLOC_CTX *ctx, fr_pair_list_t *list, vp_list_m
        for (;
             mod;
             mod = fr_dlist_next(&vlm->mod, mod)) {
-               fr_value_box_t  *vb;
+               /*
+                *      Commented out lines due to fr_value_box_t lists now
+                *      being dlists
+                */
+//             fr_value_box_t  *vb;
                fr_pair_t       *vp;
 
-               for (vb = tmpl_value(mod->rhs);
-                    vb;
-                    vb = vb->next) {
-                       vp = map_list_mod_to_vp(ctx, mod->lhs, vb);
+//             for (vb = tmpl_value(mod->rhs);
+//                  vb;
+//                  vb = vb->next) {
+                       vp = map_list_mod_to_vp(ctx, mod->lhs, tmpl_value(mod->rhs));
                        if (!vp) {
                                fr_pair_list_free(list);
                        }
                        fr_pair_add(list, vp);
-               }
+//             }
        }
 }
 
@@ -972,11 +985,16 @@ int map_list_mod_apply(request_t *request, vp_list_mod_t const *vlm)
                 *      map_list_mod_debug()
                 */
                if (RDEBUG_ENABLED2) {
-                       for (vb = tmpl_value(mod->rhs);
-                            vb;
-                            vb = vb->next) {
+                       vb = tmpl_value(mod->rhs);
+               /*
+                *      Commented out lines due to fr_value_box_t lists now
+                *      being dlists
+                */
+//                     for (vb = tmpl_value(mod->rhs);
+//                          vb;
+//                          vb = vb->next) {
                                map_list_mod_debug(request, map, mod, vb->type != FR_TYPE_INVALID ? vb : NULL);
-                       }
+//                     }
                }
        }
        mod = fr_dlist_head(&vlm->mod); /* Reset */
@@ -1132,13 +1150,16 @@ int map_list_mod_apply(request_t *request, vp_list_mod_t const *vlm)
                 */
                if (tmpl_num(map->lhs) != NUM_ALL) {
                        fr_value_box_t  *vb = tmpl_value(fr_map_list_head(&vlm->mod)->rhs);
-
-                       do {
+                       /*
+                        *      Commented out loop due to fr_value_box_t now being
+                        *      in dlists
+                        */
+//                     do {
                                if (fr_value_box_cmp(vb, &found->data) == 0) {
                                        fr_dcursor_free_item(&list);
                                        goto finish;
                                }
-                       } while ((vb = vb->next));
+//                     } while ((vb = vb->next));
                        goto finish;    /* Wasn't found */
                }
 
@@ -1150,13 +1171,16 @@ int map_list_mod_apply(request_t *request, vp_list_mod_t const *vlm)
                 */
                do {
                        fr_value_box_t  *vb = tmpl_value(fr_map_list_head(&vlm->mod)->rhs);
-
-                       do {
+                       /*
+                        *      Commented out loop due to fr_value_box_t now being
+                        *      in dlists
+                        */
+//                     do {
                                if (fr_value_box_cmp(vb, &found->data) == 0) {
                                        fr_dcursor_free_item(&list);
                                        break;
                                }
-                       } while ((vb = vb->next));
+//                     } while ((vb = vb->next));
                } while ((found = fr_dcursor_next(&list)));
        }
                goto finish;
@@ -1236,9 +1260,13 @@ int map_list_mod_apply(request_t *request, vp_list_mod_t const *vlm)
                        fr_value_box_t  *vb = tmpl_value(mod->rhs);
                        bool            remove = true;
 
-                       do {
+                       /*
+                        *      Commented out loop due to fr_value_box_t now being
+                        *      in dlists
+                        */
+//                     do {
                                if (fr_value_box_cmp_op(mod->op, &found->data, vb) == 1) remove = false;
-                       } while ((vb = vb->next));
+//                     } while ((vb = vb->next));
 
                        if (remove) fr_dcursor_free_item(&list);
                        goto finish;
@@ -1251,9 +1279,13 @@ int map_list_mod_apply(request_t *request, vp_list_mod_t const *vlm)
                        fr_value_box_t  *vb = tmpl_value(mod->rhs);
                        bool            remove = true;
 
-                       do {
+                       /*
+                        *      Commented out loop due to fr_value_box_t now being
+                        *      in dlists
+                        */
+//                     do {
                                if (fr_value_box_cmp_op(mod->op, &found->data, vb) == 1) remove = false;
-                       } while ((vb = vb->next));
+//                     } while ((vb = vb->next));
 
                        if (remove) {
                                fr_dcursor_free_item(&list);
index f1cdf5733ad874c419c8fbf2d95be4283d30d078..91164107d4dd3d89d33a3916a1a84ace5e4e04ec 100644 (file)
@@ -201,7 +201,7 @@ map_proc_inst_t *map_proc_instantiate(TALLOC_CTX *ctx, map_proc_t const *proc,
  * @param[in,out] result       Result of expanding the map input.  May be consumed
  *                             by the map processor.
  */
-rlm_rcode_t map_proc(request_t *request, map_proc_inst_t const *inst, fr_value_box_t **result)
+rlm_rcode_t map_proc(request_t *request, map_proc_inst_t const *inst, fr_value_box_list_t *result)
 {
        return inst->proc->evaluate(inst->proc->mod_inst, inst->data, request, result, inst->maps);
 }
index 1ee679390c32af7b0f946e6f96803fcec5bb6a5c..e0b0929c63dba8c996b8b5ccce3c9815871ad500 100644 (file)
@@ -59,7 +59,7 @@ extern "C" {
  *     - #RLM_MODULE_FAIL - If an error occurred performing the mapping.
  */
 typedef rlm_rcode_t (*map_proc_func_t)(void *mod_inst, void *proc_inst, request_t *request,
-                                      fr_value_box_t **result, fr_map_list_t const *maps);
+                                      fr_value_box_list_t *result, fr_map_list_t const *maps);
 
 /** Allocate new instance data for a map processor
  *
@@ -85,7 +85,7 @@ int           map_proc_register(void *mod_inst, char const *name,
 map_proc_inst_t *map_proc_instantiate(TALLOC_CTX *ctx, map_proc_t const *proc,
                                      CONF_SECTION *cs, tmpl_t const *src, fr_map_list_t const *maps);
 
-rlm_rcode_t    map_proc(request_t *request, map_proc_inst_t const *inst, fr_value_box_t **src);
+rlm_rcode_t    map_proc(request_t *request, map_proc_inst_t const *inst, fr_value_box_list_t *src);
 
 #ifdef __cplusplus
 }
index 76aec7004c38cfa9c74ba186611849cc3b22c1ef..7076bd2fe889a7f8a515cb6d4d0a3fd123adb5a1 100644 (file)
@@ -188,11 +188,11 @@ bool trigger_enabled(void)
 }
 
 typedef struct {
-       char            *name;
-       xlat_exp_t      *xlat;
-       fr_pair_list_t  vps;
-       fr_value_box_t  *box;
-       bool            expanded;
+       char                    *name;
+       xlat_exp_t              *xlat;
+       fr_pair_list_t          vps;
+       fr_value_box_list_t     box;
+       bool                    expanded;
 } fr_trigger_t;
 
 static unlang_action_t trigger_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
@@ -236,7 +236,7 @@ static unlang_action_t trigger_process(rlm_rcode_t *p_result, module_ctx_t const
                 */
        }
 
-       if (!ctx->box) {
+       if (fr_dlist_empty(&ctx->box)) {
                RERROR("Failed trigger %s - did not expand to anything", ctx->name);
                RETURN_MODULE_FAIL;
        }
@@ -244,7 +244,7 @@ static unlang_action_t trigger_process(rlm_rcode_t *p_result, module_ctx_t const
        /*
         *      Execute the program without waiting for results.
         */
-       if (fr_exec_nowait(request, ctx->box, NULL) < 0) {
+       if (fr_exec_nowait(request, &ctx->box, NULL) < 0) {
                RPERROR("Failed trigger %s", ctx->name);
                RETURN_MODULE_FAIL;
        }
@@ -404,6 +404,7 @@ int trigger_exec(request_t *request, CONF_SECTION const *cs, char const *name, b
 
        MEM(ctx = talloc_zero(fake, fr_trigger_t));
        fr_pair_list_init(&ctx->vps);
+       fr_value_box_list_init(&ctx->box);
        ctx->name = talloc_strdup(ctx, value);
 
        if (request && !fr_pair_list_empty(&request->request_pairs)) {
index 76cab106e22d10fc43ae06a5a9787fadb972e318..1b4c08dbd472c3d040b889bf34a72640d5ff10a7 100644 (file)
@@ -53,8 +53,8 @@ typedef struct {
        vp_list_mod_t           **vlm_next;
        vp_list_mod_t           *vlm_head;                      //!< First VP List Mod.
 
-       fr_value_box_t          *lhs_result;                    //!< Result of expanding the LHS
-       fr_value_box_t          *rhs_result;                    //!< Result of expanding the RHS.
+       fr_value_box_list_t     lhs_result;                     //!< Result of expanding the LHS
+       fr_value_box_list_t     rhs_result;                     //!< Result of expanding the RHS.
 
        unlang_update_state_t   state;                          //!< What we're currently doing.
 } unlang_frame_state_update_t;
@@ -63,7 +63,7 @@ typedef struct {
  *
  */
 typedef struct {
-       fr_value_box_t          *src_result;                    //!< Result of expanding the map source.
+       fr_value_box_list_t     src_result;                     //!< Result of expanding the map source.
 } unlang_frame_state_map_proc_t;
 
 /** Apply a list of modifications on one or more fr_pair_t lists.
@@ -139,8 +139,8 @@ static unlang_action_t list_mod_create(rlm_rcode_t *p_result, request_t *request
                case UNLANG_UPDATE_MAP_INIT:
                        update_state->state = UNLANG_UPDATE_MAP_EXPANDED_LHS;
 
-                       fr_assert(!update_state->lhs_result);   /* Should have been consumed */
-                       fr_assert(!update_state->rhs_result);   /* Should have been consumed */
+                       fr_assert(fr_dlist_empty(&update_state->lhs_result));   /* Should have been consumed */
+                       fr_assert(fr_dlist_empty(&update_state->rhs_result));   /* Should have been consumed */
 
                        switch (map->lhs->type) {
                        default:
@@ -219,8 +219,8 @@ static unlang_action_t list_mod_create(rlm_rcode_t *p_result, request_t *request
                        /*
                         *      Concat the top level results together
                         */
-                       if (update_state->rhs_result &&
-                           (fr_value_box_list_concat(update_state, update_state->rhs_result, &update_state->rhs_result,
+                       if (!fr_dlist_empty(&update_state->rhs_result) &&
+                           (fr_value_box_list_concat(update_state, fr_dlist_head(&update_state->rhs_result), &update_state->rhs_result,
                                                      FR_TYPE_STRING, true) < 0)) {
                                RPEDEBUG("Failed concatenating RHS expansion results");
                                goto error;
@@ -230,11 +230,11 @@ static unlang_action_t list_mod_create(rlm_rcode_t *p_result, request_t *request
                                            request, map,
                                            &update_state->lhs_result, &update_state->rhs_result) < 0) goto error;
 
-                       talloc_list_free(&update_state->rhs_result);
+                       fr_dlist_talloc_free(&update_state->rhs_result);
 
                next:
                        update_state->state = UNLANG_UPDATE_MAP_INIT;
-                       talloc_list_free(&update_state->lhs_result);
+                       fr_dlist_talloc_free(&update_state->lhs_result);
 
                        /*
                         *      Wind to the end...
@@ -279,6 +279,8 @@ static unlang_action_t unlang_update_state_init(rlm_rcode_t *p_result, request_t
                                                                    g->num_children));  /* 128 is for string buffers */
 
        fr_dcursor_init(&update_state->maps, &gext->map);
+       fr_value_box_list_init(&update_state->lhs_result);
+       fr_value_box_list_init(&update_state->rhs_result);
        update_state->vlm_next = &update_state->vlm_head;
        repeatable_set(frame);
 
@@ -302,17 +304,17 @@ static unlang_action_t map_proc_apply(rlm_rcode_t *p_result, request_t *request)
        map_proc_inst_t                 *inst = gext->proc_inst;
        unlang_frame_state_map_proc_t   *map_proc_state = talloc_get_type_abort(frame->state, unlang_frame_state_map_proc_t);
 
-       RDEBUG2("MAP %s \"%pM\"", inst->proc->name, map_proc_state->src_result);
+       RDEBUG2("MAP %s \"%pM\"", inst->proc->name, &map_proc_state->src_result);
 
        /*
         *      FIXME - We don't yet support async LHS/RHS expansions for map procs
         */
 #ifndef NDEBUG
-       if (map_proc_state->src_result) talloc_list_get_type_abort(map_proc_state->src_result, fr_value_box_t);
+       if (!fr_dlist_empty(&map_proc_state->src_result)) fr_dlist_verify(&map_proc_state->src_result);
 #endif
        *p_result = map_proc(request, gext->proc_inst, &map_proc_state->src_result);
 #ifndef NDEBUG
-       if (map_proc_state->src_result) talloc_list_get_type_abort(map_proc_state->src_result, fr_value_box_t);
+       if (!fr_dlist_empty(&map_proc_state->src_result)) fr_dlist_verify(&map_proc_state->src_result);
 #endif
 
        return *p_result == RLM_MODULE_YIELD ? UNLANG_ACTION_YIELD : UNLANG_ACTION_CALCULATE_RESULT;
@@ -333,6 +335,7 @@ static unlang_action_t unlang_map_state_init(rlm_rcode_t *p_result, request_t *r
         */
        repeatable_set(frame);
 
+       fr_value_box_list_init(&map_proc_state->src_result);
        /*
         *      Set this BEFORE doing anything else, as we will be
         *      called again after unlang_xlat_push() returns.
@@ -344,15 +347,18 @@ static unlang_action_t unlang_map_state_init(rlm_rcode_t *p_result, request_t *r
         */
        if (inst->src) switch (inst->src->type) {
        default:
-               if (tmpl_aexpand(frame->state, &map_proc_state->src_result,
+       {
+               fr_value_box_t *src_result = NULL;
+               if (tmpl_aexpand(frame->state, &src_result,
                                 request, inst->src, NULL, NULL) < 0) {
                        REDEBUG("Failed expanding map src");
                error:
                        *p_result = RLM_MODULE_FAIL;
                        return UNLANG_ACTION_CALCULATE_RESULT;
                }
+               fr_dlist_insert_head(&map_proc_state->src_result, src_result);
                break;
-
+       }
        case TMPL_TYPE_EXEC:
                if (unlang_tmpl_push(map_proc_state, &map_proc_state->src_result,
                                     request, inst->src, NULL, NULL) < 0) {
index b5d2daf74d9946c960b2bff875751be13c8be140..f169205027122d69e565f3a1521546af7e0f373f 100644 (file)
@@ -475,7 +475,7 @@ unlang_action_t unlang_module_yield_to_subrequest(rlm_rcode_t *p_result, request
  * @return
  *     - UNLANG_ACTION_YIELD
  */
-unlang_action_t unlang_module_yield_to_xlat(TALLOC_CTX *ctx, fr_value_box_t **out,
+unlang_action_t unlang_module_yield_to_xlat(TALLOC_CTX *ctx, fr_value_box_list_t *out,
                                            request_t *request, xlat_exp_t const *exp,
                                            unlang_module_resume_t resume,
                                            unlang_module_signal_t signal, void *rctx)
@@ -521,7 +521,7 @@ unlang_action_t unlang_module_yield_to_xlat(TALLOC_CTX *ctx, fr_value_box_t **ou
  * @return
  *     - UNLANG_ACTION_YIELD
  */
-unlang_action_t unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_t **out, int *status,
+unlang_action_t unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_list_t *out, int *status,
                                            request_t *request, tmpl_t const *vpt,
                                            fr_pair_list_t *vps,
                                            unlang_module_resume_t resume,
index 0d14a7878d847cb5dd593d01058ba04e8a9669d4..e03989bb25db10aebc6459b224c9d82b2097b3a5 100644 (file)
@@ -126,12 +126,12 @@ unlang_action_t   unlang_module_yield_to_section(rlm_rcode_t *p_result,
                                               unlang_module_resume_t resume,
                                               unlang_module_signal_t signal, void *rctx);
 
-unlang_action_t        unlang_module_yield_to_xlat(TALLOC_CTX *ctx, fr_value_box_t **out,
+unlang_action_t        unlang_module_yield_to_xlat(TALLOC_CTX *ctx, fr_value_box_list_t *out,
                                            request_t *request, xlat_exp_t const *xlat,
                                            unlang_module_resume_t resume,
                                            unlang_module_signal_t signal, void *rctx);
 
-unlang_action_t        unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_t **out, int *status,
+unlang_action_t        unlang_module_yield_to_tmpl(TALLOC_CTX *ctx, fr_value_box_list_t *out, int *status,
                                            request_t *request, tmpl_t const *exp,
                                            fr_pair_list_t *vps,
                                            unlang_module_resume_t resume,
index cde3de777da7488bac818f51a138b64abbd625b3..12b48f91fa9820083598ccd14aef0bbc62a050db 100644 (file)
@@ -112,7 +112,7 @@ static void unlang_tmpl_signal(request_t *request, fr_state_signal_t action)
  * @param[in] vps              the input VPs.  May be NULL.  Used only for #TMPL_TYPE_EXEC
  * @param[out] status          where the status of exited programs will be stored.
  */
-int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_t **out, request_t *request, tmpl_t const *tmpl, fr_pair_list_t *vps, int *status)
+int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *tmpl, fr_pair_list_t *vps, int *status)
 {
        unlang_stack_t                  *stack = request->stack;
        unlang_stack_frame_t            *frame;
@@ -159,6 +159,8 @@ int unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_t **out, request_t *request,
                .status_p = status
        };
 
+       fr_value_box_list_init(&state->box);
+
        return 0;
 }
 
@@ -303,7 +305,7 @@ static unlang_action_t unlang_tmpl_resume(rlm_rcode_t *p_result, request_t *requ
        unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state,
                                                                       unlang_frame_state_tmpl_t);
 
-       if (state->out) *state->out = state->box;
+       if (state->out) fr_dlist_move(state->out, &state->box);
 
        if (state->resume) {
                rlm_rcode_t rcode;
@@ -337,7 +339,7 @@ static unlang_action_t unlang_tmpl_exec_wait_final(rlm_rcode_t *p_result, reques
         *      care about output, and we don't care about the programs exit status.
         */
        if (state->failed) {
-               TALLOC_FREE(state->box);
+               fr_dlist_talloc_free(&state->box);
                goto resume;
        }
 
@@ -357,7 +359,7 @@ static unlang_action_t unlang_tmpl_exec_wait_final(rlm_rcode_t *p_result, reques
                        state->status = -state->status;
                }
 
-               fr_assert(state->box == NULL);
+               fr_assert(fr_dlist_empty(&state->box));
                goto resume;
        }
 
@@ -374,6 +376,7 @@ static unlang_action_t unlang_tmpl_exec_wait_final(rlm_rcode_t *p_result, reques
         */
        if (state->out) {
                fr_type_t type = FR_TYPE_STRING;
+               fr_value_box_t *box;
 
                /*
                 *      Remove any trailing LF / CR
@@ -392,13 +395,15 @@ static unlang_action_t unlang_tmpl_exec_wait_final(rlm_rcode_t *p_result, reques
                        state->ptr = p;
                }
 
-               MEM(state->box = fr_value_box_alloc(state->ctx, FR_TYPE_STRING, NULL, true));
-               if (fr_value_box_from_str(state->box, state->box, &type, NULL,
+               fr_value_box_list_init(&state->box);
+               MEM(box = fr_value_box_alloc(state->ctx, FR_TYPE_STRING, NULL, true));
+               if (fr_value_box_from_str(state->ctx, box, &type, NULL,
                                          state->buffer, state->ptr - state->buffer, 0, true) < 0) {
-                       talloc_free(state->box);
+                       talloc_free(box);
                        *p_result = RLM_MODULE_FAIL;
                        return UNLANG_ACTION_CALCULATE_RESULT;
                }
+               fr_dlist_insert_head(&state->box, box);
        }
 
        /*
@@ -429,14 +434,14 @@ static unlang_action_t unlang_tmpl_exec_wait_resume(rlm_rcode_t *p_result, reque
        state->fd = -1;
        if (state->out) fd_p = &state->fd;
 
-       if (fr_exec_wait_start(request, state->box, state->vps, &pid, NULL, fd_p) < 0) {
+       if (fr_exec_wait_start(request, &state->box, state->vps, &pid, NULL, fd_p) < 0) {
                RPEDEBUG("Failed executing program");
        fail:
                *p_result = RLM_MODULE_FAIL;
                return UNLANG_ACTION_CALCULATE_RESULT;
        }
 
-       TALLOC_FREE(state->box); /* this is the xlat expansion, and not the output string we want */
+       fr_dlist_talloc_free(&state->box); /* this is the xlat expansion, and not the output string we want */
 
        state->pid = pid;
        state->status = -1;     /* default to program didn't work */
@@ -492,7 +497,7 @@ static unlang_action_t unlang_tmpl_exec_nowait_resume(rlm_rcode_t *p_result, req
        unlang_frame_state_tmpl_t       *state = talloc_get_type_abort(frame->state,
                                                                       unlang_frame_state_tmpl_t);
 
-       if (fr_exec_nowait(request, state->box, state->vps) < 0) {
+       if (fr_exec_nowait(request, &state->box, state->vps) < 0) {
                RPEDEBUG("Failed executing program");
                *p_result = RLM_MODULE_FAIL;
 
@@ -520,9 +525,13 @@ static unlang_action_t unlang_tmpl(rlm_rcode_t *p_result, request_t *request)
 
        /*
         *      If we're not called from unlang_tmpl_push(), then
-        *      ensure that we clean up the resulting value boxes.
+        *      ensure that we clean up the resulting value boxes
+        *      and that the list to write the boxes in is initialised.
         */
-       if (!state->ctx) state->ctx = state;
+       if (!state->ctx) {
+               state->ctx = state;
+               fr_value_box_list_init(&state->box);
+       }
 
        if (!tmpl_async_required(ut->tmpl)) {
                if (!ut->inline_exec) {
index 966db00caa3bd1147c80985dbe122c8f3af4b17e..e3a5030c8c358837ef6b176847ec08f52efea9ea 100644 (file)
@@ -57,7 +57,7 @@ typedef void (*fr_unlang_tmpl_signal_t)(request_t *request, void *rctx, fr_state
  */
 typedef rlm_rcode_t (*fr_unlang_tmpl_resume_t)(request_t *request, void *rctx);
 
-int            unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_t **out,
+int            unlang_tmpl_push(TALLOC_CTX *ctx, fr_value_box_list_t *out,
                                 request_t *request, tmpl_t const *tmpl, fr_pair_list_t *vps, int *status)
                CC_HINT(warn_unused_result);
 
index 62300e77f26a7d3251e65985016f09ed27497076..ec578f1b1e05c18e5d6bd44ff2edffe2dc5d7403 100644 (file)
@@ -35,8 +35,8 @@ extern "C" {
  */
 typedef struct {
        TALLOC_CTX                      *ctx;           //!< for allocating value boxes
-       fr_value_box_t                  **out;          //!< where the expansion is stored
-       fr_value_box_t                  *box;           //!< where the expansion is stored
+       fr_value_box_list_t             *out;           //!< where the expansion is stored
+       fr_value_box_list_t             box;            //!< where the expansion is stored
 
        void                            *rctx;          //!< for resume
        fr_unlang_tmpl_resume_t         resume;         //!< resumption handler
index 1861055b5a7329e6db6c76c540b72ba4a3168d7b..94be17fa4c36c3c85a94a0196022e2e761815cba 100644 (file)
@@ -40,12 +40,12 @@ typedef struct {
        TALLOC_CTX              *ctx;                           //!< to allocate boxes and values in.
        TALLOC_CTX              *event_ctx;                     //!< for temporary events
        xlat_exp_t const        *exp;
-       fr_cursor_t             values;                         //!< Values aggregated so far.
+       fr_dcursor_t            values;                         //!< Values aggregated so far.
 
        /*
         *      For func and alternate
         */
-       fr_value_box_t          *rhead;                         //!< Head of the result of a nested
+       fr_value_box_list_t     rhead;                          //!< Head of the result of a nested
                                                                ///< expansion.
        bool                    alternate;                      //!< record which alternate branch we
                                                                ///< previously took.
@@ -192,7 +192,7 @@ int unlang_xlat_event_timeout_add(request_t *request, fr_unlang_xlat_timeout_t c
  *     - 0 on success.
  *     - -1 on failure.
  */
-int unlang_xlat_push(TALLOC_CTX *ctx, fr_value_box_t **out,
+int unlang_xlat_push(TALLOC_CTX *ctx, fr_value_box_list_t *out,
                     request_t *request, xlat_exp_t const *exp, bool top_frame)
 {
 
@@ -214,7 +214,8 @@ int unlang_xlat_push(TALLOC_CTX *ctx, fr_value_box_t **out,
        MEM(frame->state = state = talloc_zero(stack, unlang_frame_state_xlat_t));
        state->exp = talloc_get_type_abort_const(exp, xlat_exp_t);      /* Ensure the node is valid */
 
-       fr_cursor_talloc_init(&state->values, out, fr_value_box_t);
+       fr_dcursor_talloc_init(&state->values, out, fr_value_box_t);
+       fr_value_box_list_init(&state->rhead);
 
        state->ctx = ctx;
 
@@ -252,7 +253,7 @@ static unlang_action_t unlang_xlat(rlm_rcode_t *p_result, request_t *request)
                 *      at this level.  A frame may be used to evaluate
                 *      multiple sibling nodes.
                 */
-               talloc_list_free(&state->rhead);
+               fr_dlist_talloc_free(&state->rhead);
                if (unlang_xlat_push(state->ctx, &state->rhead, request, child, false) < 0) {
                        *p_result = RLM_MODULE_FAIL;
                        return UNLANG_ACTION_STOP_PROCESSING;
index a4d8ab81b3fd750441d593362a44214845123b5b..0b4210f587b1484c0da136f5d316e07487542365 100644 (file)
@@ -141,9 +141,9 @@ typedef void (*fr_unlang_xlat_fd_event_t)(request_t *request, void *xlat_inst,
  *                             mean it turned a result.
  *     - XLAT_ACTION_FAIL      the xlat function failed.
  */
-typedef xlat_action_t (*xlat_func_t)(TALLOC_CTX *ctx, fr_cursor_t *out,
+typedef xlat_action_t (*xlat_func_t)(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                     request_t *request, void const *xlat_inst, void *xlat_thread_inst,
-                                    fr_value_box_t **in);
+                                    fr_value_box_list_t *in);
 
 /** xlat callback resumption function
  *
@@ -164,9 +164,9 @@ typedef xlat_action_t (*xlat_func_t)(TALLOC_CTX *ctx, fr_cursor_t *out,
  *                             mean it turned a result.
  *     - XLAT_ACTION_FAIL      the xlat function failed.
  */
-typedef xlat_action_t (*xlat_func_resume_t)(TALLOC_CTX *ctx, fr_cursor_t *out,
+typedef xlat_action_t (*xlat_func_resume_t)(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                            request_t *request, void const *xlat_inst, void *xlat_thread_inst,
-                                           fr_value_box_t **in, void *rctx);
+                                           fr_value_box_list_t *in, void *rctx);
 
 /** A callback when the request gets a fr_state_signal_t.
  *
@@ -404,7 +404,7 @@ void                xlat_instances_free(void);
 int            unlang_xlat_event_timeout_add(request_t *request, fr_unlang_xlat_timeout_t callback,
                                              void const *ctx, fr_time_t when);
 
-int            unlang_xlat_push(TALLOC_CTX *ctx, fr_value_box_t **out,
+int            unlang_xlat_push(TALLOC_CTX *ctx, fr_value_box_list_t *out,
                                 request_t *request, xlat_exp_t const *exp, bool top_frame)
                                 CC_HINT(warn_unused_result);
 
index 1952293501d06b83a195536820fbac239c6c6b6b..585a2d800286cdccdf20890b81652ec4997b5ade 100644 (file)
@@ -1600,27 +1600,29 @@ static ssize_t xlat_func_xlat(TALLOC_CTX *ctx, char **out, size_t outlen,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                             request_t *request, UNUSED void const *xlat_inst,
                                             UNUSED void *xlat_thread_inst,
-                                            fr_value_box_t **in)
+                                            fr_value_box_list_t *in)
 {
        size_t          alen;
        ssize_t         elen;
        char            *buff;
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head;
 
        /*
         *      If there's no input, there's no output
         */
-       if (!in) return XLAT_ACTION_DONE;
+       if (fr_dlist_empty(in)) return XLAT_ACTION_DONE;
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_OCTETS, true) < 0) {
+       in_head = fr_dlist_head(in);
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       alen = FR_BASE64_ENC_LENGTH((*in)->vb_length);
+       alen = FR_BASE64_ENC_LENGTH(in_head->vb_length);
 
        MEM(vb = fr_value_box_alloc_null(ctx));
        if (fr_value_box_bstr_alloc(vb, &buff, vb, NULL, alen, false) < 0) {
@@ -1628,7 +1630,7 @@ static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_cursor_t *out,
                return XLAT_ACTION_FAIL;
        }
 
-       elen = fr_base64_encode(buff, alen + 1, (*in)->vb_octets, (*in)->vb_length);
+       elen = fr_base64_encode(buff, alen + 1, in_head->vb_octets, in_head->vb_length);
        if (elen < 0) {
                RPEDEBUG("Base64 encoding failed");
                talloc_free(buff);
@@ -1636,7 +1638,7 @@ static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_cursor_t *out,
        }
 
        fr_assert((size_t)elen <= alen);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -1651,38 +1653,40 @@ static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_base64_decode(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_base64_decode(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                             request_t *request, UNUSED void const *xlat_inst,
                                             UNUSED void *xlat_thread_inst,
-                                            fr_value_box_t **in)
+                                            fr_value_box_list_t *in)
 {
        size_t          alen;
        ssize_t         declen;
        uint8_t         *decbuf;
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head;
 
        /*
         *      If there's no input, there's no output
         */
-       if (!in) return XLAT_ACTION_DONE;
+       if (fr_dlist_empty(in)) return XLAT_ACTION_DONE;
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_OCTETS, true) < 0) {
+       in_head = fr_dlist_head(in);
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       alen = FR_BASE64_DEC_LENGTH((*in)->vb_length);
+       alen = FR_BASE64_DEC_LENGTH(in_head->vb_length);
 
        MEM(vb = fr_value_box_alloc_null(ctx));
-       MEM(fr_value_box_mem_alloc(vb, &decbuf, vb, NULL, alen, (*in)->tainted) == 0);
-       declen = fr_base64_decode(decbuf, alen, (*in)->vb_strvalue, (*in)->vb_length);
+       MEM(fr_value_box_mem_alloc(vb, &decbuf, vb, NULL, alen, in_head->tainted) == 0);
+       declen = fr_base64_decode(decbuf, alen, in_head->vb_strvalue, in_head->vb_length);
        if (declen < 0) {
                talloc_free(vb);
                REDEBUG("Base64 string invalid");
                return XLAT_ACTION_FAIL;
        }
        MEM(fr_value_box_mem_realloc(vb, NULL, vb, declen) == 0);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -1699,9 +1703,9 @@ static xlat_action_t xlat_func_base64_decode(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                   request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                  fr_value_box_t **in)
+                                  fr_value_box_list_t *in)
 {
        fr_value_box_t          *result;
        char                    *buff = NULL, *p, *end;
@@ -1712,9 +1716,9 @@ static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_cursor_t *out,
        /*
         *      If there's no input, there's no output
         */
-       if (!*in) return XLAT_ACTION_DONE;
+       if (fr_dlist_empty(in)) return XLAT_ACTION_DONE;
 
-       buff = fr_value_box_list_aprint(NULL, *in, NULL, NULL);
+       buff = fr_value_box_list_aprint(NULL, in, NULL, NULL);
        if (!buff) return XLAT_ACTION_FAIL;
 
        len = talloc_array_length(buff) - 1;
@@ -1736,7 +1740,7 @@ static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_cursor_t *out,
        outlen = len / 2;
 
        MEM(result = fr_value_box_alloc_null(ctx));
-       MEM(fr_value_box_mem_alloc(result, &bin, result, NULL, outlen, fr_value_box_list_tainted(*in)) == 0);
+       MEM(fr_value_box_mem_alloc(result, &bin, result, NULL, outlen, fr_value_box_list_tainted(in)) == 0);
        fr_hex2bin(&err, &FR_DBUFF_TMP(bin, outlen), &FR_SBUFF_IN(p, end - p), true);
        if (err) {
                REDEBUG2("Invalid hex string");
@@ -1744,7 +1748,7 @@ static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_cursor_t *out,
                return XLAT_ACTION_FAIL;
        }
 
-       fr_cursor_append(out, result);
+       fr_dcursor_append(out, result);
 
 finish:
        talloc_free(buff);
@@ -1764,9 +1768,9 @@ finish:
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_concat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_concat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                      request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                     fr_value_box_t **in)
+                                     fr_value_box_list_t *in)
 {
        fr_value_box_t  *result;
        fr_value_box_t  *separator;
@@ -1776,12 +1780,12 @@ static xlat_action_t xlat_func_concat(TALLOC_CTX *ctx, fr_cursor_t *out,
        /*
         *      If there's no input, there's no output
         */
-       if (!in) return XLAT_ACTION_DONE;
+       if (fr_dlist_empty(in)) return XLAT_ACTION_DONE;
 
        /*
         * Separator is first value box
         */
-       separator = *in;
+       separator = fr_dlist_pop_head(in);
 
        if (!separator) {
                REDEBUG("Missing separator for concat xlat");
@@ -1797,12 +1801,17 @@ static xlat_action_t xlat_func_concat(TALLOC_CTX *ctx, fr_cursor_t *out,
                return XLAT_ACTION_FAIL;
        }
 
-       buff = fr_value_box_list_aprint(result, (*in)->next, sep, NULL);
+       buff = fr_value_box_list_aprint(result, in, sep, NULL);
        if (!buff) goto error;
 
-       fr_value_box_bstrdup_buffer_shallow(NULL, result, NULL, buff, fr_value_box_list_tainted((*in)->next));
+       fr_value_box_bstrdup_buffer_shallow(NULL, result, NULL, buff, fr_value_box_list_tainted(in));
 
-       fr_cursor_append(out, result);
+       /*
+        *      Return separator to the start of the vb list
+        */
+       fr_dlist_insert_head(in, separator);
+
+       fr_dcursor_append(out, result);
 
        return XLAT_ACTION_DONE;
 }
@@ -1819,34 +1828,36 @@ static xlat_action_t xlat_func_concat(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_hex(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_hex(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                   request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                  fr_value_box_t **in)
+                                  fr_value_box_list_t *in)
 {
        char *p;
        fr_value_box_t* vb;
+       fr_value_box_t* in_head;
 
        /*
         *      If there's no input, there's no output
         */
-       if (!*in) return XLAT_ACTION_DONE;
+       if (fr_dlist_empty(in)) return XLAT_ACTION_DONE;
 
+       in_head = fr_dlist_head(in);
        /*
         *      Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_OCTETS, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
        MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_STRING, NULL, false));
-       vb->vb_length = ((*in)->vb_length * 2);
+       vb->vb_length = (in_head->vb_length * 2);
        vb->vb_strvalue = p = talloc_zero_array(vb, char, vb->vb_length + 1);
-       if ((*in)->vb_length) {
-               fr_bin2hex(&FR_SBUFF_OUT(p, talloc_array_length(p)), &FR_DBUFF_TMP((*in)->vb_octets, (*in)->vb_length), SIZE_MAX);
+       if (in_head->vb_length) {
+               fr_bin2hex(&FR_SBUFF_OUT(p, talloc_array_length(p)), &FR_DBUFF_TMP(in_head->vb_octets, in_head->vb_length), SIZE_MAX);
        }
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -1857,19 +1868,19 @@ typedef enum {
        HMAC_SHA1
 } hmac_type;
 
-static xlat_action_t xlat_hmac(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_hmac(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                               fr_value_box_t **in, uint8_t *digest, int digest_len, hmac_type type)
+                               fr_value_box_list_t *in, uint8_t *digest, int digest_len, hmac_type type)
 {
        uint8_t const   *data_p, *key_p;
        size_t          data_len, key_len;
        fr_value_box_t  *vb, *vb_data, *vb_sep, *vb_key;
 
-       if (!in) return XLAT_ACTION_FAIL;
+       if (fr_dlist_empty(in)) return XLAT_ACTION_FAIL;
 
-       vb_data = fr_value_box_list_get(*in, 0);
-       vb_sep = fr_value_box_list_get(*in, 1);
-       vb_key = fr_value_box_list_get(*in, 2);
+       vb_data = fr_dlist_head(in);
+       vb_sep = fr_dlist_next(in, vb_data);
+       vb_key = fr_dlist_next(in, vb_sep);
 
        if (!vb_data || !vb_sep || !vb_key ||
             vb_sep->vb_length != 1 ||
@@ -1893,7 +1904,7 @@ static xlat_action_t xlat_hmac(TALLOC_CTX *ctx, fr_cursor_t *out,
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_memdup(vb, vb, NULL, digest, digest_len, false);
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -1908,9 +1919,9 @@ static xlat_action_t xlat_hmac(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_hmac_md5(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_hmac_md5(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                        request_t *request, void const *xlat_inst, void *xlat_thread_inst,
-                                       fr_value_box_t **in)
+                                       fr_value_box_list_t *in)
 {
        uint8_t         digest[MD5_DIGEST_LENGTH];
        return xlat_hmac(ctx, out, request, xlat_inst, xlat_thread_inst, in, digest, MD5_DIGEST_LENGTH, HMAC_MD5);
@@ -1926,9 +1937,9 @@ static xlat_action_t xlat_func_hmac_md5(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_hmac_sha1(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_hmac_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                         request_t *request, void const *xlat_inst, void *xlat_thread_inst,
-                                        fr_value_box_t **in)
+                                        fr_value_box_list_t *in)
 {
        uint8_t         digest[SHA1_DIGEST_LENGTH];
        return xlat_hmac(ctx, out, request, xlat_inst, xlat_thread_inst, in, digest, SHA1_DIGEST_LENGTH, HMAC_SHA1);
@@ -1947,22 +1958,22 @@ static xlat_action_t xlat_func_hmac_sha1(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_length(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_length(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                      UNUSED request_t *request, UNUSED void const *xlat_inst,
-                                     UNUSED void *xlat_thread_inst, fr_value_box_t **in)
+                                     UNUSED void *xlat_thread_inst, fr_value_box_list_t *in)
 
 {
        fr_value_box_t  *vb;
-       fr_cursor_t     cursor;
+       fr_dcursor_t    cursor;
 
-       for (vb = fr_cursor_talloc_init(&cursor, in, fr_value_box_t);
+       for (vb = fr_dcursor_talloc_init(&cursor, in, fr_value_box_t);
             vb;
-            vb = fr_cursor_next(&cursor)) {
+            vb = fr_dcursor_next(&cursor)) {
                fr_value_box_t *my;
 
                MEM(my = fr_value_box_alloc(ctx, FR_TYPE_SIZE, NULL, false));
                my->vb_size = fr_value_box_network_length(vb);
-               fr_cursor_append(out, my);
+               fr_dcursor_append(out, my);
        }
 
        return XLAT_ACTION_DONE;
@@ -1978,23 +1989,24 @@ static xlat_action_t xlat_func_length(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_md4(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_md4(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                   request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                  fr_value_box_t **in)
+                                  fr_value_box_list_t *in)
 {
        uint8_t         digest[MD5_DIGEST_LENGTH];
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /*
         * Concatenate all input if there is some
         */
-       if (*in && fr_value_box_list_concat(ctx, *in, in, FR_TYPE_OCTETS, true) < 0) {
+       if (in_head && fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       if (*in) {
-               fr_md4_calc(digest, (*in)->vb_octets, (*in)->vb_length);
+       if (in_head) {
+               fr_md4_calc(digest, in_head->vb_octets, in_head->vb_length);
        } else {
                /* Digest of empty string */
                fr_md4_calc(digest, NULL, 0);
@@ -2003,7 +2015,7 @@ static xlat_action_t xlat_func_md4(TALLOC_CTX *ctx, fr_cursor_t *out,
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_memdup(vb, vb, NULL, digest, sizeof(digest), false);
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -2018,23 +2030,24 @@ static xlat_action_t xlat_func_md4(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_md5(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_md5(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                   request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                  fr_value_box_t **in)
+                                  fr_value_box_list_t *in)
 {
        uint8_t         digest[MD5_DIGEST_LENGTH];
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /*
         *      Concatenate all input if there is some
         */
-       if (*in && fr_value_box_list_concat(ctx, *in, in, FR_TYPE_OCTETS, true) < 0) {
+       if (in_head && fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       if (*in) {
-               fr_md5_calc(digest, (*in)->vb_octets, (*in)->vb_length);
+       if (in_head) {
+               fr_md5_calc(digest, in_head->vb_octets, in_head->vb_length);
        } else {
                /* Digest of empty string */
                fr_md5_calc(digest, NULL, 0);
@@ -2043,7 +2056,7 @@ static xlat_action_t xlat_func_md5(TALLOC_CTX *ctx, fr_cursor_t *out,
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_memdup(vb, vb, NULL, digest, sizeof(digest), false);
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -2068,9 +2081,9 @@ exec echo {
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_module(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_module(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                      request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                     UNUSED fr_value_box_t **in)
+                                     UNUSED fr_value_box_list_t *in)
 {
        fr_value_box_t  *vb = NULL;
 
@@ -2085,7 +2098,7 @@ static xlat_action_t xlat_func_module(TALLOC_CTX *ctx, fr_cursor_t *out,
                return XLAT_ACTION_FAIL;
        }
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -2100,14 +2113,13 @@ static xlat_action_t xlat_func_module(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_pack(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_pack(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                   request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                  fr_value_box_t **in)
+                                  fr_value_box_list_t *in)
 {
        fr_value_box_t  *vb, *in_vb;
-       fr_cursor_t     cursor;
 
-       if (!*in) {
+       if (fr_dlist_empty(in)) {
                REDEBUG("Missing input boxes");
                return XLAT_ACTION_FAIL;
        }
@@ -2117,9 +2129,9 @@ static xlat_action_t xlat_func_pack(TALLOC_CTX *ctx, fr_cursor_t *out,
        /*
         *      Loop over the input boxes, packing them together.
         */
-       for (in_vb = fr_cursor_init(&cursor, in);
+       for (in_vb = fr_dlist_head(in);
             in_vb;
-            in_vb = fr_cursor_next(&cursor)) {
+            in_vb = fr_dlist_next(in, in_vb)) {
                fr_value_box_t *cast, box;
 
                if (in_vb->type != FR_TYPE_OCTETS) {
@@ -2144,7 +2156,7 @@ static xlat_action_t xlat_func_pack(TALLOC_CTX *ctx, fr_cursor_t *out,
                fr_assert(vb->vb_octets != NULL);
        }
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -2164,28 +2176,29 @@ static xlat_action_t xlat_func_pack(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                     request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                    fr_value_box_t **in)
+                                    fr_value_box_list_t *in)
 {
        tmpl_t                  *vpt = NULL;
        fr_dcursor_t            cursor;
        tmpl_cursor_ctx_t       cc;
        fr_value_box_t          *vb;
+       fr_value_box_t          *in_head = fr_dlist_head(in);
 
        /*
         *      If there's no input, there's no output
         */
-       if (!in) return XLAT_ACTION_DONE;
+       if (!in_head) return XLAT_ACTION_DONE;
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
        fr_pair_t *vp;
 
-       if (tmpl_afrom_attr_str(ctx, NULL, &vpt, (*in)->vb_strvalue,
+       if (tmpl_afrom_attr_str(ctx, NULL, &vpt, in_head->vb_strvalue,
                                &(tmpl_rules_t){
                                        .dict_def = request->dict,
                                        .prefix = TMPL_ATTR_REF_PREFIX_AUTO
@@ -2209,7 +2222,7 @@ static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_cursor_t *out,
                vb->vb_strvalue = buff;
                vb->vb_length = talloc_array_length(buff) - 1;
 
-               fr_cursor_append(out, vb);
+               fr_dcursor_append(out, vb);
        }
        tmpl_cursor_clear(&cc);
        talloc_free(vpt);
@@ -2229,20 +2242,21 @@ static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                    request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                   fr_value_box_t **in)
+                                   fr_value_box_list_t *in)
 {
        int64_t         result;
-       fr_value_box_t* vb;
+       fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /* Make sure input can be converted to an unsigned 32 bit integer */
-       if (fr_value_box_cast_in_place(ctx, (*in), FR_TYPE_UINT32, NULL) < 0) {
+       if (fr_value_box_cast_in_place(ctx, in_head, FR_TYPE_UINT32, NULL) < 0) {
                RPEDEBUG("Failed converting input to uint32");
                return XLAT_ACTION_FAIL;
        }
 
-       result = (*in)->vb_uint32;
+       result = in_head->vb_uint32;
 
        /* Make sure it isn't too big */
        if (result > (1 << 30)) result = (1 << 30);
@@ -2253,7 +2267,7 @@ static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_cursor_t *out,
        MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_UINT64, NULL, false));
        vb->vb_uint64 = result;
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -2285,9 +2299,9 @@ static xlat_action_t xlat_func_rand(TALLOC_CTX *ctx, fr_cursor_t *out,
 @endverbatim
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                       request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                      fr_value_box_t **in)
+                                      fr_value_box_list_t *in)
 {
        /*
         *      Lookup tables for randstr char classes
@@ -2308,6 +2322,7 @@ static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_cursor_t *out,
        unsigned int    reps;
        size_t          outlen = 0;
        fr_value_box_t* vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /** Max repetitions of a single character class
         *
@@ -2317,18 +2332,17 @@ static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_cursor_t *out,
        /*
         *      Nothing to do if input is empty
         */
-       if (!(*in)) return XLAT_ACTION_DONE;
-
+       if (!in_head) return XLAT_ACTION_DONE;
        /*
         *      Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       start = p = (*in)->vb_strvalue;
-       end = p + (*in)->vb_length;
+       start = p = in_head->vb_strvalue;
+       end = p + in_head->vb_length;
 
        /*
         *      Calculate size of output
@@ -2458,7 +2472,7 @@ static xlat_action_t xlat_func_randstr(TALLOC_CTX *ctx, fr_cursor_t *out,
 
        *buff_p++ = '\0';
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -2476,14 +2490,15 @@ if ("foo" =~ /^(?<name>.*)/) {
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                     request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                    fr_value_box_t **in)
+                                    fr_value_box_list_t *in)
 {
+       fr_value_box_t  *in_head  = fr_dlist_head(in);
        /*
         *      Return the complete capture if no other capture is specified
         */
-       if (!(*in)) {
+       if (!in_head) {
                fr_value_box_t  *vb;
                char            *p;
 
@@ -2496,12 +2511,12 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
 
                fr_assert(p);
                fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, p, false);
-               fr_cursor_append(out, vb);
+               fr_dcursor_append(out, vb);
 
                return XLAT_ACTION_DONE;
        }
 
-       switch ((*in)->type) {
+       switch (in_head->type) {
        /*
         *      If the input is an integer value then get an
         *      arbitrary subcapture index.
@@ -2512,12 +2527,12 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
                fr_value_box_t  *vb;
                char            *p;
 
-               if ((*in)->next) {
+               if (fr_dlist_next(in, in_head)) {
                        REDEBUG("Only one subcapture argument allowed");
                        return XLAT_ACTION_FAIL;
                }
 
-               if (fr_value_box_cast(NULL, &idx, FR_TYPE_UINT32, NULL, *in) < 0) {
+               if (fr_value_box_cast(NULL, &idx, FR_TYPE_UINT32, NULL, in_head) < 0) {
                        RPEDEBUG("Bad subcapture index");
                        return XLAT_ACTION_FAIL;
                }
@@ -2530,7 +2545,7 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
                }
                fr_assert(p);
                fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, p, false);
-               fr_cursor_append(out, vb);
+               fr_dcursor_append(out, vb);
 
                return XLAT_ACTION_DONE;
        }
@@ -2543,13 +2558,13 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
                /*
                 *      Concatenate all input
                 */
-               if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                        RPEDEBUG("Failed concatenating input");
                        return XLAT_ACTION_FAIL;
                }
 
                MEM(vb = fr_value_box_alloc_null(ctx));
-               if (regex_request_to_sub_named(vb, &p, request, (*in)->vb_strvalue) < 0) {
+               if (regex_request_to_sub_named(vb, &p, request, in_head->vb_strvalue) < 0) {
                        REDEBUG2("No previous named regex capture group");
                        talloc_free(vb);
                        return XLAT_ACTION_FAIL;
@@ -2557,7 +2572,7 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
 
                fr_assert(p);
                fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, p, false);
-               fr_cursor_append(out, vb);
+               fr_dcursor_append(out, vb);
 
                return XLAT_ACTION_DONE;
        }
@@ -2574,25 +2589,26 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                    request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                   fr_value_box_t **in)
+                                   fr_value_box_list_t *in)
 {
        uint8_t         digest[SHA1_DIGEST_LENGTH];
        fr_sha1_ctx     sha1_ctx;
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /*
         * Concatenate all input if there is some
         */
-       if (*in && fr_value_box_list_concat(ctx, *in, in, FR_TYPE_OCTETS, true) < 0) {
+       if (in_head && fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
        fr_sha1_init(&sha1_ctx);
-       if (*in) {
-               fr_sha1_update(&sha1_ctx, (*in)->vb_octets, (*in)->vb_length);
+       if (in_head) {
+               fr_sha1_update(&sha1_ctx, in_head->vb_octets, in_head->vb_length);
        } else {
                /* sha1 of empty string */
                fr_sha1_update(&sha1_ctx, NULL, 0);
@@ -2602,7 +2618,7 @@ static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_cursor_t *out,
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_memdup(vb, vb, NULL, digest, sizeof(digest), false);
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -2618,27 +2634,28 @@ static xlat_action_t xlat_func_sha1(TALLOC_CTX *ctx, fr_cursor_t *out,
  * @ingroup xlat_functions
  */
 #ifdef HAVE_OPENSSL_EVP_H
-static xlat_action_t xlat_evp_md(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_evp_md(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                 request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                fr_value_box_t **in, EVP_MD const *md)
+                                fr_value_box_list_t *in, EVP_MD const *md)
 {
        uint8_t         digest[EVP_MAX_MD_SIZE];
        unsigned int    digestlen;
        EVP_MD_CTX      *md_ctx;
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /*
         * Concatenate all input if there is some
         */
-       if (*in && fr_value_box_list_concat(ctx, *in, in, FR_TYPE_OCTETS, true) < 0) {
+       if (in_head && fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
        md_ctx = EVP_MD_CTX_create();
        EVP_DigestInit_ex(md_ctx, md, NULL);
-       if (*in) {
-               EVP_DigestUpdate(md_ctx, (*in)->vb_octets, (*in)->vb_length);
+       if (in_head) {
+               EVP_DigestUpdate(md_ctx, in_head->vb_octets, in_head->vb_length);
        } else {
                EVP_DigestUpdate(md_ctx, NULL, 0);
        }
@@ -2648,15 +2665,15 @@ static xlat_action_t xlat_evp_md(TALLOC_CTX *ctx, fr_cursor_t *out,
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_memdup(vb, vb, NULL, digest, digestlen, false);
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
 
 #  define EVP_MD_XLAT(_md, _md_func) \
-static xlat_action_t xlat_func_##_md(TALLOC_CTX *ctx, fr_cursor_t *out,\
+static xlat_action_t xlat_func_##_md(TALLOC_CTX *ctx, fr_dcursor_t *out,\
                                      request_t *request, void const *xlat_inst, void *xlat_thread_inst,\
-                                     fr_value_box_t **in)\
+                                     fr_value_box_list_t *in)\
 {\
        return xlat_evp_md(ctx, out, request, xlat_inst, xlat_thread_inst, in, EVP_##_md_func());\
 }
@@ -2686,23 +2703,24 @@ EVP_MD_XLAT(sha3_512, sha3_512)
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_string(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_string(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                      request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                     fr_value_box_t **in)
+                                     fr_value_box_list_t *in)
 {
-       if (!*in) return XLAT_ACTION_DONE;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
+       if (!in_head) return XLAT_ACTION_DONE;
 
        /*
         * Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
 
                return XLAT_ACTION_FAIL;
        }
 
-       fr_cursor_append(out, *in);
-       *in = NULL;     /* Let the caller know this was consumed */
+       fr_dlist_remove(in, in_head);           /* Let the caller know this was consumed */
+       fr_dcursor_append(out, in_head);
 
        return XLAT_ACTION_DONE;
 }
@@ -2719,30 +2737,31 @@ static xlat_action_t xlat_func_string(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_strlen(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_strlen(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                      request_t *request, UNUSED void const *xlat_inst,
-                                     UNUSED void *xlat_thread_inst, fr_value_box_t **in)
+                                     UNUSED void *xlat_thread_inst, fr_value_box_list_t *in)
 {
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
-       if (!*in) {
+       if (!in_head) {
                MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_SIZE, NULL, false));
                vb->vb_size = 0;
-               fr_cursor_append(out, vb);
+               fr_dcursor_append(out, vb);
                return XLAT_ACTION_DONE;
        }
 
        /*
         *      Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
        MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_SIZE, NULL, false));
-       vb->vb_size = strlen((*in)->vb_strvalue);
-       fr_cursor_append(out, vb);
+       vb->vb_size = strlen(in_head->vb_strvalue);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -2766,9 +2785,9 @@ static xlat_action_t xlat_func_strlen(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_sub_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_sub_regex(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                         request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                        fr_value_box_t **in)
+                                        fr_value_box_list_t *in)
 {
        char const              *p, *q, *end;
        char const              *regex, *rep, *subject;
@@ -2778,12 +2797,13 @@ static xlat_action_t xlat_func_sub_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
        regex_t                 *pattern;
        fr_regex_flags_t        flags;
        fr_value_box_t          *vb;
+       fr_value_box_t          *in_head = fr_dlist_head(in);
 
 
        /*
         *      If there's no input, there's no output
         */
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("No input arguments");
                return XLAT_ACTION_FAIL;
        }
@@ -2791,13 +2811,13 @@ static xlat_action_t xlat_func_sub_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
        /*
         *      Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       p = (*in)->vb_strvalue;
-       end = p + (*in)->vb_length;
+       p = in_head->vb_strvalue;
+       end = p + in_head->vb_length;
 
        if (p == end) {
                REDEBUG("Regex must not be empty");
@@ -2882,9 +2902,9 @@ static xlat_action_t xlat_func_sub_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
                talloc_free(pattern);
                return XLAT_ACTION_FAIL;
        }
-       fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, buff, (*in)->tainted);
+       fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, buff, in_head->tainted);
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        talloc_free(pattern);
 
@@ -2908,14 +2928,14 @@ static xlat_action_t xlat_func_sub_regex(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_sub(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_sub(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                   request_t *request,
 #ifdef HAVE_REGEX_PCRE2
                                   void const *xlat_inst, void *xlat_thread_inst,
 #else
                                   UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
 #endif
-                                  fr_value_box_t **in)
+                                  fr_value_box_list_t *in)
 {
        char const              *p, *q, *end;
        char                    *vb_str;
@@ -2924,11 +2944,12 @@ static xlat_action_t xlat_func_sub(TALLOC_CTX *ctx, fr_cursor_t *out,
        size_t                  pattern_len, rep_len;
 
        fr_value_box_t          *vb;
+       fr_value_box_t          *in_head = fr_dlist_head(in);
 
        /*
         *      If there's no input, there's no output
         */
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("No input arguments");
                return XLAT_ACTION_FAIL;
        }
@@ -2936,13 +2957,13 @@ static xlat_action_t xlat_func_sub(TALLOC_CTX *ctx, fr_cursor_t *out,
        /*
         *      Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       p = (*in)->vb_strvalue;
-       end = p + (*in)->vb_length;
+       p = in_head->vb_strvalue;
+       end = p + in_head->vb_length;
 
        if (p == end) {
                REDEBUG("Substitution arguments must not be empty");
@@ -3002,14 +3023,14 @@ static xlat_action_t xlat_func_sub(TALLOC_CTX *ctx, fr_cursor_t *out,
                p = q + pattern_len;
        }
 
-       if (fr_value_box_bstrdup_buffer_shallow(vb, vb, NULL, vb_str, (*in)->vb_strvalue) < 0) {
+       if (fr_value_box_bstrdup_buffer_shallow(vb, vb, NULL, vb_str, in_head->vb_strvalue) < 0) {
                RPEDEBUG("Failed creating output box");
                talloc_free(vb);
                return XLAT_ACTION_FAIL;
        }
 
        fr_assert(vb && (vb->type != FR_TYPE_INVALID));
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -3018,31 +3039,32 @@ static xlat_action_t xlat_func_sub(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * If upper is true, change to uppercase, otherwise, change to lowercase
  */
-static xlat_action_t xlat_change_case(TALLOC_CTX *ctx, fr_cursor_t *out,
-                                      request_t *request, fr_value_box_t **in, bool upper)
+static xlat_action_t xlat_change_case(TALLOC_CTX *ctx, fr_dcursor_t *out,
+                                      request_t *request, fr_value_box_list_t *in, bool upper)
 {
        char            *buff_p;
        char const      *p, *end;
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /*
         *      If there's no input, there's no output
         */
-       if (!*in) return XLAT_ACTION_DONE;
+       if (!in_head) return XLAT_ACTION_DONE;
 
        /*
         * Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       p = (*in)->vb_strvalue;
-       end = p + (*in)->vb_length;
+       p = in_head->vb_strvalue;
+       end = p + in_head->vb_length;
 
        MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_STRING, NULL, false));
-       MEM(fr_value_box_bstr_alloc(vb, &buff_p, vb, NULL, (*in)->vb_length, (*in)->tainted) == 0);
+       MEM(fr_value_box_bstr_alloc(vb, &buff_p, vb, NULL, in_head->vb_length, in_head->tainted) == 0);
 
        while (p < end) {
                *(buff_p++) = upper ? toupper ((int) *(p++)) : tolower((int) *(p++));
@@ -3050,7 +3072,7 @@ static xlat_action_t xlat_change_case(TALLOC_CTX *ctx, fr_cursor_t *out,
 
        *buff_p = '\0';
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -3067,9 +3089,9 @@ static xlat_action_t xlat_change_case(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_tolower(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_tolower(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                       request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                      fr_value_box_t **in)
+                                      fr_value_box_list_t *in)
 {
        return xlat_change_case(ctx, out, request, in, false);
 }
@@ -3086,9 +3108,9 @@ static xlat_action_t xlat_func_tolower(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_toupper(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_toupper(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                       request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                      fr_value_box_t **in)
+                                      fr_value_box_list_t *in)
 {
        return xlat_change_case(ctx, out, request, in, true);
 }
@@ -3103,30 +3125,31 @@ static xlat_action_t xlat_func_toupper(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_urlquote(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_urlquote(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                        request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                       fr_value_box_t **in)
+                                       fr_value_box_list_t *in)
 {
        char const      *p, *end;
        char            *buff_p;
        size_t          outlen = 0;
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /*
         * Nothing to do if input is empty
         */
-       if (!(*in)) return XLAT_ACTION_DONE;
+       if (!in_head) return XLAT_ACTION_DONE;
 
        /*
         * Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       p = (*in)->vb_strvalue;
-       end = p + (*in)->vb_length;
+       p = in_head->vb_strvalue;
+       end = p + in_head->vb_length;
 
        /*
         * Calculate size of output
@@ -3148,7 +3171,7 @@ static xlat_action_t xlat_func_urlquote(TALLOC_CTX *ctx, fr_cursor_t *out,
        MEM(fr_value_box_bstr_alloc(vb, &buff_p, vb, NULL, outlen, false) == 0);
 
        /* Reset p to start position */
-       p = (*in)->vb_strvalue;
+       p = in_head->vb_strvalue;
 
        while (p < end) {
                if (isalnum(*p)) {
@@ -3174,7 +3197,7 @@ static xlat_action_t xlat_func_urlquote(TALLOC_CTX *ctx, fr_cursor_t *out,
 
        *buff_p = '\0';
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -3191,31 +3214,32 @@ static xlat_action_t xlat_func_urlquote(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_urlunquote(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_urlunquote(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                          request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                         fr_value_box_t **in)
+                                         fr_value_box_list_t *in)
 {
        char const      *p, *end;
        char            *buff_p;
        char            *c1, *c2;
        size_t          outlen = 0;
        fr_value_box_t  *vb;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /*
         * Nothing to do if input is empty
         */
-       if (!*in) return XLAT_ACTION_DONE;
+       if (!in_head) return XLAT_ACTION_DONE;
 
        /*
         * Concatenate all input
         */
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       p = (*in)->vb_strvalue;
-       end = p + (*in)->vb_length;
+       p = in_head->vb_strvalue;
+       end = p + in_head->vb_length;
 
        /*
         * Calculate size of output
@@ -3233,7 +3257,7 @@ static xlat_action_t xlat_func_urlunquote(TALLOC_CTX *ctx, fr_cursor_t *out,
        MEM(fr_value_box_bstr_alloc(vb, &buff_p, vb, NULL, outlen, false) == 0);
 
        /* Reset p to start position */
-       p = (*in)->vb_strvalue;
+       p = in_head->vb_strvalue;
 
        while (p < end) {
                if (*p != '%') {
@@ -3245,7 +3269,7 @@ static xlat_action_t xlat_func_urlunquote(TALLOC_CTX *ctx, fr_cursor_t *out,
                /* Don't need \0 check, as it won't be in the hextab */
                if (!(c1 = memchr(hextab, tolower(*++p), 16)) ||
                    !(c2 = memchr(hextab, tolower(*++p), 16))) {
-                       REMARKER((*in)->vb_strvalue, p - (*in)->vb_strvalue, "Non-hex char in %% sequence");
+                       REMARKER(in_head->vb_strvalue, p - in_head->vb_strvalue, "Non-hex char in %% sequence");
                        talloc_free(vb);
 
                        return XLAT_ACTION_FAIL;
@@ -3255,7 +3279,7 @@ static xlat_action_t xlat_func_urlunquote(TALLOC_CTX *ctx, fr_cursor_t *out,
        }
 
        *buff_p = '\0';
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
index e47cbf683f2792ef76950ce7a23de11d501e3068..315f969ccf24d7579ca77d157778e8254fe70526 100644 (file)
@@ -177,7 +177,7 @@ static char *xlat_fmt_aprint(TALLOC_CTX *ctx, xlat_exp_t const *node)
  * @param[in] node     Being processed.
  * @param[in] args     from previous expansion.
  */
-static inline void xlat_debug_log_expansion(request_t *request, xlat_exp_t const *node, fr_value_box_t const *args)
+static inline void xlat_debug_log_expansion(request_t *request, xlat_exp_t const *node, fr_value_box_list_t const *args)
 {
        char *str;
 
@@ -198,6 +198,18 @@ static inline void xlat_debug_log_expansion(request_t *request, xlat_exp_t const
        talloc_free(str);
 }
 
+/** Output the list result of an expansion
+ *
+ * @param[in] request  The current request.
+ * @param[in] result   of the expansion.
+ */
+static inline void xlat_debug_log_list_result(request_t *request, fr_value_box_list_t const *result)
+{
+       if (!RDEBUG_ENABLED2) return;
+
+       RDEBUG2("  --> %pM", result);
+}
+
 /** Output the result of an expansion
  *
  * @param[in] request  The current request.
@@ -207,7 +219,7 @@ static inline void xlat_debug_log_result(request_t *request, fr_value_box_t cons
 {
        if (!RDEBUG_ENABLED2) return;
 
-       RDEBUG2("  --> %pM", result);
+       RDEBUG2("  --> %pV", result);
 }
 
 /** One letter expansions
@@ -221,7 +233,7 @@ static inline void xlat_debug_log_result(request_t *request, fr_value_box_t cons
  *     - #XLAT_ACTION_DONE     if we're done processing this node.
  *
  */
-static xlat_action_t xlat_eval_one_letter(TALLOC_CTX *ctx, fr_cursor_t *out, request_t *request, char letter)
+static xlat_action_t xlat_eval_one_letter(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, char letter)
 {
 
        char            buffer[64];
@@ -387,8 +399,8 @@ static xlat_action_t xlat_eval_one_letter(TALLOC_CTX *ctx, fr_cursor_t *out, req
                return XLAT_ACTION_FAIL;
        }
 
-       fr_cursor_append(out, value);
-       fr_cursor_next(out);                            /* Advance to our first value */
+       fr_dcursor_append(out, value);
+       fr_dcursor_next(out);                           /* Advance to our first value */
 
        return XLAT_ACTION_DONE;
 }
@@ -407,7 +419,7 @@ static xlat_action_t xlat_eval_one_letter(TALLOC_CTX *ctx, fr_cursor_t *out, req
  *     - #XLAT_ACTION_FAIL     on memory allocation errors.
  *     - #XLAT_ACTION_DONE     if we're done processing this node.
  */
-static xlat_action_t xlat_eval_pair_virtual(TALLOC_CTX *ctx, fr_cursor_t *out, request_t *request, tmpl_t const *vpt)
+static xlat_action_t xlat_eval_pair_virtual(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, tmpl_t const *vpt)
 {
        fr_radius_packet_t      *packet = NULL;
        fr_value_box_t  *value;
@@ -539,8 +551,8 @@ static xlat_action_t xlat_eval_pair_virtual(TALLOC_CTX *ctx, fr_cursor_t *out, r
        }
 
 done:
-       fr_cursor_append(out, value);
-       fr_cursor_next(out);                            /* Advance to our first value */
+       fr_dcursor_append(out, value);
+       fr_dcursor_next(out);                           /* Advance to our first value */
 
        return XLAT_ACTION_DONE;
 }
@@ -556,7 +568,7 @@ done:
  *     - #XLAT_ACTION_FAIL             we failed getting a value for the attribute.
  *     - #XLAT_ACTION_DONE             we successfully evaluated the xlat.
  */
-static xlat_action_t xlat_eval_pair_real(TALLOC_CTX *ctx, fr_cursor_t *out, request_t *request, tmpl_t const *vpt)
+static xlat_action_t xlat_eval_pair_real(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, tmpl_t const *vpt)
 {
        fr_pair_t               *vp = NULL;
        fr_value_box_t          *value;
@@ -598,8 +610,8 @@ static xlat_action_t xlat_eval_pair_real(TALLOC_CTX *ctx, fr_cursor_t *out, requ
                                goto done;
                        }
                        value->datum.int32 = 0;
-                       fr_cursor_append(out, value);
-                       fr_cursor_next(out);                    /* Advance to our first value */
+                       fr_dcursor_append(out, value);
+                       fr_dcursor_next(out);                   /* Advance to our first value */
                } /* Fall through to being done */
 
                goto done;
@@ -620,8 +632,8 @@ static xlat_action_t xlat_eval_pair_real(TALLOC_CTX *ctx, fr_cursor_t *out, requ
 
                value = fr_value_box_alloc(ctx, FR_TYPE_UINT32, NULL, false);
                value->datum.uint32 = count;
-               fr_cursor_append(out, value);
-               fr_cursor_next(out);                            /* Advance to our first value */
+               fr_dcursor_append(out, value);
+               fr_dcursor_next(out);                           /* Advance to our first value */
                break;
        }
 
@@ -640,9 +652,9 @@ static xlat_action_t xlat_eval_pair_real(TALLOC_CTX *ctx, fr_cursor_t *out, requ
                     vp = fr_dcursor_next(&cursor)) {
                        value = fr_value_box_alloc(ctx, vp->data.type, vp->da, vp->data.tainted);
                        fr_value_box_copy(value, value, &vp->data);
-                       fr_cursor_append(out, value);
+                       fr_dcursor_append(out, value);
                }
-               fr_cursor_next(out);                            /* Advance to our first value */
+               fr_dcursor_next(out);                           /* Advance to our first value */
                break;
 
        default:
@@ -655,8 +667,8 @@ static xlat_action_t xlat_eval_pair_real(TALLOC_CTX *ctx, fr_cursor_t *out, requ
                if (!value) goto oom;
 
                fr_value_box_copy(value, value, &vp->data);     /* Also dups taint */
-               fr_cursor_append(out, value);
-               fr_cursor_next(out);                            /* Advance to our first value */
+               fr_dcursor_append(out, value);
+               fr_dcursor_next(out);                           /* Advance to our first value */
                break;
        }
 
@@ -695,9 +707,9 @@ void xlat_signal(xlat_func_signal_t signal, xlat_exp_t const *exp,
  * @param[in] rctx             Opaque (to us), resume ctx provided by xlat function
  *                             when it yielded.
  */
-xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
+xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                     xlat_func_resume_t resume, xlat_exp_t const *exp,
-                                    request_t *request, fr_value_box_t **result, void *rctx)
+                                    request_t *request, fr_value_box_list_t *result, void *rctx)
 {
        xlat_thread_inst_t      *thread_inst = xlat_thread_instance_find(exp);
        xlat_action_t           xa;
@@ -708,9 +720,9 @@ xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
         *      to debug problems if they free or change elements
         *      and don't remove them from the list.
         */
-       if (*result) (void) talloc_list_get_type_abort(*result, fr_value_box_t);
+       if (!fr_dlist_empty(result)) { fr_dlist_verify(result); }
        xa = resume(ctx, out, request, exp->call.inst, thread_inst->data, result, rctx);
-       if (*result) (void) talloc_list_get_type_abort(*result, fr_value_box_t);
+       if (!fr_dlist_empty(result)) { fr_dlist_verify(result); }
 
        RDEBUG2("EXPAND %%{%s:...}", exp->call.func->name);
        switch (xa) {
@@ -722,8 +734,8 @@ xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
                break;
 
        case XLAT_ACTION_DONE:
-               fr_cursor_next(out);            /* Wind to the start of this functions output */
-               RDEBUG2("   --> %pM", fr_cursor_current(out));
+               fr_dcursor_next(out);           /* Wind to the start of this functions output */
+               RDEBUG2("   --> %pV", fr_dcursor_current(out));
                break;
 
        case XLAT_ACTION_FAIL:
@@ -749,14 +761,14 @@ xlat_action_t xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
  *                             additional #xlat_exp_t.
  * @param[in] result           of a previous nested evaluation.
  */
-xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
+xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                     xlat_exp_t const **child, bool *alternate,
                                     request_t *request, xlat_exp_t const **in,
-                                    fr_value_box_t **result)
+                                    fr_value_box_list_t *result)
 {
        xlat_exp_t const        *node = *in;
 
-       fr_cursor_tail(out);    /* Needed for reentrant behaviour and debugging */
+       fr_dcursor_tail(out);   /* Needed for reentrant behaviour and debugging */
 
        switch (node->type) {
        case XLAT_FUNC:
@@ -768,9 +780,9 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
                        char            *result_str = NULL;
                        ssize_t         slen;
 
-                       if (*result) {
-                               (void) talloc_list_get_type_abort(*result, fr_value_box_t);
-                               result_str = fr_value_box_list_aprint(NULL, *result, NULL, NULL);
+                       if (!fr_dlist_empty(result)) {
+                               fr_dlist_verify(result);
+                               result_str = fr_value_box_list_aprint(NULL, result, NULL, NULL);
                                if (!result_str) return XLAT_ACTION_FAIL;
                        } else {
                                result_str = talloc_typed_strdup(NULL, "");
@@ -787,7 +799,7 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
 
                        slen = node->call.func->func.sync(value, &str, node->call.func->buf_len,
                                                     node->call.func->mod_inst, NULL, request, result_str);
-                       xlat_debug_log_expansion(request, *in, *result);
+                       xlat_debug_log_expansion(request, *in, result);
                        if (slen < 0) {
                                talloc_free(value);
                                talloc_free(result_str);
@@ -809,7 +821,7 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
                                fr_value_box_bstrdup_buffer_shallow(NULL, value, NULL, str, false);
                        }
 
-                       fr_cursor_append(out, value);                   /* Append the result of the expansion */
+                       fr_dcursor_append(out, value);                  /* Append the result of the expansion */
                        talloc_free(result_str);
                        xlat_debug_log_result(request, value);
                }
@@ -819,26 +831,26 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
                {
                        xlat_action_t           xa;
                        xlat_thread_inst_t      *thread_inst;
-                       fr_value_box_t          *result_copy = NULL;
+                       fr_value_box_list_t     result_copy;
 
+                       fr_value_box_list_init(&result_copy);
                        thread_inst = xlat_thread_instance_find(node);
 
                        XLAT_DEBUG("** [%i] %s(func-async) - %%{%s:%pM}", unlang_interpret_stack_depth(request), __FUNCTION__,
-                                  node->fmt, *result);
+                                  node->fmt, result);
 
                        /*
                         *      Need to copy the input list in case
                         *      the async function mucks with it.
                         */
-                       if (RDEBUG_ENABLED2) fr_value_box_list_acopy(NULL, &result_copy, *result);
+                       if (RDEBUG_ENABLED2) fr_value_box_list_acopy(NULL, &result_copy, result);
 
-                       if (*result) (void) talloc_list_get_type_abort(*result, fr_value_box_t);
+                       if (!fr_dlist_empty(result)) { fr_dlist_verify(result); }
                        xa = node->call.func->func.async(ctx, out, request, node->call.inst->data, thread_inst->data, result);
-                       if (*result) (void) talloc_list_get_type_abort(*result, fr_value_box_t);
-
+                       if (!fr_dlist_empty(result)) { fr_dlist_verify(result); }
                        if (RDEBUG_ENABLED2) {
-                               xlat_debug_log_expansion(request, *in, result_copy);
-                               talloc_list_free(&result_copy);
+                               xlat_debug_log_expansion(request, *in, &result_copy);
+                               fr_dlist_talloc_free(&result_copy);
                        }
                        switch (xa) {
                        case XLAT_ACTION_FAIL:
@@ -853,8 +865,8 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
                                return xa;
 
                        case XLAT_ACTION_DONE:                          /* Process the result */
-                               fr_cursor_next(out);
-                               xlat_debug_log_result(request, fr_cursor_current(out));
+                               fr_dcursor_next(out);
+                               xlat_debug_log_result(request, fr_dcursor_current(out));
                                break;
                        }
                        break;
@@ -864,14 +876,14 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
 
        case XLAT_ALTERNATE:
        {
-               fr_cursor_t from;
+               fr_dcursor_t from;
 
                fr_assert(alternate);
 
                /*
                 *      No result from the first child, try the alternate
                 */
-               if (!*result) {
+               if (fr_dlist_empty(result)) {
                        /*
                         *      Already tried the alternate
                         */
@@ -896,25 +908,24 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
                *alternate = false;     /* Reset */
 
                xlat_debug_log_expansion(request, *in, NULL);
-               xlat_debug_log_result(request, *result);
+               xlat_debug_log_list_result(request, result);
 
-               (void) talloc_list_get_type_abort(*result, fr_value_box_t);
-               fr_cursor_init(&from, result);
-               fr_cursor_merge(out, &from);
-               fr_assert(!*result);
+               fr_dlist_verify(result);
+               fr_dcursor_init(&from, result);
+               fr_dcursor_merge(out, &from);
+               fr_assert(fr_dlist_empty(result));
        }
                break;
 
        case XLAT_GROUP:
        {
                fr_value_box_t  *value;
-               fr_cursor_t from;
 
                XLAT_DEBUG("** [%i] %s(child) - continuing %%{%s ...}", unlang_interpret_stack_depth(request), __FUNCTION__,
                           node->fmt);
 
-               fr_assert(*result != NULL);
-               (void) talloc_list_get_type_abort(*result, fr_value_box_t);
+               fr_assert(!fr_dlist_empty(result));
+               fr_dlist_verify(result);
 
                /*
                 *      If the input is a series of xlat expansions,
@@ -927,28 +938,25 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
 
                        MEM(value = fr_value_box_alloc_null(ctx));
 
-                       if (*result) {
-                               (void) talloc_list_get_type_abort(*result, fr_value_box_t);
-                               str = fr_value_box_list_aprint(value, *result, NULL, NULL);
+                       if (!fr_dlist_empty(result)) {
+                               fr_dlist_verify(result);
+                               str = fr_value_box_list_aprint(value, result, NULL, NULL);
                                if (!str) return XLAT_ACTION_FAIL;
                        } else {
                                str = talloc_typed_strdup(value, "");
                        }
 
-                       fr_value_box_strdup_shallow(value, NULL, str, fr_value_box_list_tainted(*result));
-                       talloc_free(*result);
-                       *result = value;
+                       fr_value_box_strdup_shallow(value, NULL, str, fr_value_box_list_tainted(result));
+                       fr_dlist_talloc_free(result);
+                       fr_dlist_insert_head(result, value);
                }
 
                MEM(value = fr_value_box_alloc(ctx, FR_TYPE_GROUP, NULL, false));
-               value->vb_group = *result;
-               *result = NULL;
+               fr_dlist_move(&value->vb_group, result);
                xlat_debug_log_expansion(request, *in, NULL);
                xlat_debug_log_result(request, value);
 
-               fr_cursor_init(&from, &value);
-               fr_cursor_merge(out, &from);
-               fr_assert(!value);
+               fr_dcursor_insert(out, value);
        }
                break;
 
@@ -990,7 +998,7 @@ xlat_action_t xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
  *     - XLAT_ACTION_DONE we're done, pop the frame.
  *     - XLAT_ACTION_FAIL an xlat module failed.
  */
-xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t const **child,
+xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_t const **child,
                              request_t *request, xlat_exp_t const **in)
 {
        xlat_exp_t const        *node = *in;
@@ -1005,7 +1013,7 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t cons
 
        for (node = *in; node; node = (*in)->next) {
                *in = node;             /* Update node in our caller */
-               fr_cursor_tail(out);    /* Needed for debugging */
+               fr_dcursor_tail(out);   /* Needed for debugging */
 
                switch (node->type) {
                case XLAT_LITERAL:
@@ -1026,7 +1034,7 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t cons
                         */
                        MEM(value = fr_value_box_alloc_null(ctx));
                        fr_value_box_bstrdup_buffer(value, value, NULL, node->fmt, false);
-                       fr_cursor_append(out, value);
+                       fr_dcursor_append(out, value);
                        continue;
 
                case XLAT_ONE_LETTER:
@@ -1036,11 +1044,11 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t cons
                        xlat_debug_log_expansion(request, node, NULL);
                        if (xlat_eval_one_letter(ctx, out, request, node->fmt[0]) == XLAT_ACTION_FAIL) {
                        fail:
-                               fr_cursor_free_list(out);       /* Only frees what we've added during this call */
+                               fr_dcursor_free_list(out);      /* Only frees what we've added during this call */
                                xa = XLAT_ACTION_FAIL;
                                goto finish;
                        }
-                       xlat_debug_log_result(request, fr_cursor_current(out));
+                       xlat_debug_log_result(request, fr_dcursor_current(out));
                        continue;
 
                case XLAT_ATTRIBUTE:
@@ -1049,7 +1057,7 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t cons
 
                        xlat_debug_log_expansion(request, node, NULL);
                        if (xlat_eval_pair_real(ctx, out, request, node->attr) == XLAT_ACTION_FAIL) goto fail;
-                       xlat_debug_log_result(request, fr_cursor_current(out));
+                       xlat_debug_log_result(request, fr_dcursor_current(out));
                        continue;
 
                case XLAT_VIRTUAL:
@@ -1071,16 +1079,17 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t cons
                        if (slen == 0) continue;
 
                        fr_value_box_bstrdup_buffer_shallow(NULL, value, NULL, str, false);
-                       fr_cursor_append(out, value);
-                       fr_cursor_next(out);
+                       fr_dcursor_append(out, value);
+                       fr_dcursor_next(out);
 
-                       xlat_debug_log_result(request, fr_cursor_current(out));
+                       xlat_debug_log_result(request, fr_dcursor_current(out));
                }
                        continue;
 
                case XLAT_FUNC:
                {
-                       fr_value_box_t *result = NULL;
+                       fr_value_box_list_t result;
+                       fr_value_box_list_init(&result);
 
                        XLAT_DEBUG("** [%i] %s(func) - %%{%s:...}", unlang_interpret_stack_depth(request), __FUNCTION__,
                                   node->fmt);
@@ -1117,7 +1126,7 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t cons
                                continue;
                        }
                        fr_value_box_bstrdup_buffer_shallow(NULL, value, NULL, str, false);
-                       fr_cursor_append(out, value);
+                       fr_dcursor_append(out, value);
                }
                        continue;
 #endif
@@ -1173,10 +1182,12 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons
        ssize_t                 slen;
        char                    *str = NULL, *child;
        char const              *p;
-       fr_value_box_t          *head = NULL, string, *value;
-       fr_cursor_t             cursor;
+       fr_value_box_t          string, *value;
+       fr_value_box_list_t     head;
+       fr_dcursor_t            cursor;
 
-       fr_cursor_talloc_init(&cursor, &head, fr_value_box_t);
+       fr_value_box_list_init(&head);
+       fr_dcursor_talloc_init(&cursor, &head, fr_value_box_t);
 
        XLAT_DEBUG("%.*sxlat aprint %d %s", lvl, xlat_spaces, node->type, node->fmt);
 
@@ -1203,20 +1214,20 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons
                 *      cast to a string until we're actually doing
                 *      the concatenation.
                 */
-               if (fr_value_box_cast(ctx, &string, FR_TYPE_STRING, NULL, head) < 0) {
+               if (fr_value_box_cast(ctx, &string, FR_TYPE_STRING, NULL, fr_dlist_head(&head)) < 0) {
                        RPERROR("Casting one letter expansion to string failed");
-                       fr_cursor_free_list(&cursor);
+                       fr_dcursor_free_list(&cursor);
                        return NULL;
                }
                memcpy(&str, &string.vb_strvalue, sizeof(str));
-               fr_cursor_free_list(&cursor);
+               fr_dcursor_free_list(&cursor);
                break;
 
        case XLAT_ATTRIBUTE:
                XLAT_DEBUG("xlat_sync_eval ATTR");
                if (xlat_eval_pair_real(ctx, &cursor, request, node->attr) == XLAT_ACTION_FAIL) return NULL;
 
-               value = fr_cursor_head(&cursor);
+               value = fr_dcursor_head(&cursor);
                if (!value) return NULL;
 
                /*
@@ -1228,7 +1239,7 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons
                if (!str) {
                attr_error:
                        RPERROR("Printing box to string failed");
-                       fr_cursor_free_list(&cursor);
+                       fr_dcursor_free_list(&cursor);
                        return NULL;
                }
 
@@ -1237,7 +1248,7 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons
                 *      temporarily until we do aggregation with
                 *      value boxes.
                 */
-               while ((value = fr_cursor_next(&cursor))) {
+               while ((value = fr_dcursor_next(&cursor))) {
                        char *more;
 
                        fr_value_box_aprint(ctx, &more, value, &fr_value_escape_double);
@@ -1246,7 +1257,7 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons
                        str = talloc_strdup_append_buffer(str, more);
                        talloc_free(more);
                }
-               fr_cursor_free_list(&cursor);
+               fr_dcursor_free_list(&cursor);
                break;
 
        case XLAT_VIRTUAL:
@@ -1272,9 +1283,9 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons
                 *      Will not handle yields.
                 */
                if (node->call.func->type == XLAT_FUNC_NORMAL) {
-                       fr_value_box_t  *result = NULL;
+                       fr_value_box_list_t     result;
                        TALLOC_CTX      *pool = talloc_new(NULL);
-
+                       fr_value_box_list_init(&result);
                        /*
                         *      Use the unlang stack to evaluate
                         *      the async xlat up until the point
@@ -1301,8 +1312,8 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons
                                return NULL;
                        }
 
-                       if (result) {
-                               str = fr_value_box_list_aprint(ctx, result, NULL, &fr_value_escape_double);
+                       if (!fr_dlist_empty(&result)) {
+                               str = fr_value_box_list_aprint(ctx, &result, NULL, &fr_value_escape_double);
                                if (!str) {
                                        RPEDEBUG("Failed concatenating xlat result string");
                                        talloc_free(pool);
index 7c174bfae530906484a6eac8dd0a349571106493..b03079fd9b602446edc883b4a84eef1c555da210 100644 (file)
@@ -162,16 +162,16 @@ xlat_t    *xlat_func_find(char const *name, ssize_t namelen);
 void           xlat_signal(xlat_func_signal_t signal, xlat_exp_t const *exp,
                            request_t *request, void *rctx, fr_state_signal_t action);
 
-xlat_action_t  xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
+xlat_action_t  xlat_frame_eval_resume(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                       xlat_func_resume_t resume, xlat_exp_t const *exp,
-                                      request_t *request, fr_value_box_t **result, void *rctx);
+                                      request_t *request, fr_value_box_list_t *result, void *rctx);
 
-xlat_action_t  xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_cursor_t *out,
+xlat_action_t  xlat_frame_eval_repeat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                       xlat_exp_t const **child, bool *alternate,
                                       request_t *request, xlat_exp_t const **in,
-                                      fr_value_box_t **result) CC_HINT(nonnull(1,2,3,5,6));
+                                      fr_value_box_list_t *result) CC_HINT(nonnull(1,2,3,5,6));
 
-xlat_action_t  xlat_frame_eval(TALLOC_CTX *ctx, fr_cursor_t *out, xlat_exp_t const **child,
+xlat_action_t  xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_t const **child,
                                request_t *request, xlat_exp_t const **in);
 
 int            xlat_eval_walk(xlat_exp_t *exp, xlat_walker_t walker, xlat_type_t type, void *uctx);
index 59ba921a08f1069f584ce4b41a362d367d42597a..f4a7795d9efbe4721580bbc8874d63edea363f46 100644 (file)
@@ -35,7 +35,6 @@ RCSIDH(libradius_h, "$Id$")
 #include <freeradius-devel/util/ascend.h>
 #include <freeradius-devel/util/base64.h>
 #include <freeradius-devel/util/conf.h>
-#include <freeradius-devel/util/cursor.h>
 #include <freeradius-devel/util/dcursor.h>
 #include <freeradius-devel/util/debug.h>
 #include <freeradius-devel/util/dict.h>
index 5ead4b6ac4cff392f17f79f637320ab7fcbeb7fa..eeb132bbc8cb77a155229efbb989edbe58991815 100644 (file)
@@ -776,7 +776,7 @@ char *fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
 
                        case 'M':
                        {
-                               fr_value_box_t const *in = va_arg(ap_q, fr_value_box_t const *);
+                               fr_value_box_list_t const *in = va_arg(ap_q, fr_value_box_list_t const *);
 
                                if (!in) {
                                        subst = talloc_strdup(NULL, "(null)");
index 6b38f8aeff5476fd25155bf7f1d68aea68cc37b5..094ad195b687fa1666717f2dd7c893f43dfc74f6 100644 (file)
@@ -49,7 +49,7 @@ RCSID("$Id$")
 #undef _VALUE_PRIVATE
 
 #include <freeradius-devel/util/ascend.h>
-#include <freeradius-devel/util/cursor.h>
+#include <freeradius-devel/util/dcursor.h>
 #include <freeradius-devel/util/dbuff.h>
 #include <freeradius-devel/util/hash.h>
 #include <freeradius-devel/util/hex.h>
@@ -500,7 +500,7 @@ static inline void fr_value_box_copy_meta(fr_value_box_t *dst, fr_value_box_t co
        dst->enumv = src->enumv;
        dst->type = src->type;
        dst->tainted = src->tainted;
-       dst->next = NULL;       /* copy one */
+       fr_dlist_entry_init(&dst->entry);
 }
 
 /** Compare two values
@@ -1811,8 +1811,7 @@ static inline int fr_value_box_cast_to_strvalue(TALLOC_CTX *ctx, fr_value_box_t
 
        case FR_TYPE_GROUP:
        {
-               fr_cursor_t cursor;
-               fr_value_box_t *vb;
+               fr_value_box_t *vb = NULL;
 
                /*
                 *      Initialise an empty buffer we can
@@ -1820,9 +1819,7 @@ static inline int fr_value_box_cast_to_strvalue(TALLOC_CTX *ctx, fr_value_box_t
                 */
                if (fr_value_box_bstrndup(ctx, dst, dst_enumv, NULL, 0, src->tainted) < 0) return -1;
 
-               for (vb = fr_cursor_init(&cursor, &src->vb_group);
-                    vb;
-                    vb = fr_cursor_next(&cursor)) {
+               while ((vb = fr_dlist_next(&src->vb_group, vb))) {
                        /*
                         *      Attempt to cast to a string so
                         *      we can append.
@@ -1895,8 +1892,7 @@ static inline int fr_value_box_cast_to_octets(TALLOC_CTX *ctx, fr_value_box_t *d
 
        case FR_TYPE_GROUP:
        {
-               fr_cursor_t cursor;
-               fr_value_box_t *vb;
+               fr_value_box_t *vb = NULL;
 
                /*
                 *      Initialise an empty buffer we can
@@ -1904,9 +1900,7 @@ static inline int fr_value_box_cast_to_octets(TALLOC_CTX *ctx, fr_value_box_t *d
                 */
                if (fr_value_box_memdup(ctx, dst, dst_enumv, NULL, 0, src->tainted) < 0) return -1;
 
-               for (vb = fr_cursor_init(&cursor, &src->vb_group);
-                    vb;
-                    vb = fr_cursor_next(&cursor)) {
+               while ((vb = fr_dlist_next(&src->vb_group, vb))) {
                        /*
                         *      Attempt to cast to octets so
                         *      we can append;
@@ -3020,6 +3014,13 @@ int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb,
                               fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
 {
        fr_value_box_t tmp;
+       /*
+        *      Store list poiters to restore later - fr_value_box_cast clears them
+        */
+       fr_dlist_t entry = {
+               .next = vb->entry.next,
+               .prev = vb->entry.prev
+       };
 
        /*
         *      Simple case, destination type and current
@@ -3042,6 +3043,12 @@ int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb,
 
        fr_value_box_clear(&tmp);       /* Clear out any old buffers */
 
+       /*
+        *      Restore list pointers
+        */
+       vb->entry.next = entry.next;
+       vb->entry.prev = entry.prev;
+
        return 0;
 }
 
@@ -3128,31 +3135,13 @@ void fr_value_box_clear_value(fr_value_box_t *data)
                 *      This ensures orderly freeing, regardless
                 *      of talloc hierarchy.
                 */
-               switch (data->datum.children.type) {
-               case FR_VALUE_BOX_LIST_SINGLE:
-               {
-                       fr_cursor_t     cursor;
-                       fr_value_box_t  *vb;
-
-                       for (vb = fr_cursor_init(&cursor, &data->datum.children.slist);
-                            vb;
-                            vb = fr_cursor_next(&cursor)) {
-                               fr_value_box_clear_value(vb);
-                               talloc_free(vb);
-                       }
-               }
-                       break;
-
-               case FR_VALUE_BOX_LIST_DOUBLE:
                {
                        fr_value_box_t  *vb = NULL;
 
-                       while ((vb = fr_dlist_next(&data->datum.children.dlist, vb))) {
+                       while ((vb = fr_dlist_next(&data->datum.children, vb))) {
                                fr_value_box_clear_value(vb);
                                talloc_free(vb);
                        }
-               }
-                       break;
                }
                return;
 
@@ -4549,7 +4538,7 @@ finish:
         *      Fixup enumvs
         */
        dst->enumv = dst_enumv;
-       dst->next = NULL;
+       fr_dlist_entry_init(&dst->entry);
 
        return 0;
 }
@@ -4799,7 +4788,7 @@ ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff
                /*
                 *      Be lazy by just converting it to a string, and then printing the string.
                 */
-               if (fr_value_box_cast_to_strvalue(NULL, &vb, FR_TYPE_STRING, NULL, data->vb_group) < 0) return 0;
+               if (fr_value_box_cast_to_strvalue(NULL, &vb, FR_TYPE_STRING, NULL, data) < 0) return 0;
 
                slen = fr_value_box_print(&our_out, &vb, e_rules);
                fr_value_box_clear(&vb);
@@ -4869,13 +4858,14 @@ ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, f
  *     - -1 on failure.
  */
 int fr_value_box_list_concat(TALLOC_CTX *ctx,
-                            fr_value_box_t *out, fr_value_box_t **list, fr_type_t type, bool free_input)
+                            fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, bool free_input)
 {
        TALLOC_CTX              *pool;
-       fr_cursor_t             cursor;
+       fr_dcursor_t            cursor;
        fr_value_box_t const    *vb;
+       fr_value_box_t          *head_vb;
 
-       if (!list || !*list) {
+       if (!list || fr_dlist_empty(list)) {
                fr_strerror_const("Invalid arguments.  List was NULL");
                return -1;
        }
@@ -4891,15 +4881,19 @@ int fr_value_box_list_concat(TALLOC_CTX *ctx,
                return -1;
        }
 
-       fr_cursor_init(&cursor, list);
+       head_vb = fr_dlist_head(list);
+       fr_dcursor_init(&cursor, list);
 
        /*
         *      Allow concatenating in place
         */
-       if (out == *list) {
-               if ((*list)->type != type) {
+       if (out == head_vb) {
+               if (head_vb->type != type) {
                        fr_value_box_t from_cast;
-                       fr_value_box_t *next = out->next;
+                       fr_dlist_t entry = {
+                               .next = out->entry.next,
+                               .prev = out->entry.prev
+                       };
 
                        /*
                         *      Two phase, as the casting code doesn't
@@ -4907,30 +4901,33 @@ int fr_value_box_list_concat(TALLOC_CTX *ctx,
                         */
                        if (fr_value_box_cast(ctx, &from_cast, type, NULL, out) < 0) return -1;
                        if (fr_value_box_copy(ctx, out, &from_cast) < 0) return -1;
-                       out->next = next;                       /* Restore the next pointer */
+
+                       out->entry.next = entry.next;           /* Restore the list pointers */
+                       out->entry.prev = entry.prev;
+
                }
-               fr_cursor_next(&cursor);
+               fr_dcursor_next(&cursor);
        } else {
-               if (fr_value_box_cast(ctx, out, type, NULL, *list) < 0) return -1;      /* Decomposes to copy */
+               if (fr_value_box_cast(ctx, out, type, NULL, head_vb) < 0) return -1;    /* Decomposes to copy */
 
                if (free_input) {
-                       fr_cursor_free_item(&cursor);           /* Advances cursor */
+                       fr_dcursor_free_item(&cursor);          /* Advances cursor */
                } else {
-                       fr_cursor_next(&cursor);
+                       fr_dcursor_next(&cursor);
                }
        }
 
        /*
         *      Imploding a one element list.
         */
-       if (!fr_cursor_current(&cursor)) return 0;
+       if (!fr_dcursor_current(&cursor)) return 0;
 
        pool = talloc_pool(NULL, 255);  /* To absorb the temporary strings */
 
        /*
         *      Join the remaining values
         */
-       while ((vb = fr_cursor_current(&cursor))) {
+       while ((vb = fr_dcursor_current(&cursor))) {
                fr_value_box_t from_cast;
                fr_value_box_t const *n;
 
@@ -4959,9 +4956,9 @@ int fr_value_box_list_concat(TALLOC_CTX *ctx,
                }
 
                if (free_input) {
-                       fr_cursor_free_item(&cursor);           /* Advances cursor */
+                       fr_dcursor_free_item(&cursor);          /* Advances cursor */
                } else {
-                       fr_cursor_next(&cursor);
+                       fr_dcursor_next(&cursor);
                }
        }
 
@@ -4973,25 +4970,25 @@ int fr_value_box_list_concat(TALLOC_CTX *ctx,
 /** Concatenate the string representations of a list of value boxes together
  *
  * @param[in] ctx      to allocate the buffer in.
- * @param[in] head     of the list of value boxes.
+ * @param[in] list     of value boxes.
  * @param[in] delim    to insert between value box values.
  * @param[in] e_rules  to control escaping of the concatenated elements.
  * @return
  *     - NULL on error.
  *     - The concatenation of the string values of the value box list on success.
  */
-char *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_t const *head, char const *delim,
+char *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
                               fr_sbuff_escape_rules_t const *e_rules)
 {
-       fr_value_box_t const    *vb = head;
+       fr_value_box_t const    *vb = fr_dlist_head(list);
        char                    *aggr, *td = NULL;
        TALLOC_CTX              *pool = NULL;
 
-       if (!head) return NULL;
+       if (!vb) return NULL;
 
        fr_value_box_aprint(ctx, &aggr, vb, e_rules);
        if (!aggr) return NULL;
-       if (!vb->next) return aggr;
+       if (!fr_dlist_next(list, vb)) return aggr;
 
        /*
         *      If we're aggregating more values,
@@ -5000,7 +4997,7 @@ char *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_t const *head, char
        pool = talloc_pool(NULL, 255);
        if (delim) td = talloc_typed_strdup(pool, delim);
 
-       while ((vb = vb->next)) {
+       while ((vb = fr_dlist_next(list, vb))) {
                char *str, *new_aggr;
 
                fr_value_box_aprint(pool, &str, vb, e_rules);
@@ -5051,12 +5048,13 @@ uint32_t fr_value_box_hash_update(fr_value_box_t const *vb, uint32_t hash)
  *     - >= 0 number of array elements in argv
  *     - <0 on error
  */
-int fr_value_box_list_flatten_argv(TALLOC_CTX *ctx, char ***argv_p, fr_value_box_t const *in)
+int fr_value_box_list_flatten_argv(TALLOC_CTX *ctx, char ***argv_p, fr_value_box_list_t const *in)
 {
        int i, argc;
        char **argv;
+       fr_value_box_t *head = fr_dlist_head(in);
 
-       if (in->type != FR_TYPE_GROUP) {
+       if (head->type != FR_TYPE_GROUP) {
                argc = 1;
 
        } else {
@@ -5066,21 +5064,21 @@ int fr_value_box_list_flatten_argv(TALLOC_CTX *ctx, char ***argv_p, fr_value_box
        argv = talloc_zero_array(ctx, char *, argc + 1);
        if (!argv) return -1;
 
-       if (in->type != FR_TYPE_GROUP) {
-               fr_value_box_aprint(argv, &argv[0], in, NULL);
+       if (head->type != FR_TYPE_GROUP) {
+               fr_value_box_aprint(argv, &argv[0], head, NULL);
        } else {
                fr_value_box_t const *in_p;
 
                /*
                 *      Print the children of each group into the argv array.
                 */
-               for (in_p = in, i = 0;
+               for (in_p = head, i = 0;
                     in_p;
-                    in_p = in_p->next) {
-                       if (!in_p->vb_group) {
+                    in_p = fr_dlist_next(in, in_p)) {
+                       if (fr_dlist_empty(&in_p->vb_group)) {
                                argv[i] = talloc_typed_strdup(argv, "");
                        } else {
-                               fr_value_box_aprint(argv, &argv[i], in_p->vb_group, NULL);
+                               fr_value_box_aprint(argv, &argv[i], in_p, NULL);
                        }
                        if (!argv[i]) {
                                talloc_free(argv);
@@ -5116,30 +5114,22 @@ int fr_value_box_list_flatten_argv(TALLOC_CTX *ctx, char ***argv_p, fr_value_box
  *     - A duplicate list of value boxes, allocated in the context of 'ctx'
  *     - NULL on error, or empty input list.
  */
-int fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_t **out, fr_value_box_t const *in)
+int fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_value_box_list_t const *in)
 {
-       fr_value_box_t const *in_p;
-       fr_cursor_t cursor;
-
-       *out = NULL;
-
-       fr_cursor_init(&cursor, out);
+       fr_value_box_t const *in_p = NULL;
 
-       for (in_p = in;
-            in_p;
-            in_p = in_p->next) {
+       while ((in_p = fr_dlist_next(in, in_p))) {
                fr_value_box_t *n = NULL;
 
                n = fr_value_box_alloc_null(ctx);
                if (!n) {
                error:
-                       fr_cursor_head(&cursor);
-                       fr_cursor_free_list(&cursor);
+                       fr_dlist_talloc_free(out);
                        return -1;
                }
 
                if (fr_value_box_copy(n, n, in_p) < 0) goto error;
-               fr_cursor_append(&cursor, n);
+               fr_dlist_insert_tail(out, n);
        }
 
        return 0;
@@ -5152,33 +5142,15 @@ int fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_t **out, fr_value_box_
  *     - true if a list member is tainted.
  *     - false if no list members are tainted.
  */
-bool fr_value_box_list_tainted(fr_value_box_t const *head)
+bool fr_value_box_list_tainted(fr_value_box_list_t const *head)
 {
-       if (!head) return false;
-
-       do {
-               if (head->tainted) return true;
-       } while ((head = head->next));
-
-       return false;
-}
+       fr_value_box_t *vb = NULL;
 
-/** Get list member at a given index
- *
- * @param[in] head     of list.
- * @param[in] index    of member to return.
- * @return
- *     - NULL if there is no member at given index
- *     - member if it exists
- */
-fr_value_box_t *fr_value_box_list_get(fr_value_box_t *head, int index)
-{
-       int i = 0;
+       if (fr_dlist_empty(head)) return false;
 
-       while (i < index && head) {
-               head = head->next;
-               i++;
+       while ((vb = fr_dlist_next(head, vb))) {
+               if (vb->tainted) return true;
        }
 
-       return head;
+       return false;
 }
index 2a5c32ccd0b3d53195423a79043f070999f21582..b2b20e172edce94c73dcdba675befe6e58a48eba 100644 (file)
@@ -84,22 +84,11 @@ extern fr_sbuff_escape_rules_t fr_value_escape_solidus;
 extern fr_sbuff_escape_rules_t fr_value_escape_backtick;
 extern fr_sbuff_escape_rules_t *fr_value_escape_by_quote[T_TOKEN_LAST];
 
-typedef enum {
-       FR_VALUE_BOX_LIST_SINGLE = 0,                           //!< Singly linked list.
-       FR_VALUE_BOX_LIST_DOUBLE,                               //!< Doubly linked list.
-} fr_value_box_list_type_t;
-
-/** Placeholder structure to represent lists of value boxes
+/** Lists of value boxes
  *
- * Should have additional fields added later.
+ * Specifically define a type for lists of value_box_t to aid type checking
  */
-typedef struct {
-       union {
-               fr_value_box_t          *slist;                 //!< The head of the list.
-               fr_dlist_head_t         dlist;                  //!< Doubly linked list head.
-       };
-       fr_value_box_list_type_t type;                          //!< What type of list this is.
-} fr_value_box_list_t;
+typedef fr_dlist_head_t        fr_value_box_list_t;
 
 /** Union containing all data types supported by the server
  *
@@ -164,7 +153,7 @@ struct value_box_s {
 
        fr_dict_attr_t const            *enumv;                 //!< Enumeration values.
 
-       fr_value_box_t                  *next;                  //!< Next in a series of value_box.
+       fr_dlist_t                      entry;                  //!< Doubly linked list entry.
 };
 
 /** @name Field accessors for #fr_value_box_t
@@ -176,7 +165,7 @@ struct value_box_s {
  */
 #define vb_strvalue                            datum.strvalue
 #define vb_octets                              datum.octets
-#define vb_group                               datum.children.slist
+#define vb_group                               datum.children
 
 #define vb_ip                                  datum.ip
 
@@ -295,36 +284,36 @@ struct value_box_s {
 
 /** Returns the number of boxes in a list of value boxes
  *
- * @param[in] head     of the value box list.
+ * @param[in] list     of value boxes.
  * @return Number of boxes in the list.
  */
-static inline size_t fr_value_box_list_len(fr_value_box_t const *head)
+static inline size_t fr_value_box_list_len(fr_value_box_list_t const *list)
 {
-       size_t i;
-
-       for (i = 0; head; head = head->next, i++);
-
-       return i;
+       return fr_dlist_num_elements(list);
 }
 
 /** Determines whether a list contains the number of boxes required
  *
- * @note More efficient than fr_value_box_list_len for argument validation as it
- *     doesn't walk the entire list.
- *
- * @param[in] head     of the list of value boxes.
+ * @param[in] list     of value boxes.
  * @param[in] min      The number of boxes required to return true.
  * @return
  *     - true if the list has at least min boxes.
  *     - false if the list has fewer than min boxes.
  */
-static inline bool fr_value_box_list_len_min(fr_value_box_t const *head, size_t min)
+static inline bool fr_value_box_list_len_min(fr_value_box_list_t const *list, size_t min)
 {
-       size_t i;
+       size_t i = fr_dlist_num_elements(list);
 
-       for (i = 0; head && i < min; head = head->next, i++);
+       return (i >= min);
+}
 
-       return (i == min);
+/** Initialise a list of fr_value_box_t
+ *
+ * @param[in,out] list         to initialise
+ */
+static inline void fr_value_box_list_init(fr_value_box_list_t *list)
+{
+       fr_dlist_talloc_init(list, fr_value_box_t, entry);
 }
 /** @} */
 
@@ -361,6 +350,8 @@ static inline CC_HINT(always_inline) void fr_value_box_init(fr_value_box_t *vb,
                .enumv = enumv,
                .tainted = tainted
        }, sizeof(*vb));
+       fr_dlist_entry_init(&vb->entry);
+       if (type == FR_TYPE_GROUP) fr_value_box_list_init(&vb->vb_group);
 }
 
 /** Initialise an empty/null box that will be filled later
@@ -731,19 +722,17 @@ int               fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst,
  * @{
  */
 int            fr_value_box_list_concat(TALLOC_CTX *ctx,
-                                        fr_value_box_t *out, fr_value_box_t **list,
+                                        fr_value_box_t *out, fr_value_box_list_t *list,
                                         fr_type_t type, bool free_input);
 
-char           *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_t const *head, char const *delim,
+char           *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
                                         fr_sbuff_escape_rules_t const *e_rules);
 
-int            fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_t **out, fr_value_box_t const *in);
-
-bool           fr_value_box_list_tainted(fr_value_box_t const *head);
+int            fr_value_box_list_acopy(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_value_box_list_t const *in);
 
-fr_value_box_t*        fr_value_box_list_get(fr_value_box_t *head, int index);
+bool           fr_value_box_list_tainted(fr_value_box_list_t const *head);
 
-int            fr_value_box_list_flatten_argv(TALLOC_CTX *ctx, char ***argv_p, fr_value_box_t const *in);
+int            fr_value_box_list_flatten_argv(TALLOC_CTX *ctx, char ***argv_p, fr_value_box_list_t const *in);
 /** @} */
 
 /*
index 86a86fe5362dcac7f5bd91747fa54f480bf25c13..814009f314c5075a61b14d7d30a18b2841f5998f 100644 (file)
@@ -66,16 +66,17 @@ static int always_xlat_instantiate(void *xlat_inst, UNUSED xlat_exp_t const *exp
  *
  * Example: "%{db_status:fail}"
  */
-static xlat_action_t always_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t always_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                 request_t *request, void const *xlat_inst,
                                 UNUSED void *xlat_thread_inst,
-                                fr_value_box_t **in)
+                                fr_value_box_list_t *in)
 {
        rlm_always_t const      *inst = talloc_get_type_abort_const(*((void const * const *)xlat_inst),rlm_always_t);
        module_instance_t       *mi;
        char const              *status;
        char const              *p;
        fr_value_box_t          *vb;
+       fr_value_box_t          *in_head = fr_dlist_head(in);
 
        mi = module_by_name(NULL, inst->xlat_name);
        if (!mi) {
@@ -91,8 +92,8 @@ static xlat_action_t always_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
                p = fr_table_str_by_value(rcode_table, mi->code, "<invalid>");
        }
 
-       if (!(*in) || (*in)->vb_length == 0) goto done;
-       status = (*in)->vb_strvalue;
+       if (!in_head || in_head->vb_length == 0) goto done;
+       status = in_head->vb_strvalue;
 
        /*
         *      Set the module status
@@ -117,7 +118,7 @@ done:
 
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_strdup(vb, vb, NULL, p, false);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 
index cd82ece3c271dbfa9a9549bbabe1535cf7dc538b..6b291cbfc8abe8c23a49a041dc75cf17ec40b664 100644 (file)
@@ -73,25 +73,26 @@ fr_dict_attr_autoload_t rlm_chap_dict_attr[] = {
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_func_chap_password(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_func_chap_password(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                             request_t *request, UNUSED void const *xlat_inst,
                                             UNUSED void *xlat_thread_inst,
-                                            fr_value_box_t **in)
+                                            fr_value_box_list_t *in)
 {
        uint8_t         chap_password[1 + RADIUS_CHAP_CHALLENGE_LENGTH];
        fr_value_box_t  *vb;
        fr_pair_t       *challenge;
        uint8_t const   *vector;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
        /*
         *      If there's no input, there's no output
         */
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("chap requires a password as input");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
@@ -107,11 +108,11 @@ static xlat_action_t xlat_func_chap_password(TALLOC_CTX *ctx, fr_cursor_t *out,
                vector = request->packet->vector;
        }
        fr_radius_encode_chap_password(chap_password, (uint8_t)(fr_rand() & 0xff), vector,
-                                      (*in)->vb_strvalue, (*in)->vb_length);
+                                      in_head->vb_strvalue, in_head->vb_length);
 
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_memdup(vb, vb, NULL, chap_password, sizeof(chap_password), false);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
index 4ef5a1a3582628ab32fc98105031009a551965c7..b0cf3d83c15704f5329c25f1a2e066fff38a36db 100644 (file)
@@ -463,9 +463,9 @@ static int cipher_rsa_certificate_file_load(TALLOC_CTX *ctx, void *out, UNUSED v
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t cipher_rsa_encrypt_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t cipher_rsa_encrypt_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                             request_t *request, UNUSED void const *xlat_inst, void *xlat_thread_inst,
-                                            fr_value_box_t **in)
+                                            fr_value_box_list_t *in)
 {
        rlm_cipher_rsa_thread_inst_t    *xt = talloc_get_type_abort(*((void **)xlat_thread_inst),
                                                                    rlm_cipher_rsa_thread_inst_t);
@@ -477,18 +477,19 @@ static xlat_action_t cipher_rsa_encrypt_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        size_t                          ciphertext_len;
 
        fr_value_box_t                  *vb;
+       fr_value_box_t                  *in_head = fr_dlist_head(in);
 
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("encrypt requires one or arguments (<plaintext>...)");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                fr_tls_log_error(request, "Failed concatenating arguments to form plaintext");
                return XLAT_ACTION_FAIL;
        }
-       plaintext = (*in)->vb_strvalue;
-       plaintext_len = (*in)->vb_length;
+       plaintext = in_head->vb_strvalue;
+       plaintext_len = in_head->vb_length;
 
        /*
         *      Figure out the buffer we need
@@ -510,7 +511,7 @@ static xlat_action_t cipher_rsa_encrypt_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        }
        RHEXDUMP3(ciphertext, ciphertext_len, "Ciphertext (%zu bytes)", ciphertext_len);
        MEM(fr_value_box_mem_realloc(vb, NULL, vb, ciphertext_len) == 0);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -527,9 +528,9 @@ static xlat_action_t cipher_rsa_encrypt_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t cipher_rsa_sign_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t cipher_rsa_sign_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                          request_t *request, void const *xlat_inst, void *xlat_thread_inst,
-                                         fr_value_box_t **in)
+                                         fr_value_box_list_t *in)
 {
        rlm_cipher_t const              *inst = talloc_get_type_abort_const(*((void const * const *)xlat_inst),
                                                                            rlm_cipher_t);
@@ -545,18 +546,19 @@ static xlat_action_t cipher_rsa_sign_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        unsigned int                    digest_len = 0;
 
        fr_value_box_t                  *vb;
+       fr_value_box_t                  *in_head = fr_dlist_head(in);
 
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("sign requires one or arguments (<plaintext>...)");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                REDEBUG("Failed concatenating arguments to form plaintext");
                return XLAT_ACTION_FAIL;
        }
-       msg = (*in)->vb_strvalue;
-       msg_len = (*in)->vb_length;
+       msg = in_head->vb_strvalue;
+       msg_len = in_head->vb_length;
 
        /*
         *      First produce a digest of the message
@@ -593,7 +595,7 @@ static xlat_action_t cipher_rsa_sign_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
                return XLAT_ACTION_FAIL;
        }
        MEM(fr_value_box_mem_realloc(vb, NULL, vb, sig_len) == 0);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -610,9 +612,9 @@ static xlat_action_t cipher_rsa_sign_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t cipher_rsa_decrypt_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t cipher_rsa_decrypt_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                             request_t *request, UNUSED void const *xlat_inst, void *xlat_thread_inst,
-                                            fr_value_box_t **in)
+                                            fr_value_box_list_t *in)
 {
        rlm_cipher_rsa_thread_inst_t    *xt = talloc_get_type_abort(*((void **)xlat_thread_inst),
                                                                    rlm_cipher_rsa_thread_inst_t);
@@ -624,18 +626,19 @@ static xlat_action_t cipher_rsa_decrypt_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        size_t                          plaintext_len;
 
        fr_value_box_t                  *vb;
+       fr_value_box_t                  *in_head = fr_dlist_head(in);
 
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("decrypt requires one or more arguments (<ciphertext>...)");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_OCTETS, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_OCTETS, true) < 0) {
                REDEBUG("Failed concatenating arguments to form plaintext");
                return XLAT_ACTION_FAIL;
        }
-       ciphertext = (*in)->vb_octets;
-       ciphertext_len = (*in)->vb_length;
+       ciphertext = in_head->vb_octets;
+       ciphertext_len = in_head->vb_length;
 
        /*
         *      Decrypt the ciphertext
@@ -656,7 +659,7 @@ static xlat_action_t cipher_rsa_decrypt_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        }
        RHEXDUMP3((uint8_t const *)plaintext, plaintext_len, "Plaintext (%zu bytes)", plaintext_len);
        MEM(fr_value_box_bstr_realloc(vb, NULL, vb, plaintext_len) == 0);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -674,9 +677,9 @@ static xlat_action_t cipher_rsa_decrypt_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t cipher_rsa_verify_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t cipher_rsa_verify_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                            request_t *request, void const *xlat_inst, void *xlat_thread_inst,
-                                           fr_value_box_t **in)
+                                           fr_value_box_list_t *in)
 {
        rlm_cipher_t const              *inst = talloc_get_type_abort_const(*((void const * const *)xlat_inst),
                                                                            rlm_cipher_t);
@@ -692,8 +695,10 @@ static xlat_action_t cipher_rsa_verify_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        unsigned int                    digest_len = 0;
 
        fr_value_box_t                  *vb;
+       fr_value_box_t                  *in_head = fr_dlist_pop_head(in);
+       fr_value_box_t                  *args;
 
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("verification requires two or more arguments (<signature>, <message>...)");
                return XLAT_ACTION_FAIL;
        }
@@ -701,7 +706,7 @@ static xlat_action_t cipher_rsa_verify_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        /*
         *      Check we have at least two boxed values
         */
-       if (!(*in)->next) {
+       if (fr_dlist_empty(in)) {
                REDEBUG("Missing message data arg or message data was (null)");
                return XLAT_ACTION_FAIL;
        }
@@ -711,25 +716,31 @@ static xlat_action_t cipher_rsa_verify_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
         *      isn't already in that form.
         *      It could be hexits or base64 or some other encoding.
         */
-       if ((*in)->type != FR_TYPE_OCTETS) {
+       if (in_head->type != FR_TYPE_OCTETS) {
                REDEBUG("Signature argument wrong type, expected %s, got %s.  "
                        "Use %%{base64_decode:<text>} or %%{hex_decode:<text>} if signature is armoured",
                        fr_table_str_by_value(fr_value_box_type_table, FR_TYPE_OCTETS, "?Unknown?"),
-                       fr_table_str_by_value(fr_value_box_type_table, (*in)->type, "?Unknown?"));
+                       fr_table_str_by_value(fr_value_box_type_table, in_head->type, "?Unknown?"));
                return XLAT_ACTION_FAIL;
        }
-       sig = (*in)->vb_octets;
-       sig_len = (*in)->vb_length;
+       sig = in_head->vb_octets;
+       sig_len = in_head->vb_length;
 
        /*
         *      Concat (...) args to get message data
         */
-       if (fr_value_box_list_concat(ctx, (*in)->next, &((*in)->next), FR_TYPE_STRING, true) < 0) {
+       args = fr_dlist_head(in);
+       if (fr_value_box_list_concat(ctx, args, in, FR_TYPE_STRING, true) < 0) {
                REDEBUG("Failed concatenating arguments to form plaintext");
                return XLAT_ACTION_FAIL;
        }
-       msg = (*in)->next->vb_strvalue;
-       msg_len = (*in)->next->vb_length;
+       msg = args->vb_strvalue;
+       msg_len = args->vb_length;
+
+       /*
+        *      Return the first entry to the "in" vb list
+        */
+       fr_dlist_insert_head(in, in_head);
 
        /*
         *      The argument separator also gets rolled into
@@ -774,13 +785,13 @@ static xlat_action_t cipher_rsa_verify_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        case 1:         /* success (signature valid) */
                MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL, false));
                vb->vb_bool = true;
-               fr_cursor_append(out, vb);
+               fr_dcursor_append(out, vb);
                break;
 
        case 0:         /* failure (signature not valid) */
                MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL, false));
                vb->vb_bool = false;
-               fr_cursor_append(out, vb);
+               fr_dcursor_append(out, vb);
                break;
 
        default:
index 22e06cffe8ee9c0ff64e653b64af7d5d7739755f..c696b536d1a26dc997d9ab1741c50155e3e4f04c 100644 (file)
@@ -115,26 +115,27 @@ static int _map_proc_client_get_vp(TALLOC_CTX *ctx, fr_pair_list_t *out, request
  *     - #RLM_MODULE_FAIL if an error occurred.
  */
 static rlm_rcode_t map_proc_client(UNUSED void *mod_inst, UNUSED void *proc_inst, request_t *request,
-                                  fr_value_box_t **client_override, fr_map_list_t const *maps)
+                                  fr_value_box_list_t *client_override, fr_map_list_t const *maps)
 {
        rlm_rcode_t             rcode = RLM_MODULE_OK;
        map_t const             *map = NULL;
        RADCLIENT               *client;
        client_get_vp_ctx_t     uctx;
 
-       if (*client_override) {
+       if (!fr_dlist_empty(client_override)) {
                fr_ipaddr_t     ip;
                char const      *client_str;
+               fr_value_box_t  *client_override_head = fr_dlist_head(client_override);
 
                /*
                 *      Concat don't asprint, as this becomes a noop
                 *      in the vast majority of cases.
                 */
-               if (fr_value_box_list_concat(request, *client_override, client_override, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat(request, client_override_head, client_override, FR_TYPE_STRING, true) < 0) {
                        REDEBUG("Failed concatenating input data");
                        return RLM_MODULE_FAIL;
                }
-               client_str = (*client_override)->vb_strvalue;
+               client_str = client_override_head->vb_strvalue;
 
                if (fr_inet_pton(&ip, client_str, -1, AF_UNSPEC, false, true) < 0) {
                        REDEBUG("\"%s\" is not a valid IPv4 or IPv6 address", client_str);
index eee486f8a0d62a7e0e982a5a4521717dd1133f2e..b82613690b03ea525cea15efd745747a657127e9 100644 (file)
@@ -31,7 +31,7 @@ RCSID("$Id$")
 #include <freeradius-devel/server/map_proc.h>
 
 static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_t *request,
-                               fr_value_box_t **key, fr_map_list_t const *maps);
+                               fr_value_box_list_t *key, fr_map_list_t const *maps);
 
 /*
  *     Define a structure for our module configuration.
@@ -975,23 +975,24 @@ finish:
  *     - #RLM_MODULE_FAIL if an error occurred.
  */
 static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_t *request,
-                               fr_value_box_t **key, fr_map_list_t const *maps)
+                               fr_value_box_list_t *key, fr_map_list_t const *maps)
 {
        rlm_csv_t               *inst = talloc_get_type_abort(mod_inst, rlm_csv_t);
+       fr_value_box_t          *key_head = fr_dlist_head(key);
 
-       if (!*key) {
+       if (!key_head) {
                REDEBUG("CSV key cannot be (null)");
                return RLM_MODULE_FAIL;
        }
 
        if ((inst->key_data_type == FR_TYPE_OCTETS) || (inst->key_data_type == FR_TYPE_STRING)) {
-               if (fr_value_box_list_concat(request, *key, key, inst->key_data_type, true) < 0) {
+               if (fr_value_box_list_concat(request, key_head, key, inst->key_data_type, true) < 0) {
                        REDEBUG("Failed parsing key");
                        return RLM_MODULE_FAIL;
                }
        }
 
-       return mod_map_apply(inst, request, *key, maps);
+       return mod_map_apply(inst, request, key_head, maps);
 }
 
 
index 749ca590f399f44b07e0d4144d3d78c8426b8552..42630d8c8ac8cbc0fbade2bf1d4fcb5c1de2579e 100644 (file)
@@ -182,10 +182,10 @@ static unlang_action_t CC_HINT(nonnull) mod_delay(rlm_rcode_t *p_result, module_
        return unlang_module_yield(request, mod_delay_return, mod_delay_cancel, yielded_at);
 }
 
-static xlat_action_t xlat_delay_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_delay_resume(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                       request_t *request,
                                       UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                      UNUSED fr_value_box_t **in, void *rctx)
+                                      UNUSED fr_value_box_list_t *in, void *rctx)
 {
        fr_time_t       *yielded_at = talloc_get_type_abort(rctx, fr_time_t);
        fr_time_t       delayed;
@@ -199,7 +199,7 @@ static xlat_action_t xlat_delay_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
 
        RDEBUG3("Request delayed by %pVs", vb);
 
-       fr_cursor_insert(out, vb);
+       fr_dcursor_insert(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -221,14 +221,15 @@ static void xlat_delay_cancel(request_t *request, UNUSED void *instance, UNUSED
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_delay(TALLOC_CTX *ctx, UNUSED fr_cursor_t *out,
+static xlat_action_t xlat_delay(TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
                                request_t *request, void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                               fr_value_box_t **in)
+                               fr_value_box_list_t *in)
 {
        rlm_delay_t const       *inst;
        void                    *instance;
        fr_time_delta_t         delay;
        fr_time_t               resume_at, *yielded_at;
+       fr_value_box_t          *in_head = fr_dlist_head(in);
 
        memcpy(&instance, xlat_inst, sizeof(instance)); /* Stupid const issues */
 
@@ -245,20 +246,20 @@ static xlat_action_t xlat_delay(TALLOC_CTX *ctx, UNUSED fr_cursor_t *out,
         *      immediately re-enqueue the request.
         *      This is very useful for testing.
         */
-       if (!*in) {
+       if (!in_head) {
                if (!fr_cond_assert(delay_add(request, &resume_at, *yielded_at, 0, true, true) == 0)) {
                        return XLAT_ACTION_FAIL;
                }
                goto yield;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                talloc_free(yielded_at);
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_time_delta_from_str(&delay, (*in)->vb_strvalue, FR_TIME_RES_SEC) < 0) {
+       if (fr_time_delta_from_str(&delay, in_head->vb_strvalue, FR_TIME_RES_SEC) < 0) {
                RPEDEBUG("Failed parsing delay time");
                talloc_free(yielded_at);
                return XLAT_ACTION_FAIL;
index 0d38e7e966ef3cf729512258be8788f9a0aab615..8ca98fe041b5fae7b84ffa8d3e04419cf75fd2dc 100644 (file)
@@ -61,11 +61,11 @@ typedef struct {
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t dhcpv4_decode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t dhcpv4_decode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                        request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                       fr_value_box_t **in)
+                                       fr_value_box_list_t *in)
 {
-       fr_cursor_t     in_cursor;
+       fr_dcursor_t    in_cursor;
        fr_value_box_t  *vb, *vb_decoded;
        fr_pair_t       *vp;
        fr_pair_list_t  head;
@@ -73,9 +73,9 @@ static xlat_action_t dhcpv4_decode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
 
        fr_pair_list_init(&head);
 
-       for (vb = fr_cursor_talloc_init(&in_cursor, in, fr_value_box_t);
+       for (vb = fr_dcursor_talloc_init(&in_cursor, in, fr_value_box_t);
             vb;
-            vb = fr_cursor_next(&in_cursor)) {
+            vb = fr_dcursor_next(&in_cursor)) {
                uint8_t const   *p, *end;
                ssize_t         len;
                fr_pair_list_t  vps;
@@ -126,7 +126,7 @@ static xlat_action_t dhcpv4_decode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        /* create a value box to hold the decoded count */
        MEM(vb_decoded = fr_value_box_alloc(ctx, FR_TYPE_UINT16, NULL, false));
        vb_decoded->vb_uint16 = decoded;
-       fr_cursor_append(out, vb_decoded);
+       fr_dcursor_append(out, vb_decoded);
 
        return XLAT_ACTION_DONE;
 }
@@ -142,9 +142,9 @@ static xlat_action_t dhcpv4_decode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t dhcpv4_encode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t dhcpv4_encode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                        request_t *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                       fr_value_box_t **in)
+                                       fr_value_box_list_t *in)
 {
        fr_dcursor_t    *cursor;
        bool            tainted = false;
@@ -153,15 +153,16 @@ static xlat_action_t dhcpv4_encode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        uint8_t         binbuf[2048];
        uint8_t         *p = binbuf, *end = p + sizeof(binbuf);
        ssize_t         len = 0;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
 
-       if (!*in) return XLAT_ACTION_DONE;
+       if (!in_head) return XLAT_ACTION_DONE;
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input string for attribute reference");
                return XLAT_ACTION_FAIL;
        }
 
-       if (xlat_fmt_to_cursor(NULL, &cursor, &tainted, request, (*in)->vb_strvalue) < 0) return XLAT_ACTION_FAIL;
+       if (xlat_fmt_to_cursor(NULL, &cursor, &tainted, request, in_head->vb_strvalue) < 0) return XLAT_ACTION_FAIL;
 
        if (!fr_dcursor_head(cursor)) return XLAT_ACTION_DONE;  /* Nothing to encode */
 
@@ -182,7 +183,7 @@ static xlat_action_t dhcpv4_encode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
         */
        MEM(encoded = fr_value_box_alloc_null(ctx));
        fr_value_box_memdup(encoded, encoded, NULL, binbuf, (size_t)len, tainted);
-       fr_cursor_append(out, encoded);
+       fr_dcursor_append(out, encoded);
 
        return XLAT_ACTION_DONE;
 }
index e00dccd9f04171d29cea37cb378c6a5f7bc634f7..c81e3a51e5fe291188792893de6a1681e83e0c6c 100644 (file)
@@ -260,7 +260,7 @@ static unlang_action_t mod_exec_nowait_resume(rlm_rcode_t *p_result, module_ctx_
                                              request_t *request, void *rctx)
 {
        rlm_exec_t const        *inst = talloc_get_type_abort_const(mctx->instance, rlm_exec_t);
-       fr_value_box_t          *box = talloc_get_type_abort(rctx, fr_value_box_t);
+       fr_value_box_list_t     *box = talloc_get_type_abort(rctx, fr_value_box_list_t);
        fr_pair_list_t          env_pairs;
 
        fr_pair_list_init(&env_pairs);
@@ -287,8 +287,8 @@ static unlang_action_t mod_exec_nowait_resume(rlm_rcode_t *p_result, module_ctx_
 }
 
 typedef struct {
-       fr_value_box_t  *box;
-       int             status;
+       fr_value_box_list_t     box;
+       int                     status;
 } rlm_exec_ctx_t;
 
 static const rlm_rcode_t status2rcode[] = {
@@ -356,11 +356,12 @@ static unlang_action_t mod_exec_wait_resume(rlm_rcode_t *p_result, module_ctx_t
        rlm_exec_ctx_t          *m = talloc_get_type_abort(rctx, rlm_exec_ctx_t);
        rlm_exec_t const        *inst = talloc_get_type_abort_const(mctx->instance, rlm_exec_t);
 
-       if (inst->output && m->box) {
+       if (inst->output && !fr_dlist_empty(&m->box)) {
                TALLOC_CTX *ctx;
                fr_pair_list_t vps, *output_pairs;
+               fr_value_box_t *box = fr_dlist_head(&m->box);
 
-               RDEBUG("EXEC GOT -- %pV", m->box);
+               RDEBUG("EXEC GOT -- %pV", box);
 
                fr_pair_list_init(&vps);
                output_pairs = tmpl_list_head(request, inst->output_list);
@@ -368,10 +369,10 @@ static unlang_action_t mod_exec_wait_resume(rlm_rcode_t *p_result, module_ctx_t
 
                ctx = tmpl_list_ctx(request, inst->output_list);
 
-               fr_pair_list_afrom_box(ctx, &vps, request->dict, m->box);
+               fr_pair_list_afrom_box(ctx, &vps, request->dict, box);
                if (!fr_pair_list_empty(&vps)) fr_pair_list_move(output_pairs, &vps);
 
-               m->box = NULL;  /* has been consumed */
+               fr_dlist_talloc_free(&m->box);  /* has been consumed */
        }
 
        status = m->status;
@@ -385,7 +386,7 @@ static unlang_action_t mod_exec_wait_resume(rlm_rcode_t *p_result, module_ctx_t
         *      The status rcodes aren't quite the same as the rcode
         *      enumeration.
         */
-       RETURN_MODULE_RCODE(rlm_exec_status2rcode(request, m->box, status));
+       RETURN_MODULE_RCODE(rlm_exec_status2rcode(request, fr_dlist_head(&m->box), status));
 }
 
 /*
@@ -413,11 +414,11 @@ static unlang_action_t CC_HINT(nonnull) mod_exec_dispatch(rlm_rcode_t *p_result,
         *      Do the asynchronous xlat expansion.
         */
        if (!inst->wait) {
-               fr_value_box_t *box;
+               fr_value_box_list_t *box = talloc_zero(ctx, fr_value_box_list_t);
 
-               MEM(box = talloc_zero(ctx, fr_value_box_t));
+               fr_value_box_list_init(box);
 
-               return unlang_module_yield_to_xlat(request, &box, request, tmpl_xlat(inst->tmpl), mod_exec_nowait_resume, NULL, box);
+               return unlang_module_yield_to_xlat(request, box, request, tmpl_xlat(inst->tmpl), mod_exec_nowait_resume, NULL, &box);
        }
 
        /*
@@ -439,6 +440,7 @@ static unlang_action_t CC_HINT(nonnull) mod_exec_dispatch(rlm_rcode_t *p_result,
        }
 
        m = talloc_zero(ctx, rlm_exec_ctx_t);
+       fr_value_box_list_init(&m->box);
 
        return unlang_module_yield_to_tmpl(m, &m->box, &m->status, request, inst->tmpl, &env_pairs, mod_exec_wait_resume, NULL, m);
 }
index 227964086b87a3ead1a30e40e1bcb252a41127d2..4753849ab4562874ac8eb7b075201c5e24bf7092 100644 (file)
@@ -123,10 +123,10 @@ static const CONF_PARSER module_config[] = {
        CONF_PARSER_TERMINATOR
 };
 
-static xlat_action_t xlat_icmp_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t xlat_icmp_resume(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                      UNUSED request_t *request,
                                      UNUSED void const *xlat_inst, void *xlat_thread_inst,
-                                     UNUSED fr_value_box_t **in, void *rctx)
+                                     UNUSED fr_value_box_list_t *in, void *rctx)
 {
        rlm_icmp_echo_t *echo = talloc_get_type_abort(rctx, rlm_icmp_echo_t);
        xlat_icmp_thread_inst_t *thread = talloc_get_type_abort(xlat_thread_inst, xlat_icmp_thread_inst_t);
@@ -138,7 +138,7 @@ static xlat_action_t xlat_icmp_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
        (void) rbtree_deletebydata(thread->t->tree, echo);
        talloc_free(echo);
 
-       fr_cursor_insert(out, vb);
+       fr_dcursor_insert(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -179,9 +179,9 @@ static void _xlat_icmp_timeout(request_t *request,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t xlat_icmp(TALLOC_CTX *ctx, UNUSED fr_cursor_t *out,
+static xlat_action_t xlat_icmp(TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
                               request_t *request, void const *xlat_inst, void *xlat_thread_inst,
-                              fr_value_box_t **in)
+                              fr_value_box_list_t *in)
 {
        void                    *instance;
        rlm_icmp_t const        *inst;
@@ -192,6 +192,7 @@ static xlat_action_t xlat_icmp(TALLOC_CTX *ctx, UNUSED fr_cursor_t *out,
        ssize_t                 rcode;
        socklen_t               salen;
        struct sockaddr_storage dst;
+       fr_value_box_t          *in_head = fr_dlist_head(in);
 
        memcpy(&instance, xlat_inst, sizeof(instance)); /* Stupid const issues */
 
@@ -200,20 +201,20 @@ static xlat_action_t xlat_icmp(TALLOC_CTX *ctx, UNUSED fr_cursor_t *out,
        /*
         *      If there's no input, do we can't ping anything.
         */
-       if (!*in) return XLAT_ACTION_FAIL;
+       if (!in_head) return XLAT_ACTION_FAIL;
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_cast_in_place(ctx, *in, thread->t->ipaddr_type, NULL) < 0) {
+       if (fr_value_box_cast_in_place(ctx, in_head, thread->t->ipaddr_type, NULL) < 0) {
                RPEDEBUG("Failed casting result to IP address");
                return XLAT_ACTION_FAIL;
        }
 
        MEM(echo = talloc_zero(ctx, rlm_icmp_echo_t));
-       echo->ip = *in;
+       echo->ip = in_head;
        echo->request = request;
        echo->counter = thread->t->counter++;
 
index 6b99be6ef1ac285b33cbfb1dca4854ea00ca76d0..8d925251fe0c25f69e720406c584c1fa2fe91112 100644 (file)
@@ -102,30 +102,31 @@ typedef struct {
  * @param in list of value boxes as input
  * @return XLAT_ACTION_DONE or XLAT_ACTION_FAIL
  */
-static xlat_action_t json_quote_xlat(TALLOC_CTX *ctx, fr_cursor_t *out, request_t *request,
+static xlat_action_t json_quote_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
                                     UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                    fr_value_box_t **in)
+                                    fr_value_box_list_t *in)
 {
        fr_value_box_t *vb;
+       fr_value_box_t *in_head = fr_dlist_head(in);
        char *tmp;
 
-       if (!*in) return XLAT_ACTION_DONE;
+       if (!in_head) return XLAT_ACTION_DONE;
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
        MEM(vb = fr_value_box_alloc_null(ctx));
 
-       if (!(tmp = fr_json_from_string(vb, (*in)->vb_strvalue, false))) {
+       if (!(tmp = fr_json_from_string(vb, in_head->vb_strvalue, false))) {
                REDEBUG("Unable to JSON-quote string");
                talloc_free(vb);
                return XLAT_ACTION_FAIL;
        }
        fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, tmp, false);
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -180,9 +181,9 @@ static ssize_t jpath_validate_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t ou
  * @param in list of value boxes as input
  * @return XLAT_ACTION_DONE or XLAT_ACTION_FAIL
  */
-static xlat_action_t json_encode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out, request_t *request,
+static xlat_action_t json_encode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
                                      void const *xlat_inst, UNUSED void *xlat_thread_inst,
-                                     fr_value_box_t **in)
+                                     fr_value_box_list_t *in)
 {
        rlm_json_t const        *inst = talloc_get_type_abort_const(*((void const * const *)xlat_inst),
                                                                    rlm_json_t);
@@ -195,20 +196,21 @@ static xlat_action_t json_encode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out, request
        char                    *json_str = NULL;
        fr_value_box_t          *vb;
        fr_sbuff_t              sbuff;
+       fr_value_box_t          *in_head = fr_dlist_head(in);
 
        fr_pair_list_init(&json_vps);
        fr_pair_list_init(&vps);
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("Missing attribute(s)");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       sbuff = FR_SBUFF_IN((*in)->vb_strvalue, (*in)->vb_length);
+       sbuff = FR_SBUFF_IN(in_head->vb_strvalue, in_head->vb_length);
        fr_sbuff_adv_past_whitespace(&sbuff, SIZE_MAX, NULL);
 
        /*
@@ -289,7 +291,7 @@ static xlat_action_t json_encode_xlat(TALLOC_CTX *ctx, fr_cursor_t *out, request
        }
        fr_value_box_bstrdup_buffer_shallow(NULL, vb, NULL, json_str, false);
 
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
        fr_pair_list_free(&json_vps);
 
        return XLAT_ACTION_DONE;
@@ -397,10 +399,12 @@ static int _json_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, reques
 {
        fr_pair_t                       *vp;
        rlm_json_jpath_to_eval_t        *to_eval = uctx;
-       fr_value_box_t                  *head, *value;
+       fr_value_box_t                  *value;
+       fr_value_box_list_t             head;
        int                             ret;
 
        fr_pair_list_free(out);
+       fr_value_box_list_init(&head);
 
        ret = fr_jpath_evaluate_leaf(request, &head, tmpl_da(map->lhs)->type, tmpl_da(map->lhs),
                                     to_eval->root, to_eval->jpath);
@@ -409,11 +413,11 @@ static int _json_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, reques
                return -1;
        }
        if (ret == 0) return 0;
-       fr_assert(head);
+       fr_assert(!fr_dlist_empty(&head));
 
-       for (value = head;
+       for (value = fr_dlist_head(&head);
             value;
-            fr_pair_add(out, vp), value = value->next) {
+            fr_pair_add(out, vp), value = fr_dlist_next(&head, value)) {
                MEM(vp = fr_pair_afrom_da(ctx, tmpl_da(map->lhs)));
                vp->op = map->op;
 
@@ -441,7 +445,7 @@ static int _json_map_proc_get_value(TALLOC_CTX *ctx, fr_pair_list_t *out, reques
  *     - #RLM_MODULE_FAIL if a fault occurred.
  */
 static rlm_rcode_t mod_map_proc(UNUSED void *mod_inst, void *proc_inst, request_t *request,
-                               fr_value_box_t **json, fr_map_list_t const *maps)
+                               fr_value_box_list_t *json, fr_map_list_t const *maps)
 {
        rlm_rcode_t                     rcode = RLM_MODULE_UPDATED;
        struct json_tokener             *tok;
@@ -452,17 +456,18 @@ static rlm_rcode_t mod_map_proc(UNUSED void *mod_inst, void *proc_inst, request_
        rlm_json_jpath_to_eval_t        to_eval;
 
        char const                      *json_str = NULL;
+       fr_value_box_t                  *json_head = fr_dlist_head(json);
 
-       if (!*json) {
+       if (!json_head) {
                REDEBUG("JSON map input cannot be (null)");
                return RLM_MODULE_FAIL;
        }
 
-       if (fr_value_box_list_concat(request, *json, json, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(request, json_head, json, FR_TYPE_STRING, true) < 0) {
                REDEBUG("Failed concatenating input");
                return RLM_MODULE_FAIL;
        }
-       json_str = (*json)->vb_strvalue;
+       json_str = json_head->vb_strvalue;
 
        if ((talloc_array_length(json_str) - 1) == 0) {
                REDEBUG("JSON map input length must be > 0");
index a25c31eaa99830bac267a0390acd4a3383b667ea..113538217aff34e64fc4ea8ce644c3516713b3ec 100644 (file)
@@ -425,7 +425,7 @@ static int ldap_map_verify(CONF_SECTION *cs, UNUSED void *mod_inst, UNUSED void
  *     - #RLM_MODULE_FAIL if an error occurred.
  */
 static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_t *request,
-                               fr_value_box_t **url, fr_map_list_t const *maps)
+                               fr_value_box_list_t *url, fr_map_list_t const *maps)
 {
        rlm_rcode_t             rcode = RLM_MODULE_UPDATED;
        rlm_ldap_t              *inst = talloc_get_type_abort(mod_inst, rlm_ldap_t);
@@ -443,20 +443,21 @@ static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_
        LDAPControl             *server_ctrls[] = { NULL, NULL };
 
        fr_ldap_map_exp_t       expanded; /* faster than allocing every time */
+       fr_value_box_t          *url_head = fr_dlist_head(url);
 
        /*
         *      FIXME - Maybe it can be NULL?
         */
-       if (!*url) {
+       if (!url_head) {
                REDEBUG("LDAP URL cannot be (null)");
                return RLM_MODULE_FAIL;
        }
 
-       if (fr_value_box_list_concat(request, *url, url, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(request, url_head, url, FR_TYPE_STRING, true) < 0) {
                REDEBUG("Failed concatenating input");
                return RLM_MODULE_FAIL;
        }
-       url_str = (*url)->vb_strvalue;
+       url_str = url_head->vb_strvalue;
 
        if (!ldap_is_ldap_url(url_str)) {
                REDEBUG("Map query string does not look like a valid LDAP URI");
index e86255ffbec726171937d9d3ce3505d0996703f6..6a87f674111443ca190255b93b2b7f3ad0f0e26f 100644 (file)
@@ -156,10 +156,10 @@ static int redis_xlat_instantiate(void *xlat_inst, UNUSED xlat_exp_t const *exp,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t redis_remap_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t redis_remap_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                      request_t *request, void const *xlat_inst,
                                      UNUSED void *xlat_thread_inst,
-                                     fr_value_box_t **in)
+                                     fr_value_box_list_t *in)
 {
        rlm_redis_t const               *inst = talloc_get_type_abort_const(*((void const * const *)xlat_inst),
                                                                            rlm_redis_t);
@@ -169,18 +169,19 @@ static xlat_action_t redis_remap_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        fr_redis_conn_t                 *conn;
        fr_redis_cluster_rcode_t        rcode;
        fr_value_box_t                  *vb;
+       fr_value_box_t                  *in_head = fr_dlist_head(in);
 
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("Missing key");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_inet_pton_port(&node_addr.inet.dst_ipaddr, &node_addr.inet.dst_port, (*in)->vb_strvalue, (*in)->vb_length,
+       if (fr_inet_pton_port(&node_addr.inet.dst_ipaddr, &node_addr.inet.dst_port, in_head->vb_strvalue, in_head->vb_length,
                              AF_UNSPEC, true, true) < 0) {
                RPEDEBUG("Failed parsing node address");
                return XLAT_ACTION_FAIL;
@@ -202,7 +203,7 @@ static xlat_action_t redis_remap_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
 
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_strdup(vb, vb, NULL, fr_table_str_by_value(fr_redis_cluster_rcodes_table, rcode, "<INVALID>"), false);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
@@ -211,10 +212,10 @@ static xlat_action_t redis_remap_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t redis_node_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t redis_node_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                     request_t *request, void const *xlat_inst,
                                     UNUSED void *xlat_thread_inst,
-                                    fr_value_box_t **in)
+                                    fr_value_box_list_t *in)
 {
        rlm_redis_t const                       *inst = talloc_get_type_abort_const(*((void const * const *)xlat_inst),
                                                                                    rlm_redis_t);
@@ -230,18 +231,19 @@ static xlat_action_t redis_node_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
        size_t                                  key_len;
        unsigned long                           idx = 0;
        fr_value_box_t                          *vb;
+       fr_value_box_t                          *in_head = fr_dlist_head(in);
 
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("Missing key");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input");
                return XLAT_ACTION_FAIL;
        }
 
-       key = p = (*in)->vb_strvalue;
+       key = p = in_head->vb_strvalue;
        p = strchr(p, ' ');             /* Look for index */
        if (p) {
                key_len = p - key;
@@ -252,7 +254,7 @@ static xlat_action_t redis_node_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
                        return XLAT_ACTION_FAIL;
                }
        } else {
-               key_len = (*in)->vb_length;
+               key_len = in_head->vb_length;
        }
 
        key_slot = fr_redis_cluster_slot_by_key(inst->cluster, request, (uint8_t const *)key, key_len);
@@ -274,7 +276,7 @@ static xlat_action_t redis_node_xlat(TALLOC_CTX *ctx, fr_cursor_t *out,
 
        MEM(vb = fr_value_box_alloc_null(ctx));
        fr_value_box_asprintf(vb, vb, NULL, false, "%pV:%u", fr_box_ipaddr(ipaddr), port);
-       fr_cursor_append(out, vb);
+       fr_dcursor_append(out, vb);
 
        return XLAT_ACTION_DONE;
 }
index b356bcf00f51111a6081e386e09d383c93cee06a..e960b7271cd4b9362be4e9ce05a65c864f69e3fc 100644 (file)
@@ -219,9 +219,9 @@ static int rlm_rest_perform(rlm_rest_t const *instance, rlm_rest_thread_t *t,
        return 0;
 }
 
-static xlat_action_t rest_xlat_resume(TALLOC_CTX *ctx, fr_cursor_t *out,
+static xlat_action_t rest_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out,
                                      request_t *request, UNUSED void const *xlat_inst, void *xlat_thread_inst,
-                                     UNUSED fr_value_box_t **in, void *rctx)
+                                     UNUSED fr_value_box_list_t *in, void *rctx)
 {
        rest_xlat_thread_inst_t         *xti = talloc_get_type_abort(xlat_thread_inst, rest_xlat_thread_inst_t);
        rlm_rest_t const                *mod_inst = xti->inst;
@@ -279,7 +279,7 @@ error:
 
                MEM(vb = fr_value_box_alloc_null(ctx));
                fr_value_box_bstrndup(vb, vb, NULL, body, len, true);
-               fr_cursor_insert(out, vb);
+               fr_dcursor_insert(out, vb);
        }
 
 finish:
@@ -301,9 +301,9 @@ finish:
  *
  * @ingroup xlat_functions
  */
-static xlat_action_t rest_xlat(TALLOC_CTX *ctx, UNUSED fr_cursor_t *out,
+static xlat_action_t rest_xlat(TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
                               request_t *request, UNUSED void const *xlat_inst, void *xlat_thread_inst,
-                              fr_value_box_t **in)
+                              fr_value_box_list_t *in)
 {
        rest_xlat_thread_inst_t         *xti = talloc_get_type_abort(xlat_thread_inst, rest_xlat_thread_inst_t);
        rlm_rest_t const                *mod_inst = xti->inst;
@@ -315,21 +315,22 @@ static xlat_action_t rest_xlat(TALLOC_CTX *ctx, UNUSED fr_cursor_t *out,
        char                            *uri = NULL;
        char const                      *p = NULL, *q;
        http_method_t                   method;
+       fr_value_box_t                  *in_head = fr_dlist_head(in);
 
        /* There are no configurable parameters other than the URI */
        rlm_rest_xlat_rctx_t            *rctx;
        rlm_rest_section_t              *section;
 
-       if (!*in) {
+       if (!in_head) {
                REDEBUG("Got empty URL string");
                return XLAT_ACTION_FAIL;
        }
 
-       if (fr_value_box_list_concat(ctx, *in, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
                REDEBUG("Failed concatenating arguments into URL string");
                return XLAT_ACTION_FAIL;
        }
-       p = (*in)->vb_strvalue;
+       p = in_head->vb_strvalue;
 
        MEM(rctx = talloc(request, rlm_rest_xlat_rctx_t));
        section = &rctx->section;
index c03341e23d57d0231c46a9c4a689f06b9a20fe44..481c4d22da2b372370e9941f2c708083fd0bab1c 100644 (file)
@@ -330,7 +330,7 @@ static int sql_map_verify(CONF_SECTION *cs, UNUSED void *mod_inst, UNUSED void *
  *     - #RLM_MODULE_FAIL if a fault occurred.
  */
 static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_t *request,
-                               fr_value_box_t **query, fr_map_list_t const *maps)
+                               fr_value_box_list_t *query, fr_map_list_t const *maps)
 {
        rlm_sql_t               *inst = talloc_get_type_abort(mod_inst, rlm_sql_t);
        rlm_sql_handle_t        *handle = NULL;
@@ -350,6 +350,7 @@ static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_
        char                    map_rhs_buff[128];
 
        char const              *query_str = NULL;
+       fr_value_box_t          *query_head = fr_dlist_head(query);
 
 #define MAX_SQL_FIELD_INDEX (64)
 
@@ -358,16 +359,16 @@ static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_
 
        fr_assert(inst->driver->sql_fields);            /* Should have been caught during validation... */
 
-       if (!*query) {
+       if (!query_head) {
                REDEBUG("Query cannot be (null)");
                return RLM_MODULE_FAIL;
        }
 
-       if (fr_value_box_list_concat(request, *query, query, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat(request, query_head, query, FR_TYPE_STRING, true) < 0) {
                RPEDEBUG("Failed concatenating input string");
                return RLM_MODULE_FAIL;
        }
-       query_str = (*query)->vb_strvalue;
+       query_str = query_head->vb_strvalue;
 
        for (i = 0; i < MAX_SQL_FIELD_INDEX; i++) field_index[i] = -1;