]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Split tmpl rules
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 19 Jan 2022 15:20:01 +0000 (10:20 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 19 Jan 2022 15:35:01 +0000 (10:35 -0500)
37 files changed:
src/bin/unit_test_attribute.c
src/bin/unit_test_map.c
src/lib/io/master.c
src/lib/ldap/map.c
src/lib/redis/redis.c
src/lib/server/cf_file.c
src/lib/server/cf_parse.c
src/lib/server/cond_eval.c
src/lib/server/cond_tokenize.c
src/lib/server/map.c
src/lib/server/map_async.c
src/lib/server/tmpl.h
src/lib/server/tmpl_dcursor.c
src/lib/server/tmpl_eval.c
src/lib/server/tmpl_tokenize.c
src/lib/server/users_file.c
src/lib/server/virtual_servers.c
src/lib/unlang/compile.c
src/lib/unlang/edit.c
src/lib/unlang/xlat.h
src/lib/unlang/xlat_builtin.c
src/lib/unlang/xlat_eval.c
src/lib/unlang/xlat_expr.c
src/lib/unlang/xlat_priv.h
src/lib/unlang/xlat_tokenize.c
src/modules/rlm_cache/rlm_cache.c
src/modules/rlm_cache/serialize.c
src/modules/rlm_csv/rlm_csv.c
src/modules/rlm_exec/rlm_exec.c
src/modules/rlm_expr/rlm_expr.c
src/modules/rlm_json/rlm_json.c
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_linelog/rlm_linelog.c
src/modules/rlm_python/rlm_python.c
src/modules/rlm_radius/rlm_radius.c
src/modules/rlm_rest/rest.c
src/modules/rlm_smtp/rlm_smtp.c

index c05e736c1bc9331b5fb0efb6f2e4e798f077fee7..4ce1ed3050a833bd498ded03141278a00801a6c4 100644 (file)
@@ -956,8 +956,8 @@ static int dictionary_load_common(command_result_t *result, command_file_ctx_t *
        /*
         *      Decrease ref count if we're loading in a new dictionary
         */
-       if (cc->tmpl_rules.dict_def) {
-               if (fr_dict_const_free(&cc->tmpl_rules.dict_def, __FILE__) < 0) return -1;
+       if (cc->tmpl_rules.attr.dict_def) {
+               if (fr_dict_const_free(&cc->tmpl_rules.attr.dict_def, __FILE__) < 0) return -1;
        }
 
        q = strchr(in, ' ');
@@ -974,12 +974,12 @@ static int dictionary_load_common(command_result_t *result, command_file_ctx_t *
        talloc_free(tmp);
        if (ret < 0) RETURN_COMMAND_ERROR();
 
-       cc->tmpl_rules.dict_def = dict;
+       cc->tmpl_rules.attr.dict_def = dict;
 
        /*
         *      Dump the dictionary if we're in super debug mode
         */
-       if (fr_debug_lvl > 5) fr_dict_debug(cc->tmpl_rules.dict_def);
+       if (fr_debug_lvl > 5) fr_dict_debug(cc->tmpl_rules.attr.dict_def);
 
        RETURN_OK(0);
 }
@@ -1133,7 +1133,7 @@ static size_t command_allow_unresolved(command_result_t *result, command_file_ct
 {
        fr_sbuff_t      our_in = FR_SBUFF_IN(in, inlen);
 
-       if (fr_sbuff_out_bool(&cc->tmpl_rules.allow_unresolved, &our_in) == 0) {
+       if (fr_sbuff_out_bool(&cc->tmpl_rules.attr.allow_unresolved, &our_in) == 0) {
                fr_strerror_printf("Invalid boolean value, must be \"yes\" or \"no\"");
                RETURN_COMMAND_ERROR();
        }
@@ -1149,7 +1149,7 @@ static size_t command_normalise_attribute(command_result_t *result, command_file
 {
        fr_pair_list_t  head;
        ssize_t         slen;
-       fr_dict_t const *dict = cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict;
+       fr_dict_t const *dict = cc->tmpl_rules.attr.dict_def ? cc->tmpl_rules.attr.dict_def : cc->config->dict;
 
        fr_pair_list_init(&head);
 
@@ -1516,7 +1516,7 @@ static size_t command_decode_pair(command_result_t *result, command_file_ctx_t *
         *      point to produce fr_pair_ts.
         */
        while (to_dec < to_dec_end) {
-               slen = tp->func(cc->tmp_ctx, &head, fr_dict_root(cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict),
+               slen = tp->func(cc->tmp_ctx, &head, fr_dict_root(cc->tmpl_rules.attr.dict_def ? cc->tmpl_rules.attr.dict_def : cc->config->dict),
                                (uint8_t *)to_dec, (to_dec_end - to_dec), decode_ctx);
                cc->last_ret = slen;
                if (slen <= 0) {
@@ -1693,7 +1693,7 @@ static size_t command_dictionary_attribute_parse(command_result_t *result, comma
 static size_t command_dictionary_dump(command_result_t *result, command_file_ctx_t *cc,
                                      UNUSED char *data, size_t data_used, UNUSED char *in, UNUSED size_t inlen)
 {
-       fr_dict_debug(cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict);
+       fr_dict_debug(cc->tmpl_rules.attr.dict_def ? cc->tmpl_rules.attr.dict_def : cc->config->dict);
 
        /*
         *      Don't modify the contents of the data buffer
@@ -1851,7 +1851,7 @@ static size_t command_encode_pair(command_result_t *result, command_file_ctx_t *
                RETURN_COMMAND_ERROR();
        }
 
-       dict = cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict;
+       dict = cc->tmpl_rules.attr.dict_def ? cc->tmpl_rules.attr.dict_def : cc->config->dict;
        if (fr_pair_list_afrom_str(cc->tmp_ctx, fr_dict_root(dict),
                                   p, in + inlen - p, &head) != T_EOL) {
                CLEAR_TEST_POINT(cc);
@@ -1884,7 +1884,7 @@ static size_t command_encode_pair(command_result_t *result, command_file_ctx_t *
 
                for (vp = fr_pair_dcursor_iter_init(&cursor, &head,
                                                    tp->next_encodable ? tp->next_encodable : fr_proto_next_encodable,
-                                                   cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict);
+                                                   cc->tmpl_rules.attr.dict_def ? cc->tmpl_rules.attr.dict_def : cc->config->dict);
                     vp;
                     vp = fr_dcursor_current(&cursor)) {
                        slen = tp->func(&FR_DBUFF_TMP(enc_p, enc_end), &cursor, encode_ctx);
@@ -2010,7 +2010,7 @@ static size_t command_encode_proto(command_result_t *result, command_file_ctx_t
                RETURN_COMMAND_ERROR();
        }
 
-       dict = cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict;
+       dict = cc->tmpl_rules.attr.dict_def ? cc->tmpl_rules.attr.dict_def : cc->config->dict;
        if (fr_pair_list_afrom_str(cc->tmp_ctx, fr_dict_root(dict),
                                   p, in + inlen - p, &head) != T_EOL) {
                CLEAR_TEST_POINT(cc);
@@ -2141,7 +2141,7 @@ static size_t command_load_dictionary(command_result_t *result, command_file_ctx
                dir = cc->path;
        }
 
-       ret = fr_dict_read(UNCONST(fr_dict_t *, cc->tmpl_rules.dict_def), dir, name);
+       ret = fr_dict_read(UNCONST(fr_dict_t *, cc->tmpl_rules.attr.dict_def), dir, name);
        talloc_free(tmp);
        if (ret < 0) RETURN_COMMAND_ERROR();
 
@@ -2295,7 +2295,7 @@ static size_t command_pair(command_result_t *result, command_file_ctx_t *cc,
 
        fr_pair_list_init(&head);
        ctx.ctx = cc->tmp_ctx;
-       ctx.parent = fr_dict_root(cc->tmpl_rules.dict_def);
+       ctx.parent = fr_dict_root(cc->tmpl_rules.attr.dict_def);
        ctx.list = &head;
 
        p = in;
@@ -2384,45 +2384,45 @@ typedef ssize_t(*command_tmpl_rule_func)(tmpl_rules_t *rules, fr_sbuff_t *value)
 
 static ssize_t command_tmpl_rule_allow_foreign(tmpl_rules_t *rules, fr_sbuff_t *value)
 {
-       return fr_sbuff_out_bool(&rules->allow_foreign, value);
+       return fr_sbuff_out_bool(&rules->attr.allow_foreign, value);
 }
 
 static ssize_t command_tmpl_rule_allow_unknown(tmpl_rules_t *rules, fr_sbuff_t *value)
 {
-       return fr_sbuff_out_bool(&rules->allow_unknown, value);
+       return fr_sbuff_out_bool(&rules->attr.allow_unknown, value);
 }
 
 static ssize_t command_tmpl_rule_allow_unresolved(tmpl_rules_t *rules, fr_sbuff_t *value)
 {
-       return fr_sbuff_out_bool(&rules->allow_unresolved, value);
+       return fr_sbuff_out_bool(&rules->attr.allow_unresolved, value);
 }
 
 static ssize_t command_tmpl_rule_attr_parent(tmpl_rules_t *rules, fr_sbuff_t *value)
 {
        return fr_dict_attr_by_oid_substr(NULL,
-                                         &rules->attr_parent,
-                                         rules->dict_def ? fr_dict_root(rules->dict_def) :
-                                                           fr_dict_root(fr_dict_internal()),
+                                         &rules->attr.parent,
+                                         rules->attr.dict_def ? fr_dict_root(rules->attr.dict_def) :
+                                                                fr_dict_root(fr_dict_internal()),
                                          value, NULL);
 }
 
 static ssize_t command_tmpl_rule_disallow_internal(tmpl_rules_t *rules, fr_sbuff_t *value)
 {
-       return fr_sbuff_out_bool(&rules->disallow_internal, value);
+       return fr_sbuff_out_bool(&rules->attr.disallow_internal, value);
 }
 
 static ssize_t command_tmpl_rule_disallow_qualifiers(tmpl_rules_t *rules, fr_sbuff_t *value)
 {
-       return fr_sbuff_out_bool(&rules->disallow_qualifiers, value);
+       return fr_sbuff_out_bool(&rules->attr.disallow_qualifiers, value);
 }
 
 static ssize_t command_tmpl_rule_list_def(tmpl_rules_t *rules, fr_sbuff_t *value)
 {
        ssize_t slen;
 
-       fr_sbuff_out_by_longest_prefix(&slen, &rules->list_def, pair_list_table, value, PAIR_LIST_UNKNOWN);
+       fr_sbuff_out_by_longest_prefix(&slen, &rules->attr.list_def, pair_list_table, value, PAIR_LIST_UNKNOWN);
 
-       if (rules->list_def == PAIR_LIST_UNKNOWN) {
+       if (rules->attr.list_def == PAIR_LIST_UNKNOWN) {
                fr_strerror_printf("Invalid list specifier \"%pV\"",
                                   fr_box_strvalue_len(fr_sbuff_current(value), fr_sbuff_remaining(value)));
        }
@@ -2434,9 +2434,9 @@ static ssize_t command_tmpl_rule_request_def(tmpl_rules_t *rules, fr_sbuff_t *va
 {
        ssize_t slen;
 
-       fr_sbuff_out_by_longest_prefix(&slen, &rules->request_def, tmpl_request_ref_table, value, REQUEST_UNKNOWN);
+       fr_sbuff_out_by_longest_prefix(&slen, &rules->attr.request_def, tmpl_request_ref_table, value, REQUEST_UNKNOWN);
 
-       if (rules->request_def == REQUEST_UNKNOWN) {
+       if (rules->attr.request_def == REQUEST_UNKNOWN) {
                fr_strerror_printf("Invalid request specifier \"%pV\"",
                                   fr_box_strvalue_len(fr_sbuff_current(value), fr_sbuff_remaining(value)));
        }
@@ -2610,9 +2610,10 @@ static size_t command_xlat_normalise(command_result_t *result, command_file_ctx_
        fr_sbuff_parse_rules_t  p_rules = { .escapes = &fr_value_unescape_double };
 
        dec_len = xlat_tokenize(cc->tmp_ctx, &head, NULL, &FR_SBUFF_IN(in, input_len), &p_rules,
-                               &(tmpl_rules_t) {
-                                       .dict_def = cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict,
-                                       .allow_unresolved = cc->tmpl_rules.allow_unresolved
+                               &(tmpl_attr_rules_t) {
+                                       .dict_def = cc->tmpl_rules.attr.dict_def ?
+                                               cc->tmpl_rules.attr.dict_def : cc->config->dict,
+                                       .allow_unresolved = cc->tmpl_rules.attr.allow_unresolved
                                });
        if (dec_len <= 0) {
                fr_strerror_printf_push_head("ERROR offset %d", (int) -dec_len);
@@ -2642,9 +2643,10 @@ static size_t command_xlat_expr(command_result_t *result, command_file_ctx_t *cc
 //     fr_sbuff_parse_rules_t  p_rules = { .escapes = &fr_value_unescape_double };
 
        dec_len = xlat_tokenize_expression(cc->tmp_ctx, &head, NULL, &FR_SBUFF_IN(in, input_len), NULL,
-                                          &(tmpl_rules_t) {
-                                                  .dict_def = cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict,
-                                                          .allow_unresolved = cc->tmpl_rules.allow_unresolved
+                                          &(tmpl_attr_rules_t) {
+                                               .dict_def = cc->tmpl_rules.attr.dict_def ?
+                                                       cc->tmpl_rules.attr.dict_def : cc->config->dict,
+                                               .allow_unresolved = cc->tmpl_rules.attr.allow_unresolved
                                           });
        if (dec_len <= 0) {
                fr_strerror_printf_push_head("ERROR offset %d", (int) -dec_len);
@@ -2679,9 +2681,10 @@ static size_t command_xlat_argv(command_result_t *result, command_file_ctx_t *cc
 
        slen = xlat_tokenize_argv(cc->tmp_ctx, &head, NULL, &FR_SBUFF_IN(in, input_len),
                                  NULL,
-                                 &(tmpl_rules_t) {
-                                       .dict_def = cc->tmpl_rules.dict_def ? cc->tmpl_rules.dict_def : cc->config->dict,
-                                       .allow_unresolved = cc->tmpl_rules.allow_unresolved
+                                 &(tmpl_attr_rules_t) {
+                                       .dict_def = cc->tmpl_rules.attr.dict_def ?
+                                               cc->tmpl_rules.attr.dict_def : cc->config->dict,
+                                       .allow_unresolved = cc->tmpl_rules.attr.allow_unresolved
                                  });
        if (slen <= 0) {
                fr_strerror_printf_push_head("ERROR offset %d", (int) -slen);
@@ -3218,7 +3221,7 @@ finish:
        /*
         *      Free any residual resources we loaded.
         */
-       if (cc && (fr_dict_const_free(&cc->tmpl_rules.dict_def, __FILE__) < 0)) {
+       if (cc && (fr_dict_const_free(&cc->tmpl_rules.attr.dict_def, __FILE__) < 0)) {
                fr_perror("unit_test_attribute");
                ret = -1;
        }
index 92a3f18d9d54ca7312886ddd1c1a101ce694ec7c..82df15ec0b4077af9f7069b98df4f60f64cab99d 100644 (file)
@@ -82,8 +82,10 @@ static int process_file(char const *filename)
        main_config_t   *config;
 
        tmpl_rules_t    parse_rules = {
-               .dict_def = dict_radius,
-               .allow_foreign = false, /* tests are in the RADIUS dictionary */
+               .attr = {
+                       .dict_def = dict_radius,
+                       .allow_foreign = false, /* tests are in the RADIUS dictionary */
+               }
        };
 
        map_list_init(&list);
index 8a2238dccf19eb3d0bc483738f5a7e4ef62c93fa..a92848cab401b6277594dd459ec82a51ade06de7 100644 (file)
@@ -2669,15 +2669,16 @@ static int mod_instantiate(void *instance, CONF_SECTION *conf)
                 *      Maybe we should?
                 */
                if (app_process->compile_list) {
-                       tmpl_rules_t            parse_rules;
-
-                       memset(&parse_rules, 0, sizeof(parse_rules));
-                       parse_rules.dict_def = virtual_server_namespace(cf_section_name2(inst->server_cs));
+                       tmpl_rules_t    parse_rules = {
+                               .attr = {
+                                       .dict_def = virtual_server_namespace(cf_section_name2(inst->server_cs))
+                               }
+                       };
 
                        if (virtual_server_compile_sections(inst->server_cs, app_process->compile_list,
                                                            &parse_rules, inst->dynamic_submodule->data) < 0) {
                                return -1;
-                       }
+                       };
                }
 
                if (app_process->instantiate && (app_process->instantiate(inst->dynamic_submodule->data, conf) < 0)) {
index c5a8faee229ef5652a09f652ab9f88a0f6b93703..1938bb5fe3da113a65bf1ef40e4f9d20d3c009b2 100644 (file)
@@ -65,15 +65,19 @@ int fr_ldap_map_getvalue(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *reques
                        char            *attr_str;
 
                        tmpl_rules_t    lhs_rules = {
-                               .dict_def = request->dict,
-                               .request_def = tmpl_request(map->lhs),
-                               .list_def = tmpl_list(map->lhs),
-                               .prefix = TMPL_ATTR_REF_PREFIX_AUTO,
+                               .attr = {
+                                       .dict_def = request->dict,
+                                       .request_def = tmpl_request(map->lhs),
+                                       .list_def = tmpl_list(map->lhs),
+                                       .prefix = TMPL_ATTR_REF_PREFIX_AUTO
+                               },
                                .at_runtime = true,
                        };
 
                        tmpl_rules_t rhs_rules = {
-                               .dict_def = request->dict,
+                               .attr = {
+                                       .dict_def = request->dict
+                               },
                                .at_runtime = true,
                        };
 
@@ -369,8 +373,10 @@ int fr_ldap_map_do(request_t *request, LDAP *handle,
                        char            *value;
 
                        tmpl_rules_t parse_rules = {
-                               .dict_def = request->dict,
-                               .prefix = TMPL_ATTR_REF_PREFIX_AUTO,
+                               .attr = {
+                                       .dict_def = request->dict,
+                                       .prefix = TMPL_ATTR_REF_PREFIX_AUTO
+                               }
                        };
 
                        value = fr_ldap_berval_to_string(request, values[i]);
index 166b11bfe3322ed049ca70d3c0a3bc4b27430ff8..b352fc20e306b590f28342e243054635b255c106 100644 (file)
@@ -384,7 +384,7 @@ int fr_redis_reply_to_map(TALLOC_CTX *ctx, map_list_t *out, request_t *request,
 
        MEM(map = talloc_zero(ctx, map_t));
        slen = tmpl_afrom_attr_str(map, NULL, &map->lhs, key->str,
-                                  &(tmpl_rules_t){
+                                  &(tmpl_attr_rules_t){
                                        .prefix = TMPL_ATTR_REF_PREFIX_NO,
                                        .dict_def = request->dict
                                   });
index 7335f79555d6a88957050a0d7320f57ede5a7cef..904c08eb425636e6dcbe8b03070c70283d8b3b4c 100644 (file)
@@ -141,16 +141,16 @@ typedef struct {
 static inline CC_HINT(always_inline) int cf_tmpl_rules_verify(CONF_SECTION *cs, tmpl_rules_t const *rules)
 {
        if (cf_section_has_parent(cs, "policy", NULL)) {
-               if (!fr_cond_assert_msg(!rules->dict_def || (rules->dict_def == fr_dict_internal()),
+               if (!fr_cond_assert_msg(!rules->attr.dict_def || (rules->attr.dict_def == fr_dict_internal()),
                                        "Protocol dictionary must be NULL not %s",
-                                       fr_dict_root(rules->dict_def)->name)) return -1;
+                                       fr_dict_root(rules->attr.dict_def)->name)) return -1;
 
        } else {
-               if (!fr_cond_assert_msg(rules->dict_def, "No protocol dictionary set")) return -1;
-               if (!fr_cond_assert_msg(rules->dict_def != fr_dict_internal(), "rules->dict_def must not be the internal dictionary")) return -1;
+               if (!fr_cond_assert_msg(rules->attr.dict_def, "No protocol dictionary set")) return -1;
+               if (!fr_cond_assert_msg(rules->attr.dict_def != fr_dict_internal(), "rules->attr.dict_def must not be the internal dictionary")) return -1;
        }
 
-       if (!fr_cond_assert_msg(!rules->allow_foreign, "rules->allow_foreign must be false")) return -1;
+       if (!fr_cond_assert_msg(!rules->attr.allow_foreign, "rules->allow_foreign must be false")) return -1;
        if (!fr_cond_assert_msg(!rules->at_runtime, "rules->at_runtime must be false")) return -1;
 
        return 0;
@@ -1190,9 +1190,11 @@ static CONF_ITEM *process_if(cf_stack_t *stack)
         */
        while (true) {
                tmpl_rules_t t_rules = {
-                       .dict_def = dict,
-                       .allow_unresolved = true,
-                       .allow_unknown = true,
+                       .attr = {
+                               .dict_def = dict,
+                               .allow_unresolved = true,
+                               .allow_unknown = true
+                       }
                };
 
                RULES_VERIFY(cs, &t_rules);
index 95af1df0b1223870895aa75df7eb923bbe351856..3012cff411ed344ff0f7e1463d76ef253f5d0d8c 100644 (file)
@@ -210,9 +210,11 @@ int cf_pair_parse_value(TALLOC_CTX *ctx, void *out, UNUSED void *base, CONF_ITEM
        if (tmpl) {
                tmpl_t                  *vpt;
                static tmpl_rules_t     rules = {
-                                               .allow_unknown = true,
-                                               .allow_unresolved = true,
-                                               .allow_foreign = true
+                                               .attr = {
+                                                       .allow_unknown = true,
+                                                       .allow_unresolved = true,
+                                                       .allow_foreign = true
+                                               }
                                        };
                fr_type_t               cast = FR_TYPE_NULL;
                fr_sbuff_t              sbuff = FR_SBUFF_IN(cp->value, strlen(cp->value));
@@ -1491,7 +1493,7 @@ int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
                         */
                        slen = xlat_tokenize(cs, &xlat, NULL,
                                             &FR_SBUFF_IN(cp->value, talloc_array_length(cp->value) - 1), NULL,
-                                            &(tmpl_rules_t){
+                                            &(tmpl_attr_rules_t){
                                                .dict_def = dict,
                                                .allow_unknown = false,
                                                .allow_unresolved = false,
index 26027146d9e00246f22634d7db80ad72e79115e8..e6d9c418eef04aae93401738d0968d6fc2cb7f53 100644 (file)
@@ -144,7 +144,7 @@ static bool cond_eval_tmpl(request_t *request, tmpl_t const *in, fr_value_box_t
                /*
                 *      No cast means that it's an existence check.
                 */
-               if (fr_type_is_null(vpt->cast)) {
+               if (fr_type_is_null(tmpl_rules_cast(vpt))) {
                        return (tmpl_find_vp(NULL, request, vpt) == 0);
                }
 
@@ -159,10 +159,10 @@ static bool cond_eval_tmpl(request_t *request, tmpl_t const *in, fr_value_box_t
                MEM(box = fr_value_box_alloc_null(request));
                box_free = box;
 
-               if (fr_value_box_cast(box, box, vpt->cast, NULL, &vp->data) < 0) {
+               if (fr_value_box_cast(box, box, tmpl_rules_cast(vpt), NULL, &vp->data) < 0) {
                        if (request) RPEDEBUG("Failed casting %pV to type %s", box,
                                              fr_table_str_by_value(fr_value_box_type_table,
-                                                                   vpt->cast, "??"));
+                                                                   tmpl_rules_cast(vpt), "??"));
                        goto done;
                }
                break;
@@ -183,7 +183,7 @@ static bool cond_eval_tmpl(request_t *request, tmpl_t const *in, fr_value_box_t
                 *      We don't yet have xlats returning lists of
                 *      value boxes, so there's an assert.
                 */
-               if (fr_type_is_null(vpt->cast)) {
+               if (fr_type_is_null(tmpl_rules_cast(vpt))) {
                        switch (box->type) {
                        case FR_TYPE_STRING:
                        case FR_TYPE_OCTETS:
@@ -385,7 +385,7 @@ static int cond_realize_tmpl(request_t *request,
         *      converted to the correct thing.
         */
        case TMPL_TYPE_DATA:
-               fr_assert((fr_type_is_null(in->cast)) || (in->cast == tmpl_value_type(in)));
+               fr_assert((fr_type_is_null(tmpl_rules_cast(in))) || (tmpl_rules_cast(in) == tmpl_value_type(in)));
                *out = tmpl_value(in);
                fr_assert(!async);
                return 0;
@@ -411,14 +411,14 @@ static int cond_realize_tmpl(request_t *request,
                 *      don't find that, then the *other* side MUST
                 *      have an explicit data type.
                 */
-               if (in->cast != FR_TYPE_NULL) {
-                       cast_type = in->cast;
+               if (tmpl_rules_cast(in) != FR_TYPE_NULL) {
+                       cast_type = tmpl_rules_cast(in);
 
                } else if (!other) {
                        cast_type = FR_TYPE_STRING;
 
-               } else if (other->cast) {
-                       cast_type = other->cast;
+               } else if (tmpl_rules_cast(other)) {
+                       cast_type = tmpl_rules_cast(other);
 
                } else if (tmpl_is_attr(other)) {
                        da = tmpl_da(other);
@@ -484,11 +484,11 @@ static int cond_realize_attr(request_t *request, fr_value_box_t **realized, fr_v
        if (da) {
                cast_type = da->type;
 
-       } else if (vpt->cast != FR_TYPE_NULL) {
+       } else if (tmpl_rules_cast(vpt) != FR_TYPE_NULL) {
                /*
                 *      If there's an explicit cast, use that.
                 */
-               cast_type = vpt->cast;
+               cast_type = tmpl_rules_cast(vpt);
 
        } else {
                /*
@@ -510,7 +510,7 @@ static int cond_realize_attr(request_t *request, fr_value_box_t **realized, fr_v
        if (fr_value_box_cast(request, box, cast_type, da, &vp->data) < 0) {
                if (request) RPEDEBUG("Failed casting %pV to type %s", &vp->data,
                                      fr_table_str_by_value(fr_value_box_type_table,
-                                                           vpt->cast, "??"));
+                                                           tmpl_rules_cast(vpt), "??"));
                return false;
        }
 
@@ -527,7 +527,7 @@ static bool cond_compare_attrs(request_t *request, fr_value_box_t *lhs, map_t co
        fr_value_box_t          *rhs, rhs_cast;
        fr_dict_attr_t const    *da = NULL;
 
-       if (tmpl_is_attr(map->lhs) && fr_type_is_null(map->lhs->cast)) da = tmpl_da(map->lhs);
+       if (tmpl_is_attr(map->lhs) && fr_type_is_null(tmpl_rules_cast(map->lhs))) da = tmpl_da(map->lhs);
 
        fr_assert(lhs != NULL);
        rhs = NULL;             /* shut up clang scan */
index a0e67d0839293c78a762e293057b56acf3430650..ec7d46256947534afc688eebbb057d18d39a581d 100644 (file)
@@ -98,10 +98,10 @@ ssize_t cond_print(fr_sbuff_t *out, fr_cond_t const *in)
                        break;
 
                case COND_TYPE_MAP:
-                       if (c->data.map->lhs->cast) {
+                       if (tmpl_rules_cast(c->data.map->lhs)) {
                                FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "<%s>",
                                                           fr_table_str_by_value(fr_value_box_type_table,
-                                                                                c->data.map->lhs->cast, "??"));
+                                                                                tmpl_rules_cast(c->data.map->lhs), "??"));
                        }
                        FR_SBUFF_RETURN(map_print, &our_out, c->data.map);
                        break;
@@ -204,9 +204,9 @@ static int cond_cast_tmpl(tmpl_t *vpt, fr_type_t type, tmpl_t *other)
         *      Which means we no longer need the cast.
         */
        fr_assert(tmpl_is_data(vpt));
-       fr_assert_msg(fr_type_is_null(vpt->cast) || (vpt->cast == tmpl_value_type(vpt)),
+       fr_assert_msg(fr_type_is_null(tmpl_rules_cast(vpt)) || (tmpl_rules_cast(vpt) == tmpl_value_type(vpt)),
                      "Cast mismatch, target was %s, but output was %s",
-                     fr_table_str_by_value(fr_value_box_type_table, vpt->cast, "<INVALID>"),
+                     fr_table_str_by_value(fr_value_box_type_table, tmpl_rules_cast(vpt), "<INVALID>"),
                      fr_table_str_by_value(fr_value_box_type_table, tmpl_value_type(vpt), "<INVALID>"));
        (void) tmpl_cast_set(vpt, FR_TYPE_NULL);
        return 0;
@@ -228,7 +228,7 @@ int fr_cond_promote_types(fr_cond_t *c, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs
        if (tmpl_contains_regex(c->data.map->rhs)) {
                fr_assert((c->data.map->op == T_OP_REG_EQ) || (c->data.map->op == T_OP_REG_NE));
                fr_assert(!tmpl_is_list(c->data.map->lhs));
-               fr_assert(fr_type_is_null(c->data.map->rhs->cast));
+               fr_assert(fr_type_is_null(tmpl_rules_cast(c->data.map->rhs)));
 
                /*
                 *      Can't use casts with regular expressions, on
@@ -242,7 +242,7 @@ int fr_cond_promote_types(fr_cond_t *c, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs
                 *      @todo - ensure that the regex interpreter is
                 *      binary-safe!
                 */
-               cast_type = c->data.map->lhs->cast;
+               cast_type = tmpl_rules_cast(c->data.map->lhs);
                if (cast_type != FR_TYPE_NULL) {
                        if ((cast_type != FR_TYPE_STRING) &&
                            (cast_type != FR_TYPE_OCTETS)) {
@@ -325,8 +325,8 @@ int fr_cond_promote_types(fr_cond_t *c, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs
        /*
         *      Figure out the type of the LHS.
         */
-       if (c->data.map->lhs->cast != FR_TYPE_NULL) {
-               lhs_type = c->data.map->lhs->cast;
+       if (tmpl_rules_cast(c->data.map->lhs) != FR_TYPE_NULL) {
+               lhs_type = tmpl_rules_cast(c->data.map->lhs);
                /*
                 *      Two explicit casts MUST be the same, otherwise
                 *      it's an error.
@@ -334,8 +334,8 @@ int fr_cond_promote_types(fr_cond_t *c, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs
                 *      We only do type promotion when at least one
                 *      data type is implicitly specified.
                 */
-               if (c->data.map->rhs->cast != FR_TYPE_NULL) {
-                       if (c->data.map->rhs->cast != lhs_type) {
+               if (tmpl_rules_cast(c->data.map->rhs) != FR_TYPE_NULL) {
+                       if (tmpl_rules_cast(c->data.map->rhs) != lhs_type) {
                                fr_strerror_const("Incompatible casts");
                                if (in) fr_sbuff_set(in, fr_sbuff_start(in));
                                return -1;
@@ -377,8 +377,8 @@ int fr_cond_promote_types(fr_cond_t *c, fr_sbuff_t *in, fr_sbuff_marker_t *m_lhs
        /*
         *      Figure out the type of the RHS.
         */
-       if (c->data.map->rhs->cast != FR_TYPE_NULL) {
-               rhs_type = c->data.map->rhs->cast;
+       if (tmpl_rules_cast(c->data.map->rhs) != FR_TYPE_NULL) {
+               rhs_type = tmpl_rules_cast(c->data.map->rhs);
 
        } else if (tmpl_is_data(c->data.map->rhs)) {
                rhs_type = tmpl_value_type(c->data.map->rhs);
@@ -1252,7 +1252,7 @@ static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **out,
                }
 
        unary:
-               if (lhs->cast != FR_TYPE_NULL) {
+               if (tmpl_rules_cast(lhs) != FR_TYPE_NULL) {
                        fr_strerror_const("Cannot do cast for existence check");
                        fr_sbuff_set(&our_in, &m_lhs_cast);
                        goto error;
index fe0a9e53636883a30911fd1b4efbdfcfe7cb0803..1f1a04c6c1c740fb874f72fdad9a378ce00031bc 100644 (file)
@@ -97,7 +97,7 @@ static inline map_t *map_alloc(TALLOC_CTX *ctx, map_t *parent)
 int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp,
                 tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules)
 {
-       map_t   *map;
+       map_t           *map;
        char const      *attr, *value, *marker_subject;
        ssize_t         slen;
        fr_token_t      type;
@@ -146,7 +146,7 @@ int map_afrom_cp(TALLOC_CTX *ctx, map_t **out, map_t *parent, CONF_PAIR *cp,
                break;
 
        default:
-               slen = tmpl_afrom_attr_str(ctx, NULL, &map->lhs, attr, lhs_rules);
+               slen = tmpl_afrom_attr_str(ctx, NULL, &map->lhs, attr, &lhs_rules->attr);
                if (slen <= 0) {
                        cf_log_err(cp, "Failed parsing attribute reference %s - %s", attr, fr_strerror());
                        marker_subject = attr;
@@ -321,14 +321,14 @@ ssize_t map_afrom_substr(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, fr_sbuf
                         tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
                         fr_sbuff_parse_rules_t const *p_rules)
 {
-       ssize_t                 slen;
-       fr_token_t              token;
-       map_t                   *map;
-       bool                    is_child;
-       fr_sbuff_t              our_in = FR_SBUFF(in);
-       fr_sbuff_marker_t       m_lhs, m_rhs, m_op;
-       fr_sbuff_term_t const   *tt = p_rules ? p_rules->terminals : NULL;
-       map_t                   *parent, *new_parent;
+       ssize_t                         slen;
+       fr_token_t                      token;
+       map_t                           *map;
+       bool                            is_child;
+       fr_sbuff_t                      our_in = FR_SBUFF(in);
+       fr_sbuff_marker_t               m_lhs, m_rhs, m_op;
+       fr_sbuff_term_t const           *tt = p_rules ? p_rules->terminals : NULL;
+       map_t                           *parent, *new_parent;
 
        if (parent_p) {
                new_parent = parent = *parent_p;
@@ -355,14 +355,20 @@ ssize_t map_afrom_substr(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, fr_sbuf
                break;
 
        default:
+       {
+               tmpl_attr_rules_t our_lhs_attr_rules;
+
+               if (lhs_rules) {
+                       our_lhs_attr_rules = lhs_rules->attr;
+               } else {
+                       memset(&our_lhs_attr_rules, 0, sizeof(our_lhs_attr_rules));
+               }
                /*
                 *      Allow for ".foo" to refer to the current
                 *      parents list.  Allow for "..foo" to refer to
                 *      the grandparent list.
                 */
-               if (lhs_rules->prefix == TMPL_ATTR_REF_PREFIX_NO) {
-                       tmpl_rules_t our_lhs_rules;
-
+               if (lhs_rules->attr.prefix == TMPL_ATTR_REF_PREFIX_NO) {
                        /*
                         *      One '.' means "the current parent".
                         */
@@ -393,12 +399,11 @@ ssize_t map_afrom_substr(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, fr_sbuf
                         *      Start looking in the correct parent, not in whatever we were handed.
                         */
                        if (is_child) {
-                               our_lhs_rules = *lhs_rules;
                                fr_assert(tmpl_is_attr(parent->lhs));
-                               our_lhs_rules.attr_parent = tmpl_da(parent->lhs);
+                               our_lhs_attr_rules.parent = tmpl_da(parent->lhs);
 
                                slen = tmpl_afrom_attr_substr(map, NULL, &map->lhs, &our_in,
-                                                             &map_parse_rules_bareword_quoted, &our_lhs_rules);
+                                                             &map_parse_rules_bareword_quoted, &our_lhs_attr_rules);
                                break;
                        }
 
@@ -411,9 +416,10 @@ ssize_t map_afrom_substr(TALLOC_CTX *ctx, map_t **out, map_t **parent_p, fr_sbuf
                }
 
                slen = tmpl_afrom_attr_substr(map, NULL, &map->lhs, &our_in,
-                                             &map_parse_rules_bareword_quoted, lhs_rules);
+                                             &map_parse_rules_bareword_quoted, &our_lhs_attr_rules);
                break;
        }
+       }
 
        if (!map->lhs) {
        error:
@@ -635,37 +641,6 @@ check_for_child:
        return fr_sbuff_set(in, &our_in);
 }
 
-
-static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_SECTION *cs,
-                               tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
-                               map_validate_t validate, void *uctx,
-                               unsigned int max);
-
-
-/** Convert an 'update' config section into an attribute map.
- *
- * Uses 'name2' of section to set default request and lists.
- *
- * @param[in] ctx              for talloc.
- * @param[out] out             Where to store the allocated map.
- * @param[in] cs               the update section
- * @param[in] lhs_rules                rules for parsing LHS attribute references.
- * @param[in] rhs_rules                rules for parsing RHS attribute references.
- * @param[in] validate         map using this callback (may be NULL).
- * @param[in] uctx             to pass to callback.
- * @param[in] max              number of mappings to process.
- * @return
- *     - 0 on success.
- *     - -1 on failure.
- */
-int map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs,
-                tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
-                map_validate_t validate, void *uctx,
-                unsigned int max)
-{
-       return _map_afrom_cs(ctx, out, NULL, cs, lhs_rules, rhs_rules, validate, uctx, max);
-}
-
 static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_SECTION *cs,
                         tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
                         map_validate_t validate, void *uctx,
@@ -695,14 +670,14 @@ static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_S
         */
        cs_list = p = cf_section_name2(cs);
        if (cs_list && (strcmp(cf_section_name1(cs), "update") == 0)) {
-               p += tmpl_request_ref_by_name(&our_lhs_rules.request_def, p, REQUEST_CURRENT);
-               if (our_lhs_rules.request_def == REQUEST_UNKNOWN) {
+               p += tmpl_request_ref_by_name(&our_lhs_rules.attr.request_def, p, REQUEST_CURRENT);
+               if (our_lhs_rules.attr.request_def == REQUEST_UNKNOWN) {
                        cf_log_err(ci, "Default request specified in mapping section is invalid");
                        return -1;
                }
 
-               our_lhs_rules.list_def = fr_table_value_by_str(pair_list_table, p, PAIR_LIST_UNKNOWN);
-               if (our_lhs_rules.list_def == PAIR_LIST_UNKNOWN) {
+               our_lhs_rules.attr.list_def = fr_table_value_by_str(pair_list_table, p, PAIR_LIST_UNKNOWN);
+               if (our_lhs_rules.attr.list_def == PAIR_LIST_UNKNOWN) {
                        cf_log_err(ci, "Default list \"%s\" specified in mapping section is invalid", p);
                        return -1;
                }
@@ -727,11 +702,11 @@ static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_S
                 *      assignment operator, THEN we allow sub-maps.
                 */
                if (cf_item_is_section(ci)) {
-                       CONF_SECTION *subcs;
-                       fr_token_t token;
-                       ssize_t slen;
-                       bool qualifiers = our_lhs_rules.disallow_qualifiers;
-                       map_list_t child_list;
+                       CONF_SECTION    *subcs;
+                       fr_token_t      token;
+                       ssize_t         slen;
+                       bool            qualifiers = our_lhs_rules.attr.disallow_qualifiers;
+                       map_list_t      child_list;
 
                        map_list_init(&child_list);
                        subcs = cf_item_to_section(ci);
@@ -753,7 +728,7 @@ static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_S
                         *      them for now.  Once the functionality
                         *      is tested and used, we can allow that.
                         */
-                       slen = tmpl_afrom_attr_str(ctx, NULL, &map->lhs, cf_section_name1(subcs), &our_lhs_rules);
+                       slen = tmpl_afrom_attr_str(ctx, NULL, &map->lhs, cf_section_name1(subcs), &our_lhs_rules.attr);
                        if (slen <= 0) {
                                cf_log_err(ci, "Failed parsing attribute reference for list %s - %s",
                                           cf_section_name1(subcs), fr_strerror());
@@ -784,15 +759,15 @@ static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_S
                         *      the child attributes go into the
                         *      parent one.
                         */
-                       our_lhs_rules.disallow_qualifiers = true;
+                       our_lhs_rules.attr.disallow_qualifiers = true;
 
                        /*
                         *      The leaf reference of the outer section
                         *      is used as the parsing context of the
                         *      inner section.
                         */
-                       our_lhs_rules.attr_parent = tmpl_da(map->lhs);
-                       our_lhs_rules.prefix = TMPL_ATTR_REF_PREFIX_NO;
+                       our_lhs_rules.attr.parent = tmpl_da(map->lhs);
+                       our_lhs_rules.attr.prefix = TMPL_ATTR_REF_PREFIX_NO;
 
                        /*
                         *      This prints out any relevant error
@@ -812,7 +787,7 @@ static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_S
                        }
                        map_list_move(&map->child, &child_list);
 
-                       our_lhs_rules.disallow_qualifiers = qualifiers;
+                       our_lhs_rules.attr.disallow_qualifiers = qualifiers;
                        MAP_VERIFY(map);
                        goto next;
                }
@@ -847,6 +822,30 @@ static int _map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, map_t *parent, CONF_S
 
 }
 
+/** Convert an 'update' config section into an attribute map.
+ *
+ * Uses 'name2' of section to set default request and lists.
+ *
+ * @param[in] ctx              for talloc.
+ * @param[out] out             Where to store the allocated map.
+ * @param[in] cs               the update section
+ * @param[in] lhs_rules                rules for parsing LHS attribute references.
+ * @param[in] rhs_rules                rules for parsing RHS attribute references.
+ * @param[in] validate         map using this callback (may be NULL).
+ * @param[in] uctx             to pass to callback.
+ * @param[in] max              number of mappings to process.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
+ */
+int map_afrom_cs(TALLOC_CTX *ctx, map_list_t *out, CONF_SECTION *cs,
+                tmpl_rules_t const *lhs_rules, tmpl_rules_t const *rhs_rules,
+                map_validate_t validate, void *uctx,
+                unsigned int max)
+{
+       return _map_afrom_cs(ctx, out, NULL, cs, lhs_rules, rhs_rules, validate, uctx, max);
+}
+
 /** Convert a value box to a map
  *
  * This is mainly used in IO modules, where another function is used to convert
@@ -969,8 +968,8 @@ int map_afrom_vp(TALLOC_CTX *ctx, map_t **out, fr_pair_t *vp, tmpl_rules_t const
        tmpl_attr_set_leaf_da(map->lhs, vp->da);
        tmpl_attr_set_leaf_num(map->lhs, NUM_ANY);
 
-       tmpl_attr_set_request(map->lhs, rules->request_def);
-       tmpl_attr_set_list(map->lhs, rules->list_def);
+       tmpl_attr_set_request(map->lhs, rules->attr.request_def);
+       tmpl_attr_set_list(map->lhs, rules->attr.list_def);
 
        tmpl_print(&FR_SBUFF_OUT(buffer, sizeof(buffer)), map->lhs, TMPL_ATTR_REF_PREFIX_YES, NULL);
        tmpl_set_name(map->lhs, T_BARE_WORD, buffer, -1);
@@ -1448,9 +1447,9 @@ int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t f
                }
 
                slen = tmpl_afrom_attr_str(tmp_ctx, NULL, &exp_lhs, attr_str,
-                                          &(tmpl_rules_t){
-                                               .dict_def = request->dict,
-                                               .prefix = TMPL_ATTR_REF_PREFIX_NO
+                                          &(tmpl_attr_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", attr_str);
index 25a66536e949251bb7a6c6578cffd930a7022347..2d32b9fac7d893c18dd55b571dc6b7e80ee9aff8 100644 (file)
@@ -329,9 +329,9 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                }
 
                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
+                                          &(tmpl_attr_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",
@@ -727,11 +727,12 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                (void)fr_pair_dcursor_init(&from, &vp_head);
                while ((vp = fr_dcursor_remove(&from))) {
                        map_t *mod;
-                       tmpl_rules_t rules;
-
-                       memset(&rules, 0, sizeof(rules));
-                       rules.request_def = tmpl_request(mutated->lhs);
-                       rules.list_def = tmpl_list(mutated->lhs);
+                       tmpl_rules_t rules = {
+                               .attr = {
+                                       .request_def = tmpl_request(mutated->lhs),
+                                       .list_def = tmpl_list(mutated->lhs)
+                               }
+                       };
 
                        if (map_afrom_vp(n, &mod, vp, &rules) < 0) {
                                RPEDEBUG("Failed converting VP to map");
index 8559d3ee95367d7ef5fd98334bdae901bac7a60b..4b278a9c8131a907002534a9e4063563077bbabd 100644 (file)
@@ -249,6 +249,9 @@ extern fr_table_num_ordered_t const tmpl_type_table[];
 extern size_t tmpl_type_table_len;
 
 typedef struct tmpl_rules_s tmpl_rules_t;
+typedef struct tmpl_attr_rules_s tmpl_attr_rules_t;
+typedef struct tmpl_data_rules_s tmpl_data_rules_t;
+typedef struct tmpl_xlat_rules_s tmpl_xlat_rules_t;
 typedef struct tmpl_res_rules_s tmpl_res_rules_t;
 typedef struct tmpl_s tmpl_t;
 
@@ -278,12 +281,7 @@ typedef enum {
        TMPL_ATTR_REF_PREFIX_AUTO                       //!< Attribute refs may have a '&' prefix.
 } tmpl_attr_prefix_t;
 
-/** Optional arguments passed to vp_tmpl functions
- *
- */
-struct tmpl_rules_s {
-       tmpl_rules_t const      *parent;                //!< for parent / child relationships
-
+struct tmpl_attr_rules_s {
        fr_dict_t const         *dict_def;              //!< Default dictionary to use
                                                        ///< with unqualified attribute references.
 
@@ -293,7 +291,7 @@ struct tmpl_rules_s {
        tmpl_pair_list_t        list_def;               //!< Default list to use with unqualified
                                                        ///< attribute reference.
 
-       fr_dict_attr_t const    *attr_parent;           //!< Point in dictionary tree to resume parsing
+       fr_dict_attr_t const    *parent;                //!< Point in dictionary tree to resume parsing
                                                        ///< from.  If this is provided then dict_def
                                                        ///< request_def and list_def will be ignored
                                                        ///< and the presence of any of those qualifiers
@@ -315,17 +313,38 @@ struct tmpl_rules_s {
 
        bool                    disallow_filters;       //!< disallow filters.
 
-       bool                    at_runtime;             //!< Produce an ephemeral/runtime tmpl.
-                                                       ///< Instantiated xlats are not added to the global
-                                                       ///< trees, regexes are not JIT'd.
        bool                    list_as_attr;           //!< return #TMPL_TYPE_ATTR for lists, and not #TMPL_TYPE_LIST
 
+       tmpl_attr_prefix_t      prefix;                 //!< Whether the attribute reference requires
+                                                       ///< a prefix.
+};
+
+struct tmpl_data_rules_s {
+       fr_dict_attr_t const    *enumv;                 //!< Enumeration attribute used to resolve enum values.
+
+       fr_type_t               cast;                   //!< Whether there was an explicit cast.
+                                                       ///< Used to determine if barewords or other values
+                                                       ///< should be converted to an internal data type.
+};
 
+struct tmpl_xlat_rules_s {
        fr_event_list_t         *runtime_el;            //!< The eventlist to use for runtime instantiation
                                                        ///< of xlats.
+};
 
-       tmpl_attr_prefix_t      prefix;                 //!< Whether the attribute reference requires
-                                                       ///< a prefix.
+/** Optional arguments passed to vp_tmpl functions
+ *
+ */
+struct tmpl_rules_s {
+       tmpl_rules_t const      *parent;                //!< for parent / child relationships
+
+       tmpl_attr_rules_t       attr;                   //!< Rules/data for parsing attribute references.
+       tmpl_data_rules_t       data;                   //!< Rules/data for parsing attribute data and enumerations.
+       tmpl_xlat_rules_t       xlat;                   //!< Rules/data for parsing xlats.
+
+       bool                    at_runtime;             //!< Produce an ephemeral/runtime tmpl.
+                                                       ///< Instantiated xlats are not added to the global
+                                                       ///< trees, regexes are not JIT'd.
 };
 
 /** Similar to tmpl_rules_t, but used to specify parameters that may change during subsequent resolution passes
@@ -542,10 +561,6 @@ struct tmpl_s {
                };
        } data;
 
-       fr_type_t       _CONST          cast;   //!< Type we should interpret unresolved data with.
-       fr_dict_attr_t const * _CONST   enumv;  //!< Enumeration we should use when parsing unescaped
-                                               ///< i.e. barewords with an unknown format.
-
        tmpl_rules_t    _CONST          rules;  //!< The rules that were used when creating the tmpl.
                                                ///< These are useful for multiple resolution passes as
                                                ///< they ensure the correct parsing rules are applied.
@@ -676,6 +691,9 @@ static inline tmpl_pair_list_t tmpl_list(tmpl_t const *vpt)
 #define tmpl_value_type(_tmpl)                 (_tmpl)->data.literal.type
 #define tmpl_value_enumv(_tmpl)                        (_tmpl)->data.literal.enumv
 
+#define tmpl_rules_cast(_tmpl)                 (_tmpl)->rules.data.cast
+#define tmpl_rules_enumv(_tmpl)                        (_tmpl)->rules.data.enumv
+
 /*
  *     Temporary macros to track where we do assignments
  */
@@ -907,11 +925,11 @@ int                       tmpl_attr_afrom_list(TALLOC_CTX *ctx, tmpl_t **out, tmpl_t const *list,
 ssize_t                        tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
                                               tmpl_t **out, fr_sbuff_t *name,
                                               fr_sbuff_parse_rules_t const *p_rules,
-                                              tmpl_rules_t const *t_rules);
+                                              tmpl_attr_rules_t const *t_rules);
 
 ssize_t                        tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
                                            tmpl_t **out, char const *name,
-                                           tmpl_rules_t const *rules) CC_HINT(nonnull (3, 4));
+                                           tmpl_attr_rules_t const *rules) CC_HINT(nonnull (3, 4));
 
 ssize_t                        tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                                          fr_sbuff_t *in,
index ca816db3e1275d3d1967ebcb2d53c6637f7e253b..fd3cba5840e37790a8664cd933aa855d599634a0 100644 (file)
@@ -367,7 +367,7 @@ fr_pair_t *tmpl_dcursor_init(int *err, TALLOC_CTX *ctx, tmpl_dcursor_ctx_t *cc,
        /*
         *      Get the right list in the specified context
         */
-       if (!vpt->rules.list_as_attr) {
+       if (!vpt->rules.attr.list_as_attr) {
                list_head = tmpl_list_head(request, tmpl_list(vpt));
                if (!list_head) {
                        fr_strerror_printf("List \"%s\" not available in this context",
@@ -513,7 +513,7 @@ int tmpl_extents_find(TALLOC_CTX *ctx,
                }
        }
 
-       if (!vpt->rules.list_as_attr) {
+       if (!vpt->rules.attr.list_as_attr) {
                /*
                 *      Get the right list in the specified context
                 */
index c294637a7ed03dd2dbff983274fc91a19e1dd0a9..adaef27f3d20137b56b8a9cd01f23bd669a2dd9f 100644 (file)
@@ -252,7 +252,7 @@ fr_type_t tmpl_expanded_type(tmpl_t const *vpt)
        /*
         *      Casts take precedence over everything.
         */
-       if (vpt->cast != FR_TYPE_NULL) return vpt->cast;
+       if (tmpl_rules_cast(vpt) != FR_TYPE_NULL) return tmpl_rules_cast(vpt);
 
        /*
         *      Anything that's not a bare word will
index 7fdc292a2e876f62f85e765f0b1ddb5570e3f9e4..92d3edd269fd8cc2c1674b8704b6a2ab38ed5b4b 100644 (file)
@@ -48,8 +48,10 @@ RCSID("$Id$")
  * Defaults are used if a NULL rules pointer is passed to the parsing function.
  */
 static tmpl_rules_t const default_attr_rules = {
-       .request_def = REQUEST_CURRENT,
-       .list_def = PAIR_LIST_REQUEST
+       .attr = {
+               .request_def = REQUEST_CURRENT,
+               .list_def = PAIR_LIST_REQUEST
+       }
 };
 
 /* clang-format off */
@@ -555,7 +557,7 @@ void tmpl_set_name(tmpl_t *vpt, fr_token_t quote, char const *name, ssize_t len)
  */
 void tmpl_set_dict_def(tmpl_t *vpt, fr_dict_t const *dict)
 {
-       vpt->rules.dict_def = dict;
+       vpt->rules.attr.dict_def = dict;
 }
 
 /** Initialise a tmpl using a format string to create the name
@@ -1097,7 +1099,7 @@ static inline CC_HINT(always_inline) void tmpl_attr_insert(tmpl_t *vpt, tmpl_att
  *     - TMPL_ATTR_REF_BAD_FILTER on failure.
  */
 static tmpl_attr_filter_t tmpl_attr_parse_filter(tmpl_attr_error_t *err, tmpl_attr_t *ar,
-                                                fr_sbuff_t *name, tmpl_rules_t const *t_rules)
+                                                fr_sbuff_t *name, tmpl_attr_rules_t const *t_rules)
 {
        /*
         *      Parse array subscript (and eventually complex filters)
@@ -1191,7 +1193,7 @@ static inline CC_HINT(nonnull(3,6))
 int tmpl_attr_afrom_attr_unresolved_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
                                           tmpl_t *vpt,
                                           fr_dict_attr_t const *parent, fr_dict_attr_t const *namespace,
-                                          fr_sbuff_t *name, tmpl_rules_t const *t_rules,
+                                          fr_sbuff_t *name, tmpl_attr_rules_t const *t_rules,
                                           unsigned int depth)
 {
        tmpl_attr_t             *ar = NULL;
@@ -1306,7 +1308,7 @@ static inline int tmpl_attr_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t
                                              tmpl_t *vpt,
                                              fr_dict_attr_t const *parent, fr_dict_attr_t const *namespace,
                                              fr_sbuff_t *name,
-                                             fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
+                                             fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules,
                                              unsigned int depth)
 {
        uint32_t                oid = 0;
@@ -1371,7 +1373,7 @@ static inline int tmpl_attr_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t
                 *      Discard any errors here... It's more
                 *      useful to have the original.
                 */
-               if (!da && !vpt->rules.disallow_internal &&
+               if (!da && !vpt->rules.attr.disallow_internal &&
                    (ar = tmpl_attr_list_tail(&vpt->data.attribute.ar)) &&
                    (ar->type == TMPL_ATTR_TYPE_NORMAL) && (ar->ar_da->type == FR_TYPE_GROUP)) {
                        (void)fr_dict_attr_by_name_substr(NULL,
@@ -1690,7 +1692,7 @@ static inline int tmpl_request_ref_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_
                                                     tmpl_t *vpt,
                                                     fr_sbuff_t *name,
                                                     fr_sbuff_parse_rules_t const *p_rules,
-                                                    tmpl_rules_t const **pt_rules,
+                                                    tmpl_attr_rules_t const **pt_rules,
                                                     unsigned int depth)
 {
        tmpl_request_ref_t                      ref;
@@ -1698,7 +1700,7 @@ static inline int tmpl_request_ref_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_
        tmpl_request_t                          *rr;
        FR_DLIST_HEAD(tmpl_request_list)        *list = &vpt->data.attribute.rr;
        fr_sbuff_marker_t                       s_m;
-       tmpl_rules_t const                      *t_rules = *pt_rules;
+       tmpl_attr_rules_t const                 *t_rules = *pt_rules;
 
        fr_sbuff_marker(&s_m, name);
        fr_sbuff_out_by_longest_prefix(&ref_len, &ref, tmpl_request_ref_table, name, t_rules->request_def);
@@ -1745,7 +1747,7 @@ static inline int tmpl_request_ref_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_
                return -1;
        }
 
-       if (t_rules->attr_parent || t_rules->disallow_qualifiers) {
+       if (t_rules->parent || t_rules->disallow_qualifiers) {
                fr_strerror_const("It is not permitted to specify a request reference here");
                if (err) *err = TMPL_ATTR_ERROR_INVALID_LIST_QUALIFIER;
                return -1;
@@ -1760,14 +1762,6 @@ static inline int tmpl_request_ref_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_
        };
        tmpl_request_list_insert_tail(list, rr);
 
-       /*
-        *      Update the parsing rules if we go to the parent.
-        */
-        if (((ref == REQUEST_OUTER) || (ref == REQUEST_PARENT)) && t_rules->parent) {
-               t_rules = t_rules->parent;
-               *pt_rules = t_rules;
-       }
-
        /*
         *      Advance past the separator (if there is one)
         */
@@ -1829,7 +1823,7 @@ static inline int tmpl_request_ref_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_
 ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
                               tmpl_t **out, fr_sbuff_t *name,
                               fr_sbuff_parse_rules_t const *p_rules,
-                              tmpl_rules_t const *t_rules)
+                              tmpl_attr_rules_t const *t_rules)
 {
        int                     ret;
        size_t                  list_len = 0;
@@ -1839,7 +1833,7 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
        bool                    is_raw = false;
        fr_sbuff_marker_t       m_l;
 
-       if (!t_rules) t_rules = &default_attr_rules;    /* Use the defaults */
+       if (!t_rules) t_rules = &default_attr_rules.attr;       /* Use the defaults */
 
        if (err) *err = TMPL_ATTR_ERROR_NONE;
 
@@ -1925,7 +1919,7 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
                        vpt->data.attribute.list = t_rules->list_def;
                }
 
-               if ((t_rules->attr_parent || t_rules->disallow_qualifiers) && (list_len > 0)) {
+               if ((t_rules->parent || t_rules->disallow_qualifiers) && (list_len > 0)) {
                        fr_strerror_const("It is not permitted to specify a pair list here");
                        if (err) *err = TMPL_ATTR_ERROR_INVALID_LIST_QUALIFIER;
                        talloc_free(vpt);
@@ -1944,7 +1938,7 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
            (fr_sbuff_next_if_char(&our_name, '.') && fr_sbuff_is_in_charset(&our_name, fr_dict_attr_allowed_chars))) {
                ret = tmpl_attr_afrom_attr_substr(vpt, err,
                                                  vpt,
-                                                 t_rules->attr_parent, t_rules->attr_parent,
+                                                 t_rules->parent, t_rules->parent,
                                                  &our_name, p_rules, t_rules, 0);
                if (ret < 0) goto error;
 
@@ -2037,7 +2031,7 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
        }
 
        tmpl_set_name(vpt, T_BARE_WORD, fr_sbuff_start(&our_name), fr_sbuff_used(&our_name));
-       vpt->rules = *t_rules;  /* Record the rules */
+       vpt->rules.attr = *t_rules;     /* Record the rules */
 
        if (!tmpl_substr_terminal_check(&our_name, p_rules)) {
                fr_strerror_const("Unexpected text after attribute reference");
@@ -2068,11 +2062,11 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
  *     name string isn't parsed.
  */
 ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err,
-                           tmpl_t **out, char const *name, tmpl_rules_t const *t_rules)
+                           tmpl_t **out, char const *name, tmpl_attr_rules_t const *t_rules)
 {
        ssize_t slen, name_len;
 
-       if (!t_rules) t_rules = &default_attr_rules;    /* Use the defaults */
+       if (!t_rules) t_rules = &default_attr_rules.attr;       /* Use the defaults */
 
        name_len = strlen(name);
        slen = tmpl_afrom_attr_substr(ctx, err, out, &FR_SBUFF_IN(name, name_len), NULL, t_rules);
@@ -2578,7 +2572,7 @@ ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                 *      we find a '&' prefix.
                 */
                if (fr_sbuff_is_char(&our_in, '&')) return tmpl_afrom_attr_substr(ctx, NULL, out, in,
-                                                                                 p_rules, t_rules);
+                                                                                 p_rules, &t_rules->attr);
 
                /*
                 *      Allow bareword xlats if we
@@ -2591,10 +2585,11 @@ ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
 
                        vpt = tmpl_alloc_null(ctx);
                        if (!t_rules->at_runtime) {
-                               slen = xlat_tokenize(vpt, &head, &flags, &our_in, p_rules, t_rules);
+                               slen = xlat_tokenize(vpt, &head, &flags, &our_in, p_rules, &t_rules->attr);
                        } else {
                                slen = xlat_tokenize_ephemeral(vpt, &head,
-                                                              t_rules->runtime_el, &flags, &our_in, p_rules, t_rules);
+                                                              t_rules->xlat.runtime_el, &flags, &our_in,
+                                                              p_rules, t_rules);
                        }
 
                        if (!head) return slen;
@@ -2674,7 +2669,7 @@ ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                 *      See if it's an attribute reference
                 *      without the prefix.
                 */
-               slen = tmpl_afrom_attr_substr(ctx, NULL, out, &our_in, p_rules, t_rules);
+               slen = tmpl_afrom_attr_substr(ctx, NULL, out, &our_in, p_rules, &t_rules->attr);
                if (slen > 0) goto done_bareword;
                fr_assert(!*out);
 
@@ -2717,9 +2712,9 @@ ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                vpt = tmpl_alloc_null(ctx);
 
                if (!t_rules->at_runtime) {
-                       slen = xlat_tokenize(vpt, &head, &flags, &our_in, p_rules, t_rules);
+                       slen = xlat_tokenize(vpt, &head, &flags, &our_in, p_rules, &t_rules->attr);
                } else {
-                       slen = xlat_tokenize_ephemeral(vpt, &head, t_rules->runtime_el,
+                       slen = xlat_tokenize_ephemeral(vpt, &head, t_rules->xlat.runtime_el,
                                                       &flags, &our_in, p_rules, t_rules);
                }
                if (!head) return slen;
@@ -2765,7 +2760,7 @@ ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                 *      FIXME - We need an ephemeral version of this
                 *      too.
                 */
-               slen = xlat_tokenize_argv(vpt, &head, &flags, &our_in, p_rules, t_rules);
+               slen = xlat_tokenize_argv(vpt, &head, &flags, &our_in, p_rules, &t_rules->attr);
                if (slen < 0) {
                        fr_sbuff_advance(&our_in, slen * -1);
                        talloc_free(vpt);
@@ -2788,7 +2783,7 @@ ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
 
                vpt = tmpl_alloc_null(ctx);
 
-               slen = xlat_tokenize(vpt, &head, &flags, &our_in, p_rules, t_rules);
+               slen = xlat_tokenize(vpt, &head, &flags, &our_in, p_rules, &t_rules->attr);
                if (!head) return slen;
 
                /*
@@ -2801,7 +2796,6 @@ ssize_t tmpl_afrom_substr(TALLOC_CTX *ctx, tmpl_t **out,
                 *      The caller will need to do the compilation
                 *      after we return.
                 */
-
                if (xlat_to_string(vpt, &str, &head)) {
                        tmpl_init(vpt, TMPL_TYPE_REGEX_UNCOMPILED, quote, fr_sbuff_start(&our_in), slen);
                        vpt->data.unescaped = str;      /* Store the unescaped string for compilation later */
@@ -2850,8 +2844,6 @@ tmpl_t *tmpl_copy(TALLOC_CTX *ctx, tmpl_t const *in)
        tmpl_t *vpt;
 
        MEM(vpt = tmpl_alloc(ctx, in->type, in->quote, in->name, in->len));
-       vpt->cast = in->cast;
-       vpt->enumv = in->enumv;
        vpt->rules = in->rules;
 
        /*
@@ -3011,7 +3003,7 @@ int tmpl_cast_set(tmpl_t *vpt, fr_type_t dst_type)
                 */
        check_types:
                if (src_type == dst_type) {
-                       vpt->cast = FR_TYPE_NULL;
+                       tmpl_rules_cast(vpt) = FR_TYPE_NULL;
                        return 0;
                }
 
@@ -3025,7 +3017,7 @@ int tmpl_cast_set(tmpl_t *vpt, fr_type_t dst_type)
        }
 
 done:
-       vpt->cast = dst_type;
+       vpt->rules.data.cast = dst_type;
        return 0;
 }
 
@@ -3188,7 +3180,7 @@ int tmpl_cast_in_place(tmpl_t *vpt, fr_type_t type, fr_dict_attr_t const *enumv)
 
        case TMPL_TYPE_ATTR:    /* FIXME - We should check cast compatibility with resolved attrs */
        case TMPL_TYPE_ATTR_UNRESOLVED:
-               vpt->cast = type;
+               vpt->rules.data.cast = type;
                break;
 
        default:
@@ -3222,7 +3214,7 @@ static inline CC_HINT(always_inline) int tmpl_attr_resolve(tmpl_t *vpt, tmpl_res
 
        TMPL_VERIFY(vpt);
 
-       dict_def = vpt->rules.dict_def;
+       dict_def = vpt->rules.attr.dict_def;
        if (!tr_rules->dict_def || tr_rules->force_dict_def) dict_def = tr_rules->dict_def;
 
        /*
@@ -3240,8 +3232,8 @@ static inline CC_HINT(always_inline) int tmpl_attr_resolve(tmpl_t *vpt, tmpl_res
                                                         &FR_SBUFF_IN(ar->ar_unresolved,
                                                                      talloc_array_length(ar->ar_unresolved) - 1),
                                                         NULL,
-                                                        !vpt->rules.disallow_internal,
-                                                        vpt->rules.allow_foreign);
+                                                        !vpt->rules.attr.disallow_internal,
+                                                        vpt->rules.attr.allow_foreign);
                if (!da) return -2;     /* Can't resolve, maybe the caller can resolve later */
 
                ar->ar_type = TMPL_ATTR_TYPE_NORMAL;
@@ -3252,7 +3244,7 @@ static inline CC_HINT(always_inline) int tmpl_attr_resolve(tmpl_t *vpt, tmpl_res
                 *      Record the dictionary that was
                 *      successfully used for resolution.
                 */
-               vpt->rules.dict_def = tr_rules->dict_def;
+               vpt->rules.attr.dict_def = tr_rules->dict_def;
 
                /*
                 *      Reach into the next reference
@@ -3298,7 +3290,7 @@ static inline CC_HINT(always_inline) int tmpl_attr_resolve(tmpl_t *vpt, tmpl_res
                 */
                if (!da) {
                        prev = tmpl_attr_list_prev(&vpt->data.attribute.ar, ar);
-                       if (!vpt->rules.disallow_internal && prev && (prev->ar_da->type == FR_TYPE_GROUP)) {
+                       if (!vpt->rules.attr.disallow_internal && prev && (prev->ar_da->type == FR_TYPE_GROUP)) {
                                (void)fr_dict_attr_by_name_substr(NULL,
                                                                  &da,
                                                                  fr_dict_root(fr_dict_internal()),
@@ -3392,7 +3384,7 @@ int tmpl_xlat_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules)
 
 /** Attempt to resolve functions and attributes in xlats and attribute references
  *
- * @note If resolution is successful, the rules->dict_def field will be modified to
+ * @note If resolution is successful, the rules->attr.dict_def field will be modified to
  *      reflect the dictionary resolution was successful in.
  *
  * @param[in,out]      vpt             to resolve.  Should be of type TMPL_TYPE_XLAT_UNRESOLVED
@@ -3429,7 +3421,7 @@ int tmpl_resolve(tmpl_t *vpt, tmpl_res_rules_t const *tr_rules)
         *      Convert unresolved tmpls into literal string values.
         */
        } else if (tmpl_is_unresolved(vpt)) {
-               fr_type_t dst_type = vpt->cast;
+               fr_type_t dst_type = tmpl_rules_cast(vpt);
 
                if (fr_type_is_null(dst_type)) dst_type = FR_TYPE_STRING;       /* Default to strings */
 
index a0e2a7b0018b02d6065a45f04e05db9b3b94646f..30086d82e35835224837e85d72e562b45a88da04 100644 (file)
@@ -269,25 +269,29 @@ int pairlist_read(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *file, PAIR
        relative_map = NULL;
 
        lhs_rules = (tmpl_rules_t) {
-               .dict_def = dict,
-               .request_def = REQUEST_CURRENT,
-               .prefix = TMPL_ATTR_REF_PREFIX_NO,
-               .disallow_qualifiers = true, /* for now, until more tests are made */
+               .attr = {
+                       .dict_def = dict,
+                       .request_def = REQUEST_CURRENT,
+                       .prefix = TMPL_ATTR_REF_PREFIX_NO,
+                       .disallow_qualifiers = true, /* for now, until more tests are made */
 
-               /*
-                *      Otherwise the tmpl code returns 0 when asked
-                *      to parse unknown names.  So we say "please
-                *      parse unknown names as unresolved attributes",
-                *      and then do a second pass to complain that the
-                *      thing isn't known.
-                */
-               .allow_unresolved = true,
+                       /*
+                        *      Otherwise the tmpl code returns 0 when asked
+                        *      to parse unknown names.  So we say "please
+                        *      parse unknown names as unresolved attributes",
+                        *      and then do a second pass to complain that the
+                        *      thing isn't known.
+                        */
+                       .allow_unresolved = true
+               }
        };
        rhs_rules = (tmpl_rules_t) {
-               .dict_def = dict,
-               .request_def = REQUEST_CURRENT,
-               .prefix = TMPL_ATTR_REF_PREFIX_YES,
-               .disallow_qualifiers = true, /* for now, until rlm_files supports it */
+               .attr = {
+                       .dict_def = dict,
+                       .request_def = REQUEST_CURRENT,
+                       .prefix = TMPL_ATTR_REF_PREFIX_YES,
+                       .disallow_qualifiers = true, /* for now, until rlm_files supports it */
+               }
        };
 
        while (true) {
@@ -381,7 +385,7 @@ int pairlist_read(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *file, PAIR
                }
                t->name = q;
 
-               lhs_rules.list_def = PAIR_LIST_CONTROL;
+               lhs_rules.attr.list_def = PAIR_LIST_CONTROL;
                comma = false;
 
 check_item:
@@ -535,7 +539,7 @@ setup_reply:
                /*
                 *      Setup the reply items.
                 */
-               lhs_rules.list_def = PAIR_LIST_REPLY;
+               lhs_rules.attr.list_def = PAIR_LIST_REPLY;
                comma = false;
 
 reply_item:
index 42d81d595679084403001af2585881884e7cea88..856657718c7c170aecbd6b467d181408ee805512 100644 (file)
@@ -735,8 +735,8 @@ static int process_instantiate(CONF_SECTION *server_cs, dl_module_inst_t *dl_ins
                tmpl_rules_t            parse_rules;
 
                memset(&parse_rules, 0, sizeof(parse_rules));
-               parse_rules.dict_def = dict;
-               fr_assert(parse_rules.dict_def != NULL);
+               parse_rules.attr.dict_def = dict;
+               fr_assert(parse_rules.attr.dict_def != NULL);
 
                if (virtual_server_compile_sections(server_cs, process->compile_list, &parse_rules,
                                                    dl_inst->data) < 0) {
index 58b269b658e5db5e12c83ee79bf0316982ea5432..ac2231c6571ee30962772e9c08e4d40643b1ce7c 100644 (file)
@@ -200,16 +200,24 @@ static const unlang_actions_t default_actions[MOD_COUNT] =
        }
 };
 
-static inline CC_HINT(always_inline) int unlang_rules_verify(tmpl_rules_t const *rules)
+static inline CC_HINT(always_inline) int unlang_attr_rules_verify(tmpl_attr_rules_t const *rules)
 {
        if (!fr_cond_assert_msg(rules->dict_def, "No protocol dictionary set")) return -1;
-       if (!fr_cond_assert_msg(rules->dict_def != fr_dict_internal(), "rules->dict_def must not be the internal dictionary")) return -1;
-       if (!fr_cond_assert_msg(!rules->allow_foreign, "rules->allow_foreign must be false")) return -1;
-       if (!fr_cond_assert_msg(!rules->at_runtime, "rules->at_runtime must be false")) return -1;
+       if (!fr_cond_assert_msg(rules->dict_def != fr_dict_internal(), "rules->attr.dict_def must not be the internal dictionary")) return -1;
+       if (!fr_cond_assert_msg(!rules->allow_foreign, "rules->attr.allow_foreign must be false")) return -1;
 
        return 0;
 }
 
+static inline CC_HINT(always_inline) int unlang_rules_verify(tmpl_rules_t const *rules)
+{
+       if (!fr_cond_assert_msg(!rules->at_runtime, "rules->at_runtime must be false")) return -1;
+       return unlang_attr_rules_verify(&rules->attr);
+}
+
+#if 0
+#define ATTR_RULES_VERIFY(_rules) if (unlang_attr_rules_verify(_rules) < 0) return NULL;
+#endif
 #define RULES_VERIFY(_rules) if (unlang_rules_verify(_rules) < 0) return NULL;
 
 static bool pass2_fixup_tmpl(TALLOC_CTX *ctx, tmpl_t **vpt_p, CONF_ITEM const *ci, fr_dict_t const *dict)
@@ -222,7 +230,7 @@ static bool pass2_fixup_tmpl(TALLOC_CTX *ctx, tmpl_t **vpt_p, CONF_ITEM const *c
         *      We may now know the correct dictionary
         *      where we didn't before...
         */
-       if (!vpt->rules.dict_def) tmpl_set_dict_def(vpt, dict);
+       if (!vpt->rules.attr.dict_def) tmpl_set_dict_def(vpt, dict);
 
        /*
         *      Convert virtual &Attr-Foo to "%{Attr-Foo}"
@@ -421,7 +429,9 @@ static bool pass2_fixup_cond_map(fr_cond_t *c, CONF_ITEM *ci, fr_dict_t const *d
                                         T_DOUBLE_QUOTED_STRING,
                                         NULL,
                                         &(tmpl_rules_t){
-                                               .allow_unknown = true
+                                               .attr = {
+                                                       .allow_unknown = true
+                                               }
                                         });
                if (!vpt) {
                        char *spaces, *text;
@@ -489,7 +499,7 @@ static bool pass2_fixup_cond_map(fr_cond_t *c, CONF_ITEM *ci, fr_dict_t const *d
                return false;
        }
 
-       if (c->data.map->lhs->cast != FR_TYPE_NULL) {
+       if (tmpl_rules_cast(c->data.map->lhs) != FR_TYPE_NULL) {
                cf_log_err(map->ci, "Cannot cast virtual attribute %s to %s", map->lhs->name,
                           fr_table_str_by_value(fr_value_box_type_table, c->data.map->lhs->type, "<INVALID>"));
                return false;
@@ -532,13 +542,13 @@ static bool pass2_fixup_map(map_t *map, tmpl_rules_t const *rules, fr_dict_attr_
                 *      FIXME: compile to attribute && handle
                 *      the conversion in map_to_vp().
                 */
-               if (!pass2_fixup_tmpl(map, &map->lhs, map->ci, rules->dict_def)) {
+               if (!pass2_fixup_tmpl(map, &map->lhs, map->ci, rules->attr.dict_def)) {
                        return false;
                }
        }
 
        if (tmpl_is_exec(map->lhs)) {
-               if (!pass2_fixup_tmpl(map, &map->lhs, map->ci, rules->dict_def)) {
+               if (!pass2_fixup_tmpl(map, &map->lhs, map->ci, rules->attr.dict_def)) {
                        return false;
                }
        }
@@ -547,7 +557,7 @@ static bool pass2_fixup_map(map_t *map, tmpl_rules_t const *rules, fr_dict_attr_
         *      Deal with undefined attributes now.
         */
        if (tmpl_is_attr_unresolved(map->lhs)) {
-               if (!pass2_fixup_tmpl(map, &map->lhs, map->ci, rules->dict_def)) return false;
+               if (!pass2_fixup_tmpl(map, &map->lhs, map->ci, rules->attr.dict_def)) return false;
        }
 
        /*
@@ -570,7 +580,7 @@ static bool pass2_fixup_map(map_t *map, tmpl_rules_t const *rules, fr_dict_attr_
                         *      FIXME: compile to attribute && handle
                         *      the conversion in map_to_vp().
                         */
-                       if (!pass2_fixup_tmpl(map, &map->rhs, map->ci, rules->dict_def)) {
+                       if (!pass2_fixup_tmpl(map, &map->rhs, map->ci, rules->attr.dict_def)) {
                                return false;
                        }
                }
@@ -578,11 +588,11 @@ static bool pass2_fixup_map(map_t *map, tmpl_rules_t const *rules, fr_dict_attr_
                fr_assert(!tmpl_is_regex_xlat_unresolved(map->rhs));
 
                if (tmpl_is_attr_unresolved(map->rhs)) {
-                       if (!pass2_fixup_tmpl(map, &map->rhs, map->ci, rules->dict_def)) return false;
+                       if (!pass2_fixup_tmpl(map, &map->rhs, map->ci, rules->attr.dict_def)) return false;
                }
 
                if (tmpl_is_exec(map->rhs)) {
-                       if (!pass2_fixup_tmpl(map, &map->rhs, map->ci, rules->dict_def)) {
+                       if (!pass2_fixup_tmpl(map, &map->rhs, map->ci, rules->attr.dict_def)) {
                                return false;
                        }
                }
@@ -670,7 +680,7 @@ static bool pass2_fixup_map_rhs(unlang_group_t *g, tmpl_rules_t const *rules)
        if (!gext->vpt) return true;
 
        return pass2_fixup_tmpl(map_list_head(&gext->map)->ci, &gext->vpt,
-                               cf_section_to_item(g->cs), rules->dict_def);
+                               cf_section_to_item(g->cs), rules->attr.dict_def);
 }
 
 static void unlang_dump(unlang_t *instruction, int depth)
@@ -1314,7 +1324,7 @@ static unlang_t *compile_map(unlang_t *parent, unlang_compile_t *unlang_ctx, CON
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
+       t_rules.attr.allow_unknown = true;
        RULES_VERIFY(&t_rules);
 
        modules = cf_section_find(cf_root(cs), "modules", NULL);
@@ -1445,7 +1455,7 @@ static unlang_t *compile_update(unlang_t *parent, unlang_compile_t *unlang_ctx,
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
+       t_rules.attr.allow_unknown = true;
        RULES_VERIFY(&t_rules);
 
        g = group_allocate(parent, cs, &update_ext);
@@ -1504,7 +1514,7 @@ static unlang_t *compile_filter(unlang_t *parent, unlang_compile_t *unlang_ctx,
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
+       t_rules.attr.allow_unknown = true;
        RULES_VERIFY(&t_rules);
 
        g = group_allocate(parent, cs, &filter_ext);
@@ -1663,8 +1673,8 @@ static unlang_t *compile_edit_section(unlang_t *parent, unlang_compile_t *unlang
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
-       t_rules.list_as_attr = true;
+       t_rules.attr.allow_unknown = true;
+       t_rules.attr.list_as_attr = true;
        RULES_VERIFY(&t_rules);
 
        c = *prev;
@@ -1700,7 +1710,7 @@ static unlang_t *compile_edit_section(unlang_t *parent, unlang_compile_t *unlang
 
        name = cf_section_name1(cs);
 
-       slen = tmpl_afrom_attr_str(map, NULL, &map->lhs, name, &t_rules);
+       slen = tmpl_afrom_attr_str(map, NULL, &map->lhs, name, &t_rules.attr);
        if (slen <= 0) {
                cf_log_err(cs, "Failed parsing list reference %s", name);
        fail:
@@ -1755,8 +1765,8 @@ static unlang_t *compile_edit_pair(unlang_t *parent, unlang_compile_t *unlang_ct
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
-       t_rules.list_as_attr = true;
+       t_rules.attr.allow_unknown = true;
+       t_rules.attr.list_as_attr = true;
        RULES_VERIFY(&t_rules);
 
        c = *prev;
@@ -2465,7 +2475,7 @@ static unlang_t *compile_switch(unlang_t *parent, unlang_compile_t *unlang_ctx,
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
+       t_rules.attr.allow_unknown = true;
        RULES_VERIFY(&t_rules);
 
        name2 = cf_section_name2(cs);
@@ -2519,7 +2529,7 @@ static unlang_t *compile_switch(unlang_t *parent, unlang_compile_t *unlang_ctx,
         *      This is so that compile_case() can do attribute type
         *      checks / casts against us.
         */
-       if (!pass2_fixup_tmpl(g, &gext->vpt, cf_section_to_item(cs), unlang_ctx->rules->dict_def)) {
+       if (!pass2_fixup_tmpl(g, &gext->vpt, cf_section_to_item(cs), unlang_ctx->rules->attr.dict_def)) {
        error:
                talloc_free(g);
                return NULL;
@@ -2548,8 +2558,8 @@ static unlang_t *compile_switch(unlang_t *parent, unlang_compile_t *unlang_ctx,
        }
 
        type = FR_TYPE_STRING;
-       if (gext->vpt->cast) {
-               type = gext->vpt->cast;
+       if (tmpl_rules_cast(gext->vpt)) {
+               type = tmpl_rules_cast(gext->vpt);
 
        } else if (tmpl_is_attr(gext->vpt)) {
                type = tmpl_da(gext->vpt)->type;
@@ -2677,7 +2687,7 @@ static unlang_t *compile_case(unlang_t *parent, unlang_compile_t *unlang_ctx, CO
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
+       t_rules.attr.allow_unknown = true;
        RULES_VERIFY(&t_rules);
 
        if (!parent || (parent->type != UNLANG_TYPE_SWITCH)) {
@@ -2728,7 +2738,7 @@ static unlang_t *compile_case(unlang_t *parent, unlang_compile_t *unlang_ctx, CO
                 *      "switch" tmpl.
                 */
                if (tmpl_is_unresolved(vpt)) {
-                       fr_type_t cast_type = switch_gext->vpt->cast;
+                       fr_type_t cast_type = tmpl_rules_cast(switch_gext->vpt);
                        fr_dict_attr_t const *da = NULL;
 
                        if (tmpl_is_attr(switch_gext->vpt)) da = tmpl_da(switch_gext->vpt);
@@ -2801,7 +2811,7 @@ static unlang_t *compile_foreach(unlang_t *parent, unlang_compile_t *unlang_ctx,
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
+       t_rules.attr.allow_unknown = true;
        RULES_VERIFY(&t_rules);
 
        name2 = cf_section_name2(cs);
@@ -3054,7 +3064,7 @@ static unlang_t *compile_if_subsection(unlang_t *parent, unlang_compile_t *unlan
                        case COND_TYPE_TMPL:
                                fr_assert(!tmpl_is_regex_xlat_unresolved(leaf->data.vpt));
                                if (!pass2_fixup_tmpl(leaf, &leaf->data.vpt, cf_section_to_item(cs),
-                                                     unlang_ctx->rules->dict_def)) return false;
+                                                     unlang_ctx->rules->attr.dict_def)) return false;
                                break;
 
                        /*
@@ -3062,7 +3072,7 @@ static unlang_t *compile_if_subsection(unlang_t *parent, unlang_compile_t *unlan
                         */
                        case COND_TYPE_MAP:
                                if (!pass2_fixup_cond_map(leaf, cf_section_to_item(cs),
-                                                         unlang_ctx->rules->dict_def)) return false;
+                                                         unlang_ctx->rules->attr.dict_def)) return false;
                                break;
 
                        default:
@@ -3216,7 +3226,7 @@ static unlang_t *compile_load_balance_subsection(unlang_t *parent, unlang_compil
         *      We allow unknown attributes here.
         */
        t_rules = *(unlang_ctx->rules);
-       t_rules.allow_unknown = true;
+       t_rules.attr.allow_unknown = true;
        RULES_VERIFY(&t_rules);
 
        /*
@@ -3283,7 +3293,7 @@ static unlang_t *compile_load_balance_subsection(unlang_t *parent, unlang_compil
                /*
                 *      Fixup the templates
                 */
-               if (!pass2_fixup_tmpl(g, &gext->vpt, cf_section_to_item(cs), unlang_ctx->rules->dict_def)) {
+               if (!pass2_fixup_tmpl(g, &gext->vpt, cf_section_to_item(cs), unlang_ctx->rules->attr.dict_def)) {
                        talloc_free(g);
                        return NULL;
                }
@@ -3429,7 +3439,7 @@ static unlang_t *compile_subrequest(unlang_t *parent, unlang_compile_t *unlang_c
         */
        name2 = cf_section_name2(cs);
        if (!name2) {
-               dict = unlang_ctx->rules->dict_def;
+               dict = unlang_ctx->rules->attr.dict_def;
                packet_name = name2 = unlang_ctx->section_name2;
                goto get_packet_type;
        }
@@ -3444,7 +3454,7 @@ static unlang_t *compile_subrequest(unlang_t *parent, unlang_compile_t *unlang_c
 
                slen = tmpl_afrom_attr_substr(parent, NULL, &vpt,
                                              &FR_SBUFF_IN(name2, talloc_array_length(name2) - 1),
-                                             NULL, unlang_ctx->rules);
+                                             NULL, &unlang_ctx->rules->attr);
                if (slen <= 0) {
                        cf_log_perr(cs, "Invalid argument to 'subrequest', failed parsing packet-type");
                        return NULL;
@@ -3466,7 +3476,7 @@ static unlang_t *compile_subrequest(unlang_t *parent, unlang_compile_t *unlang_c
                        return NULL;
                }
 
-               dict = unlang_ctx->rules->dict_def;
+               dict = unlang_ctx->rules->attr.dict_def;
                packet_name = NULL;
                goto get_packet_type;
        }
@@ -3478,7 +3488,7 @@ static unlang_t *compile_subrequest(unlang_t *parent, unlang_compile_t *unlang_c
         */
        p = strchr(name2, '.');
        if (!p) {
-               dict = unlang_ctx->rules->dict_def;
+               dict = unlang_ctx->rules->attr.dict_def;
                packet_name = name2;
 
        } else {
@@ -3585,8 +3595,8 @@ get_packet_type:
 
        t_rules = *unlang_ctx->rules;
        t_rules.parent = unlang_ctx->rules;
-       t_rules.dict_def = dict;
-       t_rules.allow_foreign = false;
+       t_rules.attr.dict_def = dict;
+       t_rules.attr.allow_foreign = false;
 
        /*
         *      Copy over the compilation context.  This is mostly
@@ -3674,9 +3684,9 @@ static unlang_t *compile_call(unlang_t *parent, unlang_compile_t *unlang_ctx, CO
                return NULL;
        }
        if ((dict != fr_dict_internal()) && fr_dict_internal() &&
-           unlang_ctx->rules->dict_def && (unlang_ctx->rules->dict_def != dict)) {
+           unlang_ctx->rules->attr.dict_def && (unlang_ctx->rules->attr.dict_def != dict)) {
                cf_log_err(cs, "Cannot call server %s with namespace '%s' from namespaces '%s' - they have incompatible protocols",
-                          server, fr_dict_root(dict)->name, fr_dict_root(unlang_ctx->rules->dict_def)->name);
+                          server, fr_dict_root(dict)->name, fr_dict_root(unlang_ctx->rules->attr.dict_def)->name);
                return NULL;
        }
 
@@ -3745,7 +3755,7 @@ static unlang_t *compile_caller(unlang_t *parent, unlang_compile_t *unlang_ctx,
         */
        memcpy(&parent_rules, unlang_ctx->rules, sizeof(parent_rules));
        memcpy(&t_rules, unlang_ctx->rules, sizeof(t_rules));
-       parent_rules.dict_def = dict;
+       parent_rules.attr.dict_def = dict;
        t_rules.parent = &parent_rules;
 
        /*
@@ -3973,13 +3983,13 @@ static unlang_t *compile_module(unlang_t *parent, unlang_compile_t *unlang_ctx,
        /*
         *      Can't use "chap" in "dhcp".
         */
-       if (inst->module->dict && *inst->module->dict && unlang_ctx->rules && unlang_ctx->rules->dict_def &&
-           (unlang_ctx->rules->dict_def != fr_dict_internal()) &&
-           (*(inst->module->dict) != unlang_ctx->rules->dict_def)) {
+       if (inst->module->dict && *inst->module->dict && unlang_ctx->rules && unlang_ctx->rules->attr.dict_def &&
+           (unlang_ctx->rules->attr.dict_def != fr_dict_internal()) &&
+           (*(inst->module->dict) != unlang_ctx->rules->attr.dict_def)) {
                cf_log_err(ci, "The \"%s\" module can only used with 'namespace = %s'.  It cannot be used with 'namespace = %s'.",
                           inst->module->name,
                           fr_dict_root(*inst->module->dict)->name,
-                          fr_dict_root(unlang_ctx->rules->dict_def)->name);
+                          fr_dict_root(unlang_ctx->rules->attr.dict_def)->name);
                return NULL;
        }
 
index fe1b549322fdef8a562e6bba5c17c1fb6f948256..64f4d72d60db8324d25ec226a41a2413ca955dfa 100644 (file)
@@ -88,7 +88,7 @@ static int templatize_lhs(TALLOC_CTX *ctx, edit_result_t *out, request_t *reques
         *      anything else.
         */
        slen = tmpl_afrom_attr_str(ctx, NULL, &out->to_free, box->vb_strvalue,
-                                  &(tmpl_rules_t){
+                                  &(tmpl_attr_rules_t){
                                           .dict_def = request->dict,
                                           .prefix = TMPL_ATTR_REF_PREFIX_NO
                                   });
index a16096f071e15de7e8b49147e3a70158cfff193e..0518a1d463ca691c9a148209ff681c86f93e3691 100644 (file)
@@ -291,16 +291,20 @@ int               xlat_flatten_compiled_argv(TALLOC_CTX *ctx, xlat_exp_t const ***argv, xlat_
 
 bool           xlat_async_required(xlat_exp_t const *xlat);
 
+
+ssize_t                xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
+                                        fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules);
+
 ssize_t                xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_t **head,
                                        fr_event_list_t *el,
                                        xlat_flags_t *flags, fr_sbuff_t *in,
                                        fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
 
 ssize_t        xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
+                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules);
 
 ssize_t                xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                             fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
+                             fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules);
 
 ssize_t                xlat_print(fr_sbuff_t *in, xlat_exp_t const *node, fr_sbuff_escape_rules_t const *e_rules);
 
@@ -330,9 +334,6 @@ int         xlat_func_args(xlat_t *xlat, xlat_arg_parser_t const args[]) CC_HINT(nonnul
 
 int            xlat_func_mono(xlat_t *xlat, xlat_arg_parser_t const *arg) CC_HINT(nonnull);
 
-ssize_t                xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                                        fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
-
 /** Set a callback for global instantiation of xlat functions
  *
  * @param[in] _xlat            function to set the callback for (as returned by xlat_register).
index 02f33a234492d57492b0c91ed345a5575377428c..ccca6acc4b8cf7597108c38c1f4642c3ad4bd516 100644 (file)
@@ -76,7 +76,7 @@ int xlat_fmt_get_vp(fr_pair_t **out, request_t *request, char const *name)
        *out = NULL;
 
        if (tmpl_afrom_attr_str(request, NULL, &vpt, name,
-                               &(tmpl_rules_t){
+                               &(tmpl_attr_rules_t){
                                        .dict_def = request->dict,
                                        .prefix = TMPL_ATTR_REF_PREFIX_AUTO
                                }) <= 0) return -4;
@@ -1004,7 +1004,7 @@ static xlat_action_t xlat_func_debug_attr(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcur
        fmt = attr->vb_strvalue;
 
        if (tmpl_afrom_attr_str(request, NULL, &vpt, fmt,
-                               &(tmpl_rules_t){
+                               &(tmpl_attr_rules_t){
                                        .dict_def = request->dict,
                                        .prefix = TMPL_ATTR_REF_PREFIX_AUTO
                                }) <= 0) {
@@ -1375,8 +1375,10 @@ static xlat_action_t xlat_func_map(TALLOC_CTX *ctx, fr_dcursor_t *out,
        fr_value_box_t  *vb;
 
        tmpl_rules_t    attr_rules = {
-               .dict_def = request->dict,
-               .prefix = TMPL_ATTR_REF_PREFIX_AUTO
+               .attr = {
+                       .dict_def = request->dict,
+                       .prefix = TMPL_ATTR_REF_PREFIX_AUTO
+               }
        };
 
        if (map_afrom_attr_str(request, &map, fmt_vb->vb_strvalue, &attr_rules, &attr_rules) < 0) {
@@ -1584,12 +1586,16 @@ static xlat_action_t xlat_func_eval(TALLOC_CTX *ctx, fr_dcursor_t *out,
        if (xlat_tokenize_ephemeral(rctx,
                                    &rctx->ex, unlang_interpret_event_list(request), &flags,
                                    &FR_SBUFF_IN(arg->vb_strvalue, arg->vb_length),
-                                   &(fr_sbuff_parse_rules_t){ .escapes = &escape_rules },
+                                   &(fr_sbuff_parse_rules_t){
+                                       .escapes = &escape_rules
+                                   },
                                    &(tmpl_rules_t){
-                                       .allow_unknown = false,
-                                       .allow_unresolved = false,
-                                       .allow_foreign = false,
-                                       .dict_def = request->dict,
+                                       .attr = {
+                                               .allow_unknown = false,
+                                               .allow_unresolved = false,
+                                               .allow_foreign = false,
+                                               .dict_def = request->dict
+                                       },
                                        .at_runtime = true
                                    }) < 0) {
                RPEDEBUG("Failed parsing expansion");
@@ -2339,7 +2345,7 @@ static xlat_action_t xlat_func_pairs(TALLOC_CTX *ctx, fr_dcursor_t *out,
        fr_pair_t *vp;
 
        if (tmpl_afrom_attr_str(ctx, NULL, &vpt, in_head->vb_strvalue,
-                               &(tmpl_rules_t){
+                               &(tmpl_attr_rules_t){
                                        .dict_def = request->dict,
                                        .prefix = TMPL_ATTR_REF_PREFIX_AUTO
                                }) <= 0) {
@@ -3394,7 +3400,7 @@ static xlat_action_t protocol_encode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
        memcpy(&tp_encode, xctx->inst, sizeof(tp_encode)); /* const issues */
 
        if (tmpl_afrom_attr_str(ctx, NULL, &vpt, in_head->vb_strvalue,
-                               &(tmpl_rules_t){
+                               &(tmpl_attr_rules_t){
                                        .dict_def = request->dict,
                                        .prefix = TMPL_ATTR_REF_PREFIX_AUTO
                                }) <= 0) {
index 5abbcd131020baec5f7abba1f6ba3e80641739c3..bee412f7568070b6bf8342b6d80c27fdbaf9cd77 100644 (file)
@@ -1520,7 +1520,12 @@ ssize_t _xlat_eval(TALLOC_CTX *ctx, char **out, size_t outlen, request_t *reques
         */
        len = xlat_tokenize_ephemeral(ctx, &node, unlang_interpret_event_list(request), NULL,
                                      &FR_SBUFF_IN(fmt, strlen(fmt)),
-                                     NULL, &(tmpl_rules_t){ .dict_def = request->dict });
+                                     NULL,
+                                     &(tmpl_rules_t){
+                                       .attr = {
+                                               .dict_def = request->dict
+                                       }
+                                     });
        if (len == 0) {
                if (*out) {
                        **out = '\0';
index de75451b56d854d2d948fbad035b0429b3a44a98..8451f9750c6427f4319e2f4ae310ea2c33ce6b5f 100644 (file)
@@ -477,7 +477,7 @@ static xlat_exp_t *xlat_expr_cast_alloc(TALLOC_CTX *ctx, fr_type_t type)
 }
 
 static ssize_t tokenize_expression(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *input,
-                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
+                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules,
                                   fr_token_t prev, fr_type_t type, fr_sbuff_parse_rules_t const *bracket_rules,
                                   fr_dict_attr_t const *da);
 
@@ -496,7 +496,7 @@ static ssize_t tokenize_expression(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flag
  *     int64_t.
  */
 static ssize_t tokenize_field(TALLOC_CTX *input_ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *input,
-                             fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
+                             fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules,
                              fr_type_t type, fr_sbuff_parse_rules_t const *bracket_rules, fr_dict_attr_t const *da)
 {
        ssize_t         slen;
@@ -701,7 +701,7 @@ check_more:
                         *      @todo - also update the escaping rules, depending on kind of string we have.
                         */
                        type = FR_TYPE_STRING;
-               } else {                        
+               } else {
                        type = FR_TYPE_INT64;
                }
        }
@@ -892,11 +892,11 @@ static size_t const expr_assignment_op_table_len = NUM_ELEMENTS(expr_assignment_
  *     A OP B
  */
 static ssize_t tokenize_expression(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *input,
-                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
+                                  fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules,
                                   fr_token_t prev, fr_type_t type, fr_sbuff_parse_rules_t const *bracket_rules,
                                   fr_dict_attr_t const *da)
 {
-       xlat_exp_t      *lhs = NULL, *rhs = NULL, *node;
+       xlat_exp_t      *lhs, *rhs = NULL, *node;
        xlat_t          *func = NULL;
        fr_token_t      op;
        ssize_t         slen;
@@ -1082,7 +1082,7 @@ static const fr_sbuff_term_t operator_terms = FR_SBUFF_TERMS(
 );
 
 ssize_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                                fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+                                fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules)
 {
        ssize_t slen;
        fr_sbuff_parse_rules_t *bracket_rules = NULL;
index d00aa778719a5ccd15564f9ea9785e414851906b..e5d967c8e6b76cfc31c5a956727aa8596895ddc1 100644 (file)
@@ -154,6 +154,8 @@ typedef struct {
        size_t          len;            //!< Length of the output string.
 } xlat_out_t;
 
+extern fr_dict_attr_t const    *attr_cast_base; /* for xlat_expr.c */
+
 /*
  *     Helper functions
  */
@@ -306,10 +308,10 @@ int               xlat_register_expressions(void);
  *     xlat_tokenize.c
  */
 int            xlat_tokenize_expansion(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                                       tmpl_rules_t const *t_rules);
+                                       tmpl_attr_rules_t const *t_rules);
 
 int            xlat_tokenize_function_args(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                                           tmpl_rules_t const *rules);
+                                           tmpl_attr_rules_t const *rules);
 
 
 #ifdef __cplusplus
index 5fe9e21a9db846cb71307406653d30948e34a92c..9b6ca9e05e24a6471b16f0f02844373bb3f85a88 100644 (file)
@@ -170,10 +170,10 @@ void xlat_exp_free(xlat_exp_t **head)
 
 static int xlat_tokenize_string(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags,
                                 fr_sbuff_t *in, bool brace,
-                                fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules);
+                                fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules);
 
 static inline int xlat_tokenize_alternation(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                                           tmpl_rules_t const *t_rules, bool func_args)
+                                           tmpl_attr_rules_t const *t_rules, bool func_args)
 {
        xlat_exp_t      *node;
 
@@ -310,7 +310,7 @@ int xlat_validate_function_mono(xlat_exp_t *node)
  */
 static inline int xlat_tokenize_function_mono(TALLOC_CTX *ctx, xlat_exp_t **head,
                                              xlat_flags_t *flags, fr_sbuff_t *in,
-                                             tmpl_rules_t const *rules)
+                                             tmpl_attr_rules_t const *rules)
 {
        xlat_exp_t              *node;
        xlat_t                  *func;
@@ -448,7 +448,7 @@ int xlat_validate_function_args(xlat_exp_t *node)
  */
 int xlat_tokenize_function_args(TALLOC_CTX *ctx, xlat_exp_t **head,
                                xlat_flags_t *flags, fr_sbuff_t *in,
-                               tmpl_rules_t const *rules)
+                               tmpl_attr_rules_t const *rules)
 {
        xlat_exp_t              *node;
        xlat_t                  *func;
@@ -569,7 +569,7 @@ static int xlat_resolve_virtual_attribute(xlat_exp_t *node, tmpl_t *vpt)
  *
  */
 static inline int xlat_tokenize_attribute(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                                         fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+                                         fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules)
 {
        ssize_t                 slen;
        tmpl_attr_error_t       err;
@@ -587,7 +587,7 @@ static inline int xlat_tokenize_attribute(TALLOC_CTX *ctx, xlat_exp_t **head, xl
         *      and instead are "virtual" attributes like
         *      Foreach-Variable-N.
         */
-       tmpl_rules_t             our_t_rules;
+       tmpl_attr_rules_t                our_t_rules;
 
        if (t_rules) {
                memcpy(&our_t_rules, t_rules, sizeof(our_t_rules));
@@ -694,7 +694,7 @@ done:
 }
 
 int xlat_tokenize_expansion(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                           tmpl_rules_t const *t_rules)
+                           tmpl_attr_rules_t const *t_rules)
 {
        size_t                  len;
        fr_sbuff_marker_t       s_m;
@@ -864,7 +864,7 @@ int xlat_tokenize_expansion(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *fl
  */
 static int xlat_tokenize_string(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags,
                                 fr_sbuff_t *in, bool brace,
-                                fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+                                fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules)
 {
        xlat_exp_t                      *node = NULL;
        size_t                          len;
@@ -1325,11 +1325,11 @@ ssize_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_t **head,
 
        if (t_rules) our_t_rules = *t_rules;
 
-       our_t_rules.runtime_el = el;
+       our_t_rules.xlat.runtime_el = el;
 
        fr_strerror_clear();    /* Clear error buffer */
        if (xlat_tokenize_string(ctx, head, flags, &our_in,
-                                false, p_rules, &our_t_rules) < 0) return -fr_sbuff_used(&our_in);
+                                false, p_rules, &our_t_rules.attr) < 0) return -fr_sbuff_used(&our_in);
 
        /*
         *      Zero length expansion, return a zero length node.
@@ -1369,7 +1369,7 @@ ssize_t xlat_tokenize_ephemeral(TALLOC_CTX *ctx, xlat_exp_t **head,
  *     - >0  on success which is the number of characters parsed.
  */
 ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                          fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+                          fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules)
 {
        fr_sbuff_t                      our_in = FR_SBUFF(in);
        ssize_t                         slen;
@@ -1541,7 +1541,7 @@ ssize_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *fla
  *     - < 0 the negative offset of the parse failure.
  */
 ssize_t xlat_tokenize(TALLOC_CTX *ctx, xlat_exp_t **head, xlat_flags_t *flags, fr_sbuff_t *in,
-                     fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules)
+                     fr_sbuff_parse_rules_t const *p_rules, tmpl_attr_rules_t const *t_rules)
 {
        fr_sbuff_t      our_in = FR_SBUFF(in);
        xlat_flags_t    tmp_flags = {};
index accc1edc1a5ff823eb9ff109495316576d2c1233..f44e4378bdfffc588452542507b8dccec9ca5f92 100644 (file)
@@ -841,7 +841,7 @@ xlat_action_t cache_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
        slen = tmpl_afrom_attr_substr(ctx, NULL, &target,
                                      &FR_SBUFF_IN(attr->vb_strvalue, attr->vb_length),
                                      NULL,
-                                     &(tmpl_rules_t){
+                                     &(tmpl_attr_rules_t){
                                                .dict_def = request->dict,
                                                .prefix = TMPL_ATTR_REF_PREFIX_AUTO
                                      });
@@ -1041,7 +1041,9 @@ static int mod_instantiate(module_inst_ctx_t const *mctx)
         */
        {
                tmpl_rules_t    parse_rules = {
-                       .allow_foreign = true   /* Because we don't know where we'll be called */
+                       .attr = {
+                               .allow_foreign = true   /* Because we don't know where we'll be called */
+                       }
                };
 
                map_list_init(&inst->maps);
index 45640b4086a39beb46bdad7e50de8a6851d60689..fafbf44a0aee19329d15975540ead2e7be04218f 100644 (file)
@@ -111,9 +111,11 @@ int cache_deserialize(rlm_cache_entry_t *c, fr_dict_t const *dict, char *in, ssi
        while (((size_t)(p - in)) < (size_t)inlen) {
                map_t   *map = NULL;
                tmpl_rules_t parse_rules = {
-                                       .dict_def = dict,
-                                       .prefix = TMPL_ATTR_REF_PREFIX_NO
-                               };
+                       .attr = {
+                               .dict_def = dict,
+                               .prefix = TMPL_ATTR_REF_PREFIX_NO
+                       }
+               };
 
                q = strchr(p, '\n');
                if (!q) break;  /* List should also be terminated with a \n */
index a0330543895b85f00f9b74fc153c7d1d327ef485..9357aee1923af29be174f427623ac5a7f6068c87 100644 (file)
@@ -758,7 +758,9 @@ static int mod_instantiate(module_inst_ctx_t const *mctx)
        int             lineno;
        FILE            *fp;
        tmpl_rules_t    parse_rules = {
-               .allow_foreign = true   /* Because we don't know where we'll be called */
+               .attr = {
+                       .allow_foreign = true   /* Because we don't know where we'll be called */
+               }
        };
        char buffer[8192];
 
index 458bfcbdbf3a3306cc85a9bb392b33225117452b..9caf02d2ee7cebfb962361e3e9903d2640aa9282 100644 (file)
@@ -243,9 +243,11 @@ static int mod_instantiate(module_inst_ctx_t const *mctx)
                                 &FR_SBUFF_IN(inst->program, strlen(inst->program)),
                                 T_BACK_QUOTED_STRING, NULL,
                                 &(tmpl_rules_t) {
-                                       .allow_foreign = true,
-                                       .allow_unresolved = false,
-                                       .allow_unknown = false
+                                       .attr = {
+                                               .allow_foreign = true,
+                                               .allow_unresolved = false,
+                                               .allow_unknown = false
+                                       }
                                 });
        if (!inst->tmpl) {
                char *spaces, *text;
index 974ae8da99a553dbeb467f831eac6c3325d1b56f..d84e89b18fc07e18af2bea11cda2d6dd2f213447 100644 (file)
@@ -217,7 +217,9 @@ static bool get_number(request_t *request, char const **string, int64_t *answer)
                slen = tmpl_afrom_attr_substr(request, NULL, &vpt,
                                              &FR_SBUFF_IN(p, strlen(p)),
                                              &p_rules,
-                                             &(tmpl_rules_t){ .dict_def = request->dict });
+                                             &(tmpl_attr_rules_t){
+                                               .dict_def = request->dict
+                                             });
                if (slen <= 0) {
                        RPEDEBUG("Failed parsing attribute name '%s'", p);
                        return false;
index 079f6cf71ae30c2e64cc84cb6d8e63709ba49f32..187073430d034617dfed213a554ca0a2f085fe36 100644 (file)
@@ -198,7 +198,9 @@ static xlat_action_t json_encode_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
                slen = tmpl_afrom_attr_substr(ctx, NULL, &vpt,
                                              &sbuff,
                                              &json_arg_parse_rules,
-                                             &(tmpl_rules_t){ .dict_def = request->dict });
+                                             &(tmpl_attr_rules_t){
+                                               .dict_def = request->dict
+                                             });
                if (slen <= 0) {
                        fr_sbuff_set(&sbuff, (size_t)(slen * -1));
                        REMARKER(fr_sbuff_start(&sbuff), fr_sbuff_used(&sbuff), "%s", fr_strerror());
index 4a722cb125c9b777d82a9fd9403c0f2c173fa13d..e848b1ec85247662212ef1f0707c005144e7d3ea 100644 (file)
@@ -2314,7 +2314,9 @@ if (inst->handle_config.tls_min_version_str) {
         */
        {
                tmpl_rules_t    parse_rules = {
-                       .allow_foreign = true   /* Because we don't know where we'll be called */
+                       .attr = {
+                               .allow_foreign = true   /* Because we don't know where we'll be called */
+                       }
                };
 
                update = cf_section_find(conf, "update", NULL);
index 474a63f1bcf559c6f5cbf70f8eea961e90eeffef..2abb1e4dcd2f37f0bb58efc4cb1f00c48bccf985 100644 (file)
@@ -524,9 +524,11 @@ static unlang_action_t CC_HINT(nonnull) mod_do_linelog(rlm_rcode_t *p_result, mo
                                         cf_pair_value_quote(cp),
                                         NULL,
                                         &(tmpl_rules_t){
-                                               .dict_def = request->dict,
-                                               .allow_unknown = true,
-                                               .allow_unresolved = false,
+                                               .attr = {
+                                                       .dict_def = request->dict,
+                                                       .allow_unknown = true,
+                                                       .allow_unresolved = false,
+                                               },
                                                .at_runtime = true
                                         });
                if (!vpt) {
index 12931d4a0bae6cd809b3eee57165e9f152f84d49..93fe9f4588f0a57967527b223c431f43496ce2e4 100644 (file)
@@ -324,7 +324,7 @@ static void mod_vptuple(TALLOC_CTX *ctx, module_ctx_t const *mctx, request_t *re
                }
 
                if (tmpl_afrom_attr_str(ctx, NULL, &dst, s1,
-                                       &(tmpl_rules_t){
+                                       &(tmpl_attr_rules_t){
                                                .dict_def = request->dict,
                                                .list_def = PAIR_LIST_REPLY
                                        }) <= 0) {
index 05306d361552a9b2f2e890feb4335712bfe1e72b..be60be909d361385733c1675db0dde226a841716 100644 (file)
@@ -344,7 +344,9 @@ static int status_check_update_parse(TALLOC_CTX *ctx, void *out, UNUSED void *pa
         */
        {
                tmpl_rules_t    parse_rules = {
-                       .allow_foreign = true   /* Because we don't know where we'll be called */
+                       .attr = {
+                               .allow_foreign = true   /* Because we don't know where we'll be called */
+                       }
                };
 
                rcode = map_afrom_cs(ctx, head, cs, &parse_rules, &parse_rules, unlang_fixup_update, NULL, 128);
index 5194ce89bf8902d75a348af7814963b7af38c4e9..73c0abf045e4cc36d54464c279645f379432f130 100644 (file)
@@ -736,7 +736,7 @@ static int rest_decode_post(UNUSED rlm_rest_t const *instance, UNUSED rlm_rest_s
                RDEBUG2("Parsing attribute \"%pV\"", fr_box_strvalue_len(name, curl_len));
 
                if (tmpl_afrom_attr_str(request, NULL, &dst, name,
-                                       &(tmpl_rules_t){
+                                       &(tmpl_attr_rules_t){
                                                .prefix = TMPL_ATTR_REF_PREFIX_NO,
                                                .dict_def = request->dict,
                                                .list_def = PAIR_LIST_REPLY
@@ -1024,7 +1024,7 @@ static int json_pair_alloc(rlm_rest_t const *instance, rlm_rest_section_t const
                RDEBUG2("Parsing attribute \"%s\"", name);
 
                if (tmpl_afrom_attr_str(request, NULL, &dst, name,
-                                       &(tmpl_rules_t){
+                                       &(tmpl_attr_rules_t){
                                                .prefix = TMPL_ATTR_REF_PREFIX_NO,
                                                .dict_def = request->dict,
                                                .list_def = PAIR_LIST_REPLY
index 513fe0b57bc9320390b1ee350c50eb29fee6f0c3..c81a85c64c8d3fb3f20f7fcce73b6a7fd0d45e18 100644 (file)
@@ -117,9 +117,11 @@ static int cf_table_parse_tmpl(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
        tmpl_t                  *vpt;
 
        static tmpl_rules_t     rules = {
-                                       .allow_unknown = true,
-                                       .allow_unresolved = true,
-                                       .allow_foreign = true
+                                       .attr = {
+                                               .allow_unknown = true,
+                                               .allow_unresolved = true,
+                                               .allow_foreign = true
+                                       }
                                };
 
        if (!tmpl) {
@@ -1054,10 +1056,12 @@ static int mod_instantiate(module_inst_ctx_t const *mctx)
         */
        {
                tmpl_rules_t    parse_rules = {
-                       .allow_foreign = true,  /* Because we don't know where we'll be called */
-                       .allow_unknown = true,
-                       .allow_unresolved = true,
-                       .prefix = TMPL_ATTR_REF_PREFIX_AUTO,
+                       .attr = {
+                               .allow_foreign = true,  /* Because we don't know where we'll be called */
+                               .allow_unknown = true,
+                               .allow_unresolved = true,
+                               .prefix = TMPL_ATTR_REF_PREFIX_AUTO,
+                       }
                };
 
                if (map_afrom_cs(inst, &inst->header_maps, header,