/* * Helper function for call_modgroup, and call_modredundantloadbalance * * Returns 0 for "stop", and "1" for continue. */ static int call_one(int component, modcallable *p, REQUEST *request, int *priority, int *result) { int r; #ifdef RAD_REQUEST_OPTION_STOP_NOW /* * A module has taken too long to process the request, * and we've been told to stop processing it. */ if (request->options & RAD_REQUEST_OPTION_STOP_NOW) { *result = RLM_MODULE_FAIL; return 0; } #endif /* Call this child by recursing into modcall */ r = modcall(component, p, request); #if 0 DEBUG2("%s: action for %s is %s", comp2str[component], lrad_int2str(rcode_table, r, "??"), action2str(p->actions[r])); #endif /* * Find an action to go with the child's result. If it is * "return", break out of the loop so the rest of the * children in the list will be skipped. */ if (p->actions[r] == MOD_ACTION_RETURN) { *result = r; return 0; } /* If "reject" break out of the loop and return reject */ if (p->actions[r] == MOD_ACTION_REJECT) { *result = RLM_MODULE_REJECT; return 0; } /* * Otherwise, the action is a number, the preference * level of this return code. If no higher preference has * been seen yet, remember this one . */ if (p->actions[r] >= *priority) { *result = r; *priority = p->actions[r]; } return 1; }
rlm_rcode_t indexed_modcall(int comp, int idx, REQUEST *request) { rlm_rcode_t rcode; modcallable *list = NULL; virtual_server_t *server; /* * Hack to find the correct virtual server. */ server = virtual_server_find(request->server); if (!server) { RDEBUG("No such virtual server \"%s\"", request->server); return RLM_MODULE_FAIL; } if (idx == 0) { list = server->mc[comp]; if (!list) RWDEBUG2("Empty %s section. Using default return values.", section_type_value[comp].section); } else { indexed_modcallable *this; this = lookup_by_index(server->components, comp, idx); if (this) { list = this->modulelist; } else { RWDEBUG2("Unknown value specified for %s. Cannot perform requested action.", section_type_value[comp].typename); } } if (server->subcs[comp]) { if (idx == 0) { RDEBUG("# Executing section %s from file %s", section_type_value[comp].section, cf_section_filename(server->subcs[comp])); } else { RDEBUG("# Executing group from file %s", cf_section_filename(server->subcs[comp])); } } request->component = section_type_value[comp].section; rcode = modcall(comp, list, request); request->module = ""; request->component = "<core>"; return rcode; }
static int call_modloadbalance(int component, modgroup *g, REQUEST *request, int default_result) { int count = 1; modcallable *p, *child = NULL; /* * Catch people who have issues. */ if (!g->children) { DEBUG2(" WARNING! Asked to process empty load-balance group. Returning %s.", lrad_int2str(rcode_table, default_result, "??")); return default_result; } /* * Pick a random child. */ /* Loop over the children */ for(p = g->children; p; p = p->next) { if (!child) { child = p; count = 1; continue; } /* * Keep track of how many load balancing servers * we've gone through. */ count++; /* * See the "camel book" for why this works. * * If (rand(0..n) < 1), pick the current realm. * We add a scale factor of 65536, to avoid * floating point. */ if ((count * (lrad_rand() & 0xffff)) < (uint32_t) 0x10000) { child = p; } } rad_assert(child != NULL); /* Call the chosen child by recursing into modcall */ return modcall(component, child, request); }
static int indexed_modcall(int comp, int idx, REQUEST *request) { indexed_modcallable *this; this = lookup_by_index(components[comp], idx); if (!this) { /* Return a default value appropriate for the component */ switch(comp) { case RLM_COMPONENT_AUTZ: return RLM_MODULE_NOTFOUND; case RLM_COMPONENT_AUTH: return RLM_MODULE_REJECT; case RLM_COMPONENT_PREACCT: return RLM_MODULE_NOOP; case RLM_COMPONENT_ACCT: return RLM_MODULE_NOOP; case RLM_COMPONENT_SESS: return RLM_MODULE_FAIL; case RLM_COMPONENT_PRE_PROXY: return RLM_MODULE_NOOP; case RLM_COMPONENT_POST_PROXY: return RLM_MODULE_NOOP; case RLM_COMPONENT_POST_AUTH: return RLM_MODULE_NOOP; default: return RLM_MODULE_FAIL; } } return modcall(comp, this->modulelist, request); }
/* * Evaluate a module statement */ static int evaluate_module(policy_state_t *state, const policy_item_t *item) { const policy_module_t *this; this = (const policy_module_t *) item; /* * Just to be paranoid. Maybe we want to loosen this * restriction in the future? */ if (this->component != state->component) { DEBUG2("rlm_policy: Cannot mix & match components"); return 0; } DEBUG2("rlm_policy: begin nested call"); state->rcode = modcall(this->component, this->mc, state->request); DEBUG2("rlm_policy: end nested call"); return 1; /* we succeeded */ }