return g;
}
-void unlang_compile_action_defaults(unlang_t *c, unlang_compile_ctx_t *unlang_ctx)
+/** Update a compiled unlang_t with the default actions.
+ *
+ * Don't over-ride any actions which have been set.
+ */
+static void compile_set_default_actions(unlang_t *c, unlang_compile_ctx_t *unlang_ctx)
{
int i;
* have RETURN for all actions except fail. But THEIR children are normal.
*/
if (c->parent &&
- ((c->parent->type == UNLANG_TYPE_REDUNDANT) || (c->parent->type == UNLANG_TYPE_REDUNDANT_LOAD_BALANCE))) {
+ ((c->parent->type == UNLANG_TYPE_REDUNDANT) ||
+ (c->parent->type == UNLANG_TYPE_REDUNDANT_LOAD_BALANCE))) {
for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
switch (i) {
case RLM_MODULE_FAIL:
}
/*
- * Set the default actions, if they haven't already been
+ * Set the default actions if they haven't already been
* set.
*/
for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
map_list_init(&edit->maps);
- unlang_compile_action_defaults(c, unlang_ctx);
-
/*
* Allocate the map and initialize it.
*/
map_list_init(&edit->maps);
- unlang_compile_action_defaults(c, unlang_ctx);
-
op = cf_pair_operator(cp);
if ((op == T_OP_CMP_TRUE) || (op == T_OP_CMP_FALSE)) {
cf_log_err(cp, "Invalid operator \"%s\".",
return true;
}
-unlang_t *unlang_compile_empty(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_SECTION *cs, unlang_type_t type)
+unlang_t *unlang_compile_empty(unlang_t *parent, UNUSED unlang_compile_ctx_t *unlang_ctx, CONF_SECTION *cs, unlang_type_t type)
{
unlang_group_t *g;
unlang_t *c;
}
}
- unlang_compile_action_defaults(c, unlang_ctx);
return c;
}
}
-unlang_t *unlang_compile_children(unlang_group_t *g, unlang_compile_ctx_t *unlang_ctx_in, bool set_action_defaults)
+unlang_t *unlang_compile_children(unlang_group_t *g, unlang_compile_ctx_t *unlang_ctx_in)
{
CONF_ITEM *ci = NULL;
unlang_t *c, *single;
if (fr_list_assignment_op[cf_section_name2_quote(subcs)]) {
single = compile_edit_section(c, unlang_ctx, subcs);
if (!single) {
+ fail:
talloc_free(c);
return NULL;
}
}
if (strcmp(name, "actions") == 0) {
- if (!compile_action_subsection(c, g->cs, subcs)) {
- talloc_free(c);
- return NULL;
- }
-
+ if (!compile_action_subsection(c, g->cs, subcs)) goto fail;
continue;
}
if (!was_if) {
cf_log_err(ci, "Invalid location for '%s'. There is no preceding "
"'if' or 'elsif' statement", name);
- talloc_free(c);
- return NULL;
+ goto fail;
}
/*
single = compile_item(c, unlang_ctx, ci);
if (!single) {
cf_log_err(ci, "Failed to parse \"%s\" subsection", cf_section_name1(subcs));
- talloc_free(c);
- return NULL;
+ goto fail;
}
goto add_child;
* Variable definition.
*/
if (cf_pair_operator(cp) == T_OP_CMP_TRUE) {
- if (compile_variable(c, unlang_ctx, cp, &t_rules) < 0) {
- talloc_free(c);
- return NULL;
- }
+ if (compile_variable(c, unlang_ctx, cp, &t_rules) < 0) goto fail;
single = UNLANG_IGNORE;
goto add_child;
single = compile_item(c, unlang_ctx, ci);
if (!single) {
cf_log_err(ci, "Invalid keyword \"%s\".", cf_pair_attr(cp));
- talloc_free(c);
- return NULL;
+ goto fail;
}
goto add_child;
* tells us what it is, and we don't really care if there's a leading '&'.
*/
single = compile_edit_pair(c, unlang_ctx, cp);
- if (!single) {
- talloc_free(c);
- return NULL;
- }
+ if (!single) goto fail;
goto add_child;
} else {
cf_log_err(ci, "Asked to compile unknown conf type");
- talloc_free(c);
- return NULL;
+ goto fail;
}
add_child:
}
}
- /*
- * Set the default actions, if they haven't already been
- * set by an "actions" section above.
- */
- if (set_action_defaults) unlang_compile_action_defaults(c, unlang_ctx);
-
return c;
}
MEM(c->debug_name = talloc_typed_asprintf(c, "%s %s", name1, name2));
}
- return unlang_compile_children(g, unlang_ctx, true);
+ return unlang_compile_children(g, unlang_ctx);
}
}
ut->tmpl = vpt; /* const issues */
- unlang_compile_action_defaults(c, unlang_ctx);
return c;
}
*/
c->actions = m->mmc.mi->actions;
- /*
- * Add in the default actions for this section.
- */
- unlang_compile_action_defaults(c, unlang_ctx);
-
/*
* Parse the method environment for this module / method
*/
}
c = op->compile(parent, unlang_ctx, ci);
- allocate_number:
- if (!c) return NULL;
- if (c == UNLANG_IGNORE) return UNLANG_IGNORE;
-
- c->number = unlang_number++;
-
- /*
- * Only insert the per-thread allocation && instantiation if it's used.
- */
- op = &unlang_ops[c->type];
- if (!op->thread_inst_size) return c;
-
- if (!fr_rb_insert(unlang_instruction_tree, c)) {
- cf_log_err(ci, "Instruction \"%s\" number %u has conflict with previous one.",
- c->debug_name, c->number);
- talloc_free(c);
- return NULL;
- }
-
- return c;
+ goto allocate_number;
}
/* else it's something like sql { fail = 1 ...} */
*/
CONF_PAIR *cp = cf_item_to_pair(ci);
- name = cf_pair_attr(cp);
- op = name_to_op(name);
-
- /*
- * Forbid section keywords as pair names, e.g. bare "update"
- */
- if (op && ((op->flag & UNLANG_OP_FLAG_SINGLE_WORD) == 0)) {
- cf_log_err(ci, "Syntax error after keyword '%s' - missing '{'", name);
- return NULL;
- }
-
/*
* We cannot have assignments or actions here.
*/
if (cf_pair_value(cp) != NULL) {
- cf_log_err(ci, "Entry is not a reference to a module");
+ cf_log_err(ci, "Invalid assignment");
return NULL;
}
+ name = cf_pair_attr(cp);
+ op = name_to_op(name);
+
+ if (op) {
+ /*
+ * Forbid section keywords as pair names, e.g. bare "update"
+ */
+ if ((op->flag & UNLANG_OP_FLAG_SINGLE_WORD) == 0) {
+ cf_log_err(ci, "Syntax error after keyword '%s' - missing '{'", name);
+ return NULL;
+ }
+
+ c = op->compile(parent, unlang_ctx, ci);
+ goto allocate_number;
+ }
+
/*
* In-place expansions.
*
goto allocate_number;
}
- if (!op) goto check_for_module;
+ goto check_for_module;
- c = op->compile(parent, unlang_ctx, ci);
- goto allocate_number;
} else {
- cf_log_err(ci, "Asked to compile unknown conf type");
+ cf_log_err(ci, "Asked to compile unknown configuration item");
return NULL; /* who knows what it is... */
}
*/
UPDATE_CTX2;
c = compile_module(parent, &unlang_ctx2, ci, realname);
- if (c) goto allocate_number;
+ if (!c) {
+ if (ignore_notfound) {
+ cf_log_warn(ci, "Ignoring \"%s\" as the \"%s\" module is not enabled, "
+ "or the method does not exist", name, realname);
+ return UNLANG_IGNORE;
+ }
- if (ignore_notfound) {
- cf_log_warn(ci, "Ignoring \"%s\" as the \"%s\" module is not enabled, "
- "or the method does not exist", name, realname);
- return UNLANG_IGNORE;
+ return NULL;
}
- return NULL;
+allocate_number:
+ if (!c) return NULL;
+ if (c == UNLANG_IGNORE) return UNLANG_IGNORE;
+
+ c->number = unlang_number++;
+ compile_set_default_actions(c, unlang_ctx);
+
+ /*
+ * Only insert the per-thread allocation && instantiation if it's used.
+ */
+ op = &unlang_ops[c->type];
+ if (!op->thread_inst_size) return c;
+
+ if (!fr_rb_insert(unlang_instruction_tree, c)) {
+ cf_log_err(ci, "Instruction \"%s\" number %u has conflict with previous one.",
+ c->debug_name, c->number);
+ talloc_free(c);
+ return NULL;
+ }
+
+ return c;
}
/** Compile an unlang section for a virtual server
* - -1 on error.
*/
int unlang_compile(virtual_server_t const *vs,
- CONF_SECTION *cs, unlang_mod_actions_t const * actions, tmpl_rules_t const *rules, void **instruction)
+ CONF_SECTION *cs, unlang_mod_actions_t const *actions, tmpl_rules_t const *rules, void **instruction)
{
unlang_t *c;
tmpl_rules_t my_rules;
if (!transaction_ok(cs)) return NULL;
- /*
- * Any failure is return, not continue.
- */
- unlang_compile_ctx_copy(&unlang_ctx2, unlang_ctx);
-
- unlang_ctx2.actions.actions[RLM_MODULE_REJECT] = MOD_ACTION_RETURN;
- unlang_ctx2.actions.actions[RLM_MODULE_FAIL] = MOD_ACTION_RETURN;
- unlang_ctx2.actions.actions[RLM_MODULE_INVALID] = MOD_ACTION_RETURN;
- unlang_ctx2.actions.actions[RLM_MODULE_DISALLOW] = MOD_ACTION_RETURN;
-
g = unlang_group_allocate(parent, cs, UNLANG_TYPE_TRANSACTION);
if (!g) return NULL;
c = unlang_group_to_generic(g);
c->debug_name = c->name = cf_section_name1(cs);
- if (!unlang_compile_children(g, &unlang_ctx2, false)) return NULL;
+ /*
+ * The default for a failed transaction is to continue to
+ * the next instruction on failure.
+ */
+ c->actions.actions[RLM_MODULE_FAIL] = 1;
+ c->actions.actions[RLM_MODULE_INVALID] = 1;
+ c->actions.actions[RLM_MODULE_DISALLOW] = 1;
/*
- * The default for a failed transaction is to continue on
- * failure.
+ * For the children of this keyword, any failure is
+ * return, not continue.
*/
- if (!c->actions.actions[RLM_MODULE_FAIL]) c->actions.actions[RLM_MODULE_FAIL] = 1;
- if (!c->actions.actions[RLM_MODULE_INVALID]) c->actions.actions[RLM_MODULE_INVALID] = 1;
- if (!c->actions.actions[RLM_MODULE_DISALLOW]) c->actions.actions[RLM_MODULE_DISALLOW] = 1;
+ unlang_compile_ctx_copy(&unlang_ctx2, unlang_ctx);
- unlang_compile_action_defaults(c, unlang_ctx); /* why is this here???? */
+ unlang_ctx2.actions.actions[RLM_MODULE_REJECT] = MOD_ACTION_RETURN;
+ unlang_ctx2.actions.actions[RLM_MODULE_FAIL] = MOD_ACTION_RETURN;
+ unlang_ctx2.actions.actions[RLM_MODULE_INVALID] = MOD_ACTION_RETURN;
+ unlang_ctx2.actions.actions[RLM_MODULE_DISALLOW] = MOD_ACTION_RETURN;
- return c;
+ return unlang_compile_children(g, &unlang_ctx2);
}
void unlang_transaction_init(void)