* @param[in] ctx To allocate parsed environment in.
* @param[out] parsed Where to write parsed environment.
* @param[in] name Module name for error messages.
- * @param[in] namespace we're operating in.
+ * @param[in] t_rules controlling how the call env is parsed.
* @param[in] cs Module config.
* @param[in] rule to parse.
* @return
* - 0 on success;
* - <0 on failure;
*/
-static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char const *name, fr_dict_t const *namespace,
+static int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char const *name, tmpl_rules_t const *t_rules,
CONF_SECTION const *cs, call_env_parser_t const *rule) {
CONF_PAIR const *cp, *next;
call_env_parsed_t *call_env_parsed = NULL;
ssize_t count, multi_index;
- fr_type_t type;
while (rule->name) {
if (call_env_is_subsection(rule->flags)) {
*/
call_env_parsed_t *last = call_env_parsed_tail(parsed);
- if (rule->section.func(ctx, parsed, namespace, cf_section_to_item(subcs), rule) < 0) {
+ if (rule->section.func(ctx, parsed, t_rules, cf_section_to_item(subcs), rule) < 0) {
cf_log_perr(cs, "Failed parsing configuration section %s", rule->name);
talloc_free(call_env_parsed);
return -1;
goto next;
}
- if (call_env_parse(ctx, parsed, name, namespace, subcs, rule->section.subcs) < 0) return -1;
+ if (call_env_parse(ctx, parsed, name, t_rules, subcs, rule->section.subcs) < 0) return -1;
goto next;
}
* result structure.
*/
if (rule->pair.func) {
- if (unlikely(rule->pair.func(ctx, &call_env_parsed->data, namespace, cf_pair_to_item(to_parse), rule) < 0)) {
+ if (unlikely(rule->pair.func(ctx, &call_env_parsed->data, t_rules, cf_pair_to_item(to_parse), rule) < 0)) {
error:
cf_log_perr(to_parse, "Failed to parse configuration item '%s = %s'", rule->name, cf_pair_value(to_parse));
talloc_free(call_env_parsed);
} else {
tmpl_t *parsed_tmpl;
- type = rule->pair.cast_type;
-
if (tmpl_afrom_substr(call_env_parsed, &parsed_tmpl,
&FR_SBUFF_IN(cf_pair_value(to_parse), talloc_array_length(cf_pair_value(to_parse)) - 1),
- cf_pair_value_quote(to_parse), NULL, &(tmpl_rules_t){
- .cast = ((type == FR_TYPE_VOID) ? FR_TYPE_NULL : type),
- .attr = {
- .list_def = request_attr_request,
- .dict_def = namespace
- }
- }) < 0) {
+ cf_pair_value_quote(to_parse), NULL, t_rules) < 0) {
goto error;
}
call_env_parsed->data.tmpl = parsed_tmpl;
* @param[in] ctx to allocate the call_env_t in.
* @param[in] name Module name for error messages.
* @param[in] call_env_method containing the call_env_pair_t to evaluate against the specified CONF_SECTION.
- * @param[in] namespace to pass to the tmpl tokenizer when parsing pairs from the specified CONF_SECTION.
+ * @param[in] t_rules that control how call_env_pair_t are parsed.
* @param[in] cs to parse in the context of the call.
* @return
* - A new call_env_t on success.
* - NULL on failure.
*/
call_env_t *call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t const *call_env_method,
- fr_dict_t const *namespace, CONF_SECTION *cs)
+ tmpl_rules_t const *t_rules, CONF_SECTION *cs)
{
unsigned int count;
size_t names_len;
MEM(call_env = talloc_pooled_object(ctx, call_env_t, count * 4, (sizeof(call_env_parser_t) + sizeof(tmpl_t)) * count + names_len * 2));
call_env->method = call_env_method;
call_env_parsed_init(&call_env->parsed);
- if (call_env_parse(call_env, &call_env->parsed, name, namespace, cs, call_env_method->env) < 0) {
+ if (call_env_parse(call_env, &call_env->parsed, name, t_rules, cs, call_env_method->env) < 0) {
talloc_free(call_env);
return NULL;
}
*
* @param[in] ctx to allocate any data in.
* @param[out] out Where to write the result of parsing.
- * @param[in] namespace we're operating in.
+ * @param[in] t_rules we're parsing attributes with. Contains the default dictionary and nested 'caller' tmpl_rules_t.
* @param[in] ci The #CONF_SECTION or #CONF_PAIR to parse.
* @param[in] rule Parse rules - How the #CONF_PAIR or #CONF_SECTION should be converted.
* @return
* - 0 on success.
* - -1 on failure.
*/
-typedef int (*call_env_parse_pair_t)(TALLOC_CTX *ctx, void *out, fr_dict_t const *namespace, CONF_ITEM *ci, call_env_parser_t const *rule);
+typedef int (*call_env_parse_pair_t)(TALLOC_CTX *ctx, void *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_parser_t const *rule);
/** Callback for performing custom parsing of a #CONF_SECTION
*
*
* @param[in] ctx to allocate any data in.
* @param[out] out Where to write the result of parsing.
- * @param[in] namespace we're operating in.
+ * @param[in] t_rules we're parsing attributes with. Contains the default dictionary and nested 'caller' tmpl_rules_t.
* @param[in] ci The #CONF_SECTION or #CONF_PAIR to parse.
* @param[in] rule Parse rules - How the #CONF_PAIR or #CONF_SECTION should be converted.
* @return
* - 0 on success.
* - -1 on failure.
*/
-typedef int (*call_env_parse_section_t)(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, call_env_parser_t const *rule);
+typedef int (*call_env_parse_section_t)(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_parser_t const *rule);
/** Per method call config
*
* @{
*/
call_env_t *call_env_alloc(TALLOC_CTX *ctx, char const *name, call_env_method_t const *call_env_method,
- fr_dict_t const *namespace, CONF_SECTION *cs) CC_HINT(nonnull(3,4,5));
+ tmpl_rules_t const *rules, CONF_SECTION *cs) CC_HINT(nonnull(3,4,5));
/** @} */
#ifdef __cplusplus
inst->module->name, unlang_ctx->section_name1, unlang_ctx->section_name2);
single->call_env = call_env_alloc(single, single->self.name, method_env,
- unlang_ctx->rules ? unlang_ctx->rules->attr.dict_def : fr_dict_internal(),
+ unlang_ctx->rules,
inst->dl_inst->conf);
if (!single->call_env) {
error:
"Method environment for module %s, xlat %s declared, "
"but no inst_size set", call->func->mctx->inst->name, call->func->name);
+ /*
+ * FIXME - This is wrong, we should pass in the tmpl_rule_t
+ * from the compiler call. But it would be prohibitively
+ * memory inefficient to copy it on every xlat call, and it
+ * only exists for the duration of the compilation phase
+ * because many elements are stack allocated. The correct
+ * fix is to allocate all tmpl_rules_t on the heap.
+ * OR just bite the bullet and duplicate the whole nested
+ * rules structure for every xlat node.
+ *
+ * Because of this hack, outer. and parent. will not work
+ * within xlat call envs.
+ */
xi->call_env = call_env_alloc(xi, call->func->name, call->func->call_env_method,
- call->dict, call->func->mctx->inst->conf);
+ &(tmpl_rules_t){
+ .attr = {
+ .dict_def = call->dict,
+ .list_def = request_attr_request
+ }
+ }, call->func->mctx->inst->conf);
if (!xi->call_env) {
talloc_free(xi);
return NULL;
extern module_rlm_t rlm_cache;
-static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule);
+static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule);
static const conf_parser_t module_config[] = {
{ FR_CONF_OFFSET_TYPE_FLAGS("driver", FR_TYPE_VOID, 0, rlm_cache_t, driver_submodule), .dflt = "rbtree",
return 0;
}
-static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule)
+static int cache_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule)
{
CONF_SECTION *update = cf_item_to_section(ci);
call_env_parsed_t *parsed;
map_list_t *maps;
- tmpl_rules_t parse_rules = {
- .attr = {
- .dict_def = namespace,
- .list_def = request_attr_request,
- .allow_wildcard = true,
- .allow_foreign = true /* Because we don't know where we'll be called */
- }
- };
-
MEM(parsed = call_env_parsed_add(ctx, out,
&(call_env_parser_t){ FR_CALL_ENV_PARSE_ONLY_OFFSET("update", FR_TYPE_VOID, 0, cache_call_env_t, maps)}));
map_list_init(maps);
if (map_afrom_cs(maps, maps, update,
- &parse_rules, &parse_rules, cache_verify, NULL, MAX_ATTRMAP) < 0) {
+ t_rules, t_rules, cache_verify, NULL, MAX_ATTRMAP) < 0) {
error:
call_env_parsed_free(out, parsed);
return -1;
map_list_t *profile_map; //!< List of maps to apply to the profile.
} ldap_xlat_profile_call_env_t;
-static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule);
+static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule);
static const call_env_parser_t sasl_call_env[] = {
{ FR_CALL_ENV_OFFSET("mech", FR_TYPE_STRING, CALL_ENV_FLAG_NONE, ldap_auth_call_env_t, user_sasl_mech) },
return 0;
}
-static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, fr_dict_t const *namespace, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule)
+static int ldap_update_section_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, tmpl_rules_t const *t_rules, CONF_ITEM *ci, UNUSED call_env_parser_t const *rule)
{
map_list_t *maps;
CONF_SECTION *update = cf_item_to_section(ci);
map_t const *map = NULL;
tmpl_attr_t const *ar;
call_env_parsed_t *parsed;
- tmpl_rules_t parse_rules = {
- .attr = {
- .dict_def = namespace,
- .list_def = request_attr_request,
- }
- };
MEM(parsed = call_env_parsed_add(ctx, out,
&(call_env_parser_t){
MEM(maps = talloc(parsed, map_list_t));
map_list_init(maps);
- if (map_afrom_cs(maps, maps, update, &parse_rules, &parse_rules, fr_ldap_map_verify, NULL, LDAP_MAX_ATTRMAP) < 0) {
+ if (map_afrom_cs(maps, maps, update, t_rules, t_rules, fr_ldap_map_verify, NULL, LDAP_MAX_ATTRMAP) < 0) {
call_env_parsed_free(out, parsed);
return -1;
}