static module_instance_t *module_instance_list = NULL;
/*
- * For each authorize/authenticate/etc, we have an ordered
+ * For each authorize/authtype/etc, we have an ordered
* list of instances to call. This data structure keeps track
* of that order.
*/
typedef struct config_module_t {
struct config_module_t *next;
- int index;
module_instance_t *instance;
#if HAVE_PTHREAD_H
pthread_mutex_t *mutex;
#endif
} config_module_t;
+typedef struct indexed_config_module_t {
+ struct indexed_config_module_t *next;
+ int idx;
+ config_module_t *modulelist;
+} indexed_config_module_t;
+
/*
* For each component, keep an ordered list of ones to call.
*/
-static config_module_t *components[RLM_COMPONENT_COUNT];
+static indexed_config_module_t *components[RLM_COMPONENT_COUNT];
/*
* The component names.
"session"
};
+static const char *subcomponent_names[RLM_COMPONENT_COUNT] =
+{
+ "authtype",
+ "autztype",
+ "preacctype",
+ "acctype",
+ "sesstype"
+};
+
static void config_list_free(config_module_t **cf)
{
config_module_t *c, *next;
*cf = NULL;
}
+static void indexed_config_list_free(indexed_config_module_t **cf)
+{
+ indexed_config_module_t *c, *next;
+
+ c = *cf;
+ while (c) {
+ next = c->next;
+ config_list_free(&c->modulelist);
+ free(c);
+ c = next;
+ }
+ *cf = NULL;
+}
+
static void instance_list_free(module_instance_t **i)
{
module_instance_t *c, *next;
* Delete the internal component pointers.
*/
for (i = 0; i < RLM_COMPONENT_COUNT; i++) {
- config_list_free(&components[i]);
+ indexed_config_list_free(&components[i]);
}
instance_list_free(&module_instance_list);
return node;
}
+static indexed_config_module_t *lookup_by_index(indexed_config_module_t *head, int idx)
+{
+ indexed_config_module_t *p;
+
+ for (p = head; p != NULL; p = p->next) {
+ if( p->idx == idx)
+ return p;
+ }
+ return NULL;
+}
+
/*
* Add one entry at the end of the config_module_t list.
*/
-static void add_to_list(int comp, module_instance_t *instance, int index)
+static void add_to_list(int comp, module_instance_t *instance, int idx)
{
+ indexed_config_module_t *subcomp;
config_module_t *node;
config_module_t **last;
config_module_t **head;
- head = &components[comp];
+ /* Step 1 - find the list corresponding to the given index. The
+ * caller is responsible for ensuring that one exists by calling
+ * new_sublist before calling add_to_list. */
+ subcomp = lookup_by_index(components[comp], idx);
+ assert(subcomp);
+
+ /* Step 2 - walk to the end of that list */
+ head = &subcomp->modulelist;
last = head;
for (node = *head; node != NULL; node = node->next) {
last = &node->next;
}
+ /* Step 3 - put a new config_module_t there */
node = (config_module_t *) rad_malloc(sizeof(config_module_t));
node->next = NULL;
node->instance = instance;
- node->index = index;
#if HAVE_PTHREAD_H
/*
*last = node;
}
-static config_module_t *lookup_by_index(config_module_t *head, int index)
+static indexed_config_module_t *new_sublist(int comp, int idx)
{
- config_module_t *p;
-
- for (p = head; p != NULL; p = p->next) {
- if( p->index == index)
- return p;
+ indexed_config_module_t **head = &components[comp];
+ indexed_config_module_t *node = *head;
+ indexed_config_module_t **last = head;
+
+ while (node) {
+ /* It is an error to try to create a sublist that already
+ * exists. It would almost certainly be caused by accidental
+ * duplication in the config file.
+ *
+ * index 0 is the exception, because it is used when we want
+ * to collect _all_ listed modules under a single index by
+ * default, which is currently the case in all components
+ * except authenticate. */
+ if (node->idx == idx) {
+ if (idx == 0)
+ return node;
+ else
+ return NULL;
+ }
+ last = &node->next;
+ node = node->next;
}
- return NULL;
+
+ node = rad_malloc(sizeof *node);
+ node->next = NULL;
+ node->modulelist = NULL;
+ node->idx = idx;
+ *last = node;
+ return node;
}
/* Bail out if the module in question does not supply the wanted component */
filename, lineno, comp);
exit(1);
}
- return NULL;
}
-static void load_module_section(CONF_SECTION *cs, int comp, const char *filename)
+/* Load a flat module list, as found inside an authtype{} block */
+static void load_subcomponent_section(CONF_SECTION *cs, int comp, const char *filename)
+{
+ module_instance_t *this;
+ CONF_ITEM *modref;
+ int modreflineno;
+ const char *modrefname;
+ int idx;
+
+ static int meaningless_counter = 1;
+
+ /* We must assign a numeric index to this subcomponent. For
+ * auth, it is generated and placed in the dictionary by
+ * new_authtype_value(). The others are just numbers that are pulled
+ * out of thin air, and the names are neither put into the dictionary
+ * nor checked for uniqueness, but all that could be fixed in a few
+ * minutes, if anyone finds a real use for indexed config of
+ * components other than auth. */
+ switch (comp) {
+ case RLM_COMPONENT_AUTH:
+ idx = new_authtype_value(cf_section_name2(cs));
+ break;
+ default:
+ idx = meaningless_counter++;
+ break;
+ }
+
+ if (!new_sublist(comp, idx)) {
+ radlog(L_ERR|L_CONS,
+ "%s[%d] %s %s already configured - skipping",
+ filename, cf_section_lineno(cs),
+ subcomponent_names[comp], cf_section_name2(cs));
+ return;
+ }
+
+ for(modref=cf_item_find_next(cs, NULL)
+ ; modref ;
+ modref=cf_item_find_next(cs, modref)) {
+
+ if(cf_item_is_section(modref)) {
+ CONF_SECTION *scs;
+ scs = cf_itemtosection(modref);
+ modreflineno = cf_section_lineno(scs);
+ modrefname = cf_section_name1(scs);
+ } else {
+ CONF_PAIR *cp;
+ cp = cf_itemtopair(modref);
+ modreflineno = cf_pair_lineno(cp);
+ modrefname = cf_pair_attr(cp);
+ }
+
+ this = find_module_instance(modrefname);
+ if (this == NULL) {
+ /* find_module_instance logs any errors */
+ exit(1);
+ }
+
+ sanity_check(comp, this->entry->module, filename, modreflineno);
+ add_to_list(comp, this, idx);
+ }
+}
+
+static void load_component_section(CONF_SECTION *cs, int comp, const char *filename)
{
module_instance_t *this;
CONF_ITEM *modref;
int modreflineno;
const char *modrefname;
+ int idx;
for(modref=cf_item_find_next(cs, NULL)
; modref ;
if(cf_item_is_section(modref)) {
CONF_SECTION *scs;
scs = cf_itemtosection(modref);
+ if (!strcmp(cf_section_name1(scs),
+ subcomponent_names[comp])) {
+ load_subcomponent_section(scs, comp, filename);
+ continue;
+ }
modreflineno = cf_section_lineno(scs);
modrefname = cf_section_name1(scs);
} else {
}
sanity_check(comp, this->entry->module, filename, modreflineno);
+
switch (comp) {
case RLM_COMPONENT_AUTH:
- add_to_list(RLM_COMPONENT_AUTH, this, new_authtype_value(this->name));
- break;
- case RLM_COMPONENT_AUTZ:
- case RLM_COMPONENT_PREACCT:
- case RLM_COMPONENT_ACCT:
- case RLM_COMPONENT_SESS:
- add_to_list(comp, this, 0);
+ idx = new_authtype_value(this->name);
break;
default:
- radlog(L_ERR|L_CONS, "%s[%d] Unknown component %d.\n",
- filename, modreflineno, comp);
- exit(1);
+ /* See the comment in new_sublist() for explanation
+ * of the special index 0 */
+ idx = 0;
+ break;
}
+
+ if (!new_sublist(comp, idx)) {
+ radlog(L_ERR|L_CONS,
+ "%s[%d] %s %s already configured - skipping",
+ filename, modreflineno, subcomponent_names[comp],
+ this->name);
+ continue;
+ }
+ add_to_list(comp, this, idx);
}
}
cs = cf_section_find(component_names[comp]);
if (!cs) continue;
- load_module_section(cs, comp, filename);
+ load_component_section(cs, comp, filename);
}
return 0;
config_module_t *this;
int rcode = RLM_MODULE_OK;
- this = components[RLM_COMPONENT_AUTZ];
+ this = lookup_by_index(components[RLM_COMPONENT_AUTZ], 0)->modulelist;
rcode = RLM_MODULE_OK;
while (this && rcode == RLM_MODULE_OK) {
config_module_t *this;
int rcode = RLM_MODULE_FAIL;
- this = lookup_by_index(components[RLM_COMPONENT_AUTH], auth_type);
+ this = lookup_by_index(components[RLM_COMPONENT_AUTH],
+ auth_type)->modulelist;
- /*
- * Only check the FIRST component. If we want multiple
- * Auth-Types, then this function should be called multiple
- * times.
- */
- DEBUG2(" authenticate: %s",
- this->instance->entry->module->name);
- safe_lock(this);
- rcode = (this->instance->entry->module->authenticate)(
- this->instance->insthandle, request);
- safe_unlock(this);
+ while (this && rcode == RLM_MODULE_FAIL) {
+ DEBUG2(" authenticate: %s",
+ this->instance->entry->module->name);
+ safe_lock(this);
+ rcode = (this->instance->entry->module->authenticate)(
+ this->instance->insthandle, request);
+ safe_unlock(this);
+ this = this->next;
+ }
return rcode;
}
config_module_t *this;
int rcode;
- this = components[RLM_COMPONENT_PREACCT];
+ this = lookup_by_index(components[RLM_COMPONENT_PREACCT], 0)->modulelist;
rcode = RLM_MODULE_OK;
while (this && (rcode == RLM_MODULE_OK)) {
config_module_t *this;
int rcode;
- this = components[RLM_COMPONENT_ACCT];
+ this = lookup_by_index(components[RLM_COMPONENT_ACCT], 0)->modulelist;
rcode = RLM_MODULE_OK;
while (this && (rcode == RLM_MODULE_OK)) {
request->simul_max = maxsimul;
request->simul_mpp = 1;
- this = components[RLM_COMPONENT_SESS];
+ this = lookup_by_index(components[RLM_COMPONENT_SESS], 0)->modulelist;
rcode = RLM_MODULE_FAIL;
while (this && (rcode == RLM_MODULE_FAIL)) {