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 *priority)
+ 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;
}
*result = next->result;
- *priority = next->priority;
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;
was_if = if_taken = FALSE;
result = RLM_MODULE_FAIL;
- priority = -1;
redo:
+ priority = -1;
c = entry->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],
g->vps, c->name);
if (rcode != RLM_MODULE_UPDATED) {
result = rcode;
- goto calculate_result;
+ } else {
+ result = RLM_MODULE_NOOP;
}
-
- result = RLM_MODULE_NOOP;
MOD_LOG_CLOSE_BRACE();
- goto next_sibling;
+ goto calculate_result;
} /* MOD_IF */
/*
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, &priority);
+ &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, &priority);
+ &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, &priority);
+ &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, &priority);
- 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);
}
*/
calculate_result:
+#if 0
+ RDEBUG("(%s, %d) ? (%s, %d)",
+ fr_int2str(mod_rcode_table, result, "<invalid>"),
+ priority,
+ fr_int2str(mod_rcode_table, entry->result, "<invalid>"),
+ entry->priority);
+#endif
+
/*
* The child's action says return. Do so.
*/
* The array holds a default priority for this return
* code. Grab it in preference to any unset priority.
*/
- if (priority < 0) priority = c->actions[result];
+ if (priority < 0) {
+ priority = c->actions[result];
+ }
/*
* We're higher than any previous priority, remember this
* return code and priority.
*/
- if ((priority >= entry->priority) &&
- (result != entry->result)) {
+ if (priority > entry->priority) {
entry->result = result;
entry->priority = priority;
}
+ /*
+ * If we're processing a "case" statement, we return once
+ * it's done, rather than going to the next "case" statement.
+ */
+ 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;
}
csingle->type = MOD_UPDATE;
csingle->method = component;
+ memcpy(csingle->actions, defaultactions[component][GROUPTYPE_SIMPLE],
+ sizeof(csingle->actions));
+
g->grouptype = GROUPTYPE_SIMPLE;
g->children = NULL;
g->cs = cs;