comp2str[component], sp->modinst->name,
sp->modinst->entry->name, request->number);
- if (sp->modinst->dead) {
- myresult = RLM_MODULE_FAIL;
+ if (sp->modinst->force) {
+ myresult = sp->modinst->code;
goto fail;
}
static int modcall_recurse(REQUEST *request, int component, int depth,
- modcall_stack_entry_t *entry);
+ modcall_stack_entry_t *entry, int do_next_sibling);
/*
* Call a child of a block.
*/
static void modcall_child(REQUEST *request, int component, int depth,
modcall_stack_entry_t *entry, modcallable *c,
- int *result)
+ int *result, int do_next_sibling)
{
modcall_stack_entry_t *next;
next->priority = 0;
if (!modcall_recurse(request, component,
- depth, next)) {
+ depth, next, do_next_sibling)) {
*result = RLM_MODULE_FAIL;
return;
}
* Interpret the various types of blocks.
*/
static int modcall_recurse(REQUEST *request, int component, int depth,
- modcall_stack_entry_t *entry)
+ modcall_stack_entry_t *entry, int do_next_sibling)
{
int if_taken, was_if;
modcallable *c;
RDEBUG2("%.*s? %s %s", depth + 1, modcall_spaces,
group_name[c->type], c->name);
- if (radius_evaluate_condition(request, entry->result,
+ if (radius_evaluate_condition(request, result,
0, &p, TRUE, &condition)) {
RDEBUG2("%.*s? %s %s -> %s", depth + 1, modcall_spaces,
group_name[c->type],
do_children:
g = mod_callabletogroup(c);
+ /*
+ * This should really have been caught in the
+ * compiler, and the node never generated. But
+ * doing that requires changing it's API so that
+ * it returns a flag instead of the compiled
+ * MOD_GROUP.
+ */
+ if (!g->children) {
+ RDEBUG2("%.*s%s %s { ... } # empty sub-section is ignored",
+ depth + 1, modcall_spaces, group_name[c->type], c->name);
+ goto next_sibling;
+ }
+
MOD_LOG_OPEN_BRACE(group_name[c->type]);
modcall_child(request, component,
depth + 1, entry, g->children,
- &result);
+ &result, TRUE);
MOD_LOG_CLOSE_BRACE();
goto calculate_result;
} /* MOD_GROUP */
if (!strchr(c->name, '%')) {
VALUE_PAIR *vp = NULL;
- radius_get_vp(request, c->name, &vp);
- if (vp) {
+ if (radius_get_vp(request, c->name, &vp) && vp) {
vp_prints_value(buffer,
sizeof(buffer),
vp, 0);
MOD_LOG_OPEN_BRACE(group_name[c->type]);
modcall_child(request, component,
depth + 1, entry, found,
- &result);
+ &result, TRUE);
MOD_LOG_CLOSE_BRACE();
goto calculate_result;
} /* MOD_SWITCH */
if ((c->type == MOD_LOAD_BALANCE) ||
(c->type == MOD_REDUNDANT_LOAD_BALANCE)) {
- int count;
+ int count = 0;
modcallable *this, *found;
modgroup *g;
if (c->type == MOD_LOAD_BALANCE) {
modcall_child(request, component,
depth + 1, entry, found,
- &result);
+ &result, FALSE);
} else {
- int i;
+ this = found;
- /*
- * Loop over all children in this
- * section. If we get FAIL, then
- * continue. Otherwise, stop.
- */
- for (i = 1; i < count; i++) {
+ do {
modcall_child(request, component,
depth + 1, entry, found,
- &result);
- if (c->actions[result] == MOD_ACTION_RETURN) {
+ &result, FALSE);
+ if (found->actions[result] == MOD_ACTION_RETURN) {
priority = -1;
break;
}
- }
+
+ this = this->next;
+ if (!this) this = g->children;
+ } while (this != found);
}
MOD_LOG_CLOSE_BRACE();
goto calculate_result;
RDEBUG("`%s`", mx->xlat_name);
radius_exec_program(mx->xlat_name, request,
0, NULL, 0,
+ EXEC_TIMEOUT,
request->packet->vps,
NULL, 1);
}
if (c->type == MOD_CASE) return TRUE;
next_sibling:
- entry->c = entry->c->next;
+ if (do_next_sibling) {
+ entry->c = entry->c->next;
- if (entry->c) goto redo;
+ if (entry->c) goto redo;
+ }
/*
* And we're done!
/*
* Call the main handler.
*/
- if (!modcall_recurse(request, component, 0, &stack[0])) {
+ if (!modcall_recurse(request, component, 0, &stack[0], TRUE)) {
return RLM_MODULE_FAIL;
}