return unlang_compile_section(parent, unlang_ctx, cf_item_to_section(ci), UNLANG_TYPE_GROUP);
}
-static unlang_t *unlang_compile_redundant(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM const *ci)
-{
- CONF_SECTION *cs = cf_item_to_section(ci);
-
- if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
-
- if (!unlang_compile_limit_subsection(cs, cf_section_name1(cs))) {
- return NULL;
- }
-
- if (cf_section_name2(cs) != NULL) {
- cf_log_warn(cs, "Ignoring name for 'redundant' section");
- }
-
- return unlang_compile_section(parent, unlang_ctx, cs, UNLANG_TYPE_REDUNDANT);
-}
-
-
void unlang_group_init(void)
{
unlang_register(&(unlang_op_t){
.unlang_name = "unlang_group_t",
});
- unlang_register(&(unlang_op_t){
- .name = "redundant",
- .type = UNLANG_TYPE_REDUNDANT,
- .flag = UNLANG_OP_FLAG_DEBUG_BRACES,
-
- .compile = unlang_compile_redundant,
- .interpret = unlang_group,
-
- .unlang_size = sizeof(unlang_group_t),
- .unlang_name = "unlang_group_t",
- });
-
unlang_register(&(unlang_op_t){
.name = "policy",
.type = UNLANG_TYPE_POLICY,
}
/*
- * We are in a resumed frame. Check if running the child resulting in an rcode that we can use.
- * If so, stop.
+ * We are in a resumed frame. Check if running the child resulted in a failure rcode which
+ * requires us to keep going. If not, return to the caller.
*/
- if ((redundant->result.rcode != RLM_MODULE_NOT_SET) &&
- (redundant->child->actions.actions[redundant->result.rcode] == MOD_ACTION_RETURN)) {
+ switch (redundant->result.rcode) {
+ case RLM_MODULE_FAIL:
+ case RLM_MODULE_TIMEOUT:
+ case RLM_MODULE_NOT_SET:
+ break;
+
+ default:
if (p_result) {
p_result->priority = MOD_PRIORITY_MIN;
p_result->rcode = redundant->result.rcode;
return UNLANG_ACTION_PUSHED_CHILD;
}
+static unlang_action_t unlang_redundant(unlang_result_t *p_result, request_t *request, unlang_stack_frame_t *frame)
+{
+ unlang_frame_state_redundant_t *redundant = talloc_get_type_abort(frame->state,
+ unlang_frame_state_redundant_t);
+ unlang_group_t *g = unlang_generic_to_group(frame->instruction);
+
+ /*
+ * Start at the first child, and then continue from there.
+ */
+ redundant->start = g->children;
+
+ frame->process = unlang_load_balance_next;
+ return unlang_load_balance_next(p_result, request, frame);
+}
+
static unlang_action_t unlang_load_balance(unlang_result_t *p_result, request_t *request, unlang_stack_frame_t *frame)
{
unlang_frame_state_redundant_t *redundant;
return compile_load_balance_subsection(parent, unlang_ctx, cf_item_to_section(ci), UNLANG_TYPE_LOAD_BALANCE);
}
-static void compile_redundant_actions(unlang_t *c)
+static unlang_t *unlang_compile_redundant_load_balance(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM const *ci)
{
- int i;
- unlang_group_t *g;
- unlang_t *child;
- unlang_mod_actions_t actions;
+ return compile_load_balance_subsection(parent, unlang_ctx, cf_item_to_section(ci), UNLANG_TYPE_REDUNDANT_LOAD_BALANCE);
+}
- /*
- * Children of "redundant" and "redundant-load-balance"
- * have RETURN for all actions except fail and timeout.
- */
- for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
- switch (i) {
- case RLM_MODULE_FAIL:
- case RLM_MODULE_TIMEOUT:
- actions.actions[i] = MOD_PRIORITY_MIN;
- break;
- default:
- actions.actions[i] = MOD_ACTION_RETURN;
- break;
- }
- }
+static unlang_t *unlang_compile_redundant(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM const *ci)
+{
+ CONF_SECTION *cs = cf_item_to_section(ci);
- g = unlang_generic_to_group(c);
+ if (!cf_item_next(cs, NULL)) return UNLANG_IGNORE;
- for (child = g->children; child != NULL; child = child->next) {
- child->actions = actions;
+ if (!unlang_compile_limit_subsection(cs, cf_section_name1(cs))) {
+ return NULL;
}
-}
+ /*
+ * "redundant foo" is allowed only inside of a "modules" section, where the name is the instance
+ * name.
+ *
+ * @todo - static versus dynamic modules?
+ */
-static unlang_t *unlang_compile_redundant_load_balance(unlang_t *parent, unlang_compile_ctx_t *unlang_ctx, CONF_ITEM const *ci)
-{
- unlang_t *c;
-
- c = compile_load_balance_subsection(parent, unlang_ctx, cf_item_to_section(ci), UNLANG_TYPE_REDUNDANT_LOAD_BALANCE);
- if (!c || (c == UNLANG_IGNORE)) return c;
+ if (cf_section_name2(cs) &&
+ (strcmp(cf_section_name1(cf_item_to_section(cf_parent(cs))), "modules") != 0)) {
+ cf_log_err(cs, "Cannot specify a key for 'redundant'");
+ return NULL;
+ }
- compile_redundant_actions(c);
- return c;
+ return unlang_compile_section(parent, unlang_ctx, cs, UNLANG_TYPE_REDUNDANT);
}
.frame_state_size = sizeof(unlang_frame_state_redundant_t),
.frame_state_type = "unlang_frame_state_redundant_t",
});
+
+ unlang_register(&(unlang_op_t){
+ .name = "redundant",
+ .type = UNLANG_TYPE_REDUNDANT,
+ .flag = UNLANG_OP_FLAG_DEBUG_BRACES | UNLANG_OP_FLAG_RCODE_SET,
+
+ .compile = unlang_compile_redundant,
+ .interpret = unlang_redundant,
+
+ .unlang_size = sizeof(unlang_group_t),
+ .unlang_name = "unlang_group_t",
+
+ .frame_state_size = sizeof(unlang_frame_state_redundant_t),
+ .frame_state_type = "unlang_frame_state_redundant_t",
+ });
+
}