/*
* 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, ' ');
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);
}
{
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();
}
{
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);
* 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) {
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
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);
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);
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);
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();
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;
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)));
}
{
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)));
}
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);
// 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);
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);
/*
* 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;
}
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);
* 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)) {
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,
};
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]);
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
});
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;
*/
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);
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));
*/
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,
/*
* 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);
}
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;
* 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:
* 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;
* 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);
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 {
/*
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;
}
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 */
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;
* 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;
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
* @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)) {
/*
* 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.
* 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;
/*
* 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);
}
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;
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;
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;
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;
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".
*/
* 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;
}
}
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:
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,
*/
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;
}
* 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);
* 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());
* 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
}
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;
}
}
+/** 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
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);
}
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);
}
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",
(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");
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;
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.
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
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
};
} 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.
#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
*/
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,
/*
* 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",
}
}
- if (!vpt->rules.list_as_attr) {
+ if (!vpt->rules.attr.list_as_attr) {
/*
* Get the right list in the specified context
*/
/*
* 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
* 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 */
*/
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
* - 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)
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;
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;
* 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,
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;
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);
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;
};
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)
*/
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;
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;
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);
(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;
}
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");
* 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);
* 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
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;
* 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);
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;
* 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);
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;
/*
* 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 */
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;
/*
*/
check_types:
if (src_type == dst_type) {
- vpt->cast = FR_TYPE_NULL;
+ tmpl_rules_cast(vpt) = FR_TYPE_NULL;
return 0;
}
}
done:
- vpt->cast = dst_type;
+ vpt->rules.data.cast = dst_type;
return 0;
}
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:
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;
/*
&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;
* 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
*/
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()),
/** 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
* 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 */
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) {
}
t->name = q;
- lhs_rules.list_def = PAIR_LIST_CONTROL;
+ lhs_rules.attr.list_def = PAIR_LIST_CONTROL;
comma = false;
check_item:
/*
* Setup the reply items.
*/
- lhs_rules.list_def = PAIR_LIST_REPLY;
+ lhs_rules.attr.list_def = PAIR_LIST_REPLY;
comma = false;
reply_item:
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) {
}
};
-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)
* 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}"
T_DOUBLE_QUOTED_STRING,
NULL,
&(tmpl_rules_t){
- .allow_unknown = true
+ .attr = {
+ .allow_unknown = true
+ }
});
if (!vpt) {
char *spaces, *text;
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;
* 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;
}
}
* 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;
}
/*
* 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;
}
}
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;
}
}
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)
* 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);
* 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);
* 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);
* 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;
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:
* 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;
* 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);
* 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;
}
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;
* 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)) {
* "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);
* 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);
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;
/*
*/
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:
* 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);
/*
/*
* 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;
}
*/
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;
}
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;
return NULL;
}
- dict = unlang_ctx->rules->dict_def;
+ dict = unlang_ctx->rules->attr.dict_def;
packet_name = NULL;
goto get_packet_type;
}
*/
p = strchr(name2, '.');
if (!p) {
- dict = unlang_ctx->rules->dict_def;
+ dict = unlang_ctx->rules->attr.dict_def;
packet_name = name2;
} else {
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
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;
}
*/
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;
/*
/*
* 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;
}
* 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
});
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);
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).
*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;
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) {
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) {
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");
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) {
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) {
*/
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';
}
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);
* 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;
* @todo - also update the escaping rules, depending on kind of string we have.
*/
type = FR_TYPE_STRING;
- } else {
+ } else {
type = FR_TYPE_INT64;
}
}
* 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;
);
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;
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
*/
* 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
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;
*/
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;
*/
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;
*
*/
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;
* 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));
}
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;
*/
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;
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.
* - >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;
* - < 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 = {};
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
});
*/
{
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);
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 */
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];
&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;
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;
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());
*/
{
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);
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) {
}
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) {
*/
{
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);
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
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
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) {
*/
{
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,