typedef struct conf_item CONF_ITEM;
typedef struct conf_pair CONF_PAIR;
typedef struct conf_part CONF_SECTION;
+typedef struct conf_data CONF_DATA;
/*
* Instead of putting the information into a configuration structure,
CONF_SECTION *cf_section_sub_find_name2(const CONF_SECTION *, const char *name1, const char *name2);
char *cf_section_value_find(const CONF_SECTION *, const char *attr);
+void *cf_data_find(CONF_SECTION *, const char *);
+int cf_data_add(CONF_SECTION *, const char *, void *, void (*)(void *));
+
char *cf_pair_attr(CONF_PAIR *pair);
char *cf_pair_value(CONF_PAIR *pair);
const char *cf_section_name1(const CONF_SECTION *);
#endif
} module_instance_t;
-module_instance_t *find_module_instance(const char *instname);
+module_instance_t *find_module_instance(CONF_SECTION *, const char *instname);
"$Id$";
typedef enum conf_type {
+ CONF_ITEM_INVALID = 0,
CONF_ITEM_PAIR,
- CONF_ITEM_SECTION
+ CONF_ITEM_SECTION,
+ CONF_ITEM_DATA
} CONF_ITEM_TYPE;
struct conf_item {
rbtree_t *name2_tree; /* for sections of the same name2 */
};
+
+/*
+ * Internal data that is associated with a configuration section,
+ * so that we don't have to track it separately.
+ */
+struct conf_data {
+ CONF_ITEM item;
+ const char *name;
+ void *data; /* user data */
+ void (*free)(void *); /* free user data function */
+};
+
/*
* Isolate the scary casts in these tiny provably-safe functions
*/
return (CONF_ITEM *)cs;
}
+static CONF_DATA *cf_itemtodata(CONF_ITEM *ci)
+{
+ if (ci == NULL)
+ return NULL;
+ rad_assert(ci->type == CONF_ITEM_DATA);
+ return (CONF_DATA *)ci;
+}
+static CONF_ITEM *cf_datatoitem(CONF_DATA *cd)
+{
+ if (cd == NULL)
+ return NULL;
+ return (CONF_ITEM *)cd;
+}
+
/*
* Create a new CONF_PAIR
*/
}
+static void cf_data_free(CONF_DATA **cd)
+{
+ if (!cd || !*cd) return;
+
+ free((*cd)->name);
+ if (!(*cd)->free) {
+ free((*cd)->data);
+ } else {
+ ((*cd)->free)((*cd)->data);
+ }
+
+ *cd = NULL;
+}
+
/*
* rbtree callback function
*/
for (ci = (*cs)->children; ci; ci = next) {
next = ci->next;
- if (ci->type==CONF_ITEM_PAIR) {
- CONF_PAIR *pair = cf_itemtopair(ci);
- cf_pair_free(&pair);
- } else {
- CONF_SECTION *section = cf_itemtosection(ci);
- cf_section_free(§ion);
+
+ switch (ci->type) {
+ case CONF_ITEM_PAIR: {
+ CONF_PAIR *pair = cf_itemtopair(ci);
+ cf_pair_free(&pair);
+ }
+ break;
+
+ case CONF_ITEM_SECTION: {
+
+ CONF_SECTION *section = cf_itemtosection(ci);
+ cf_section_free(§ion);
+ }
+ break;
+
+ case CONF_ITEM_DATA: {
+ CONF_DATA *data = cf_itemtodata(ci);
+ cf_data_free(&data);
+ }
+ break;
+
+ default: /* should really be an error. */
+ break;
}
}
* For fast lookups.
*/
while (ci_new) {
- if (ci_new->type == CONF_ITEM_PAIR) {
- rbtree_insert(cs->pair_tree, ci_new);
-
- } else if (ci_new->type == CONF_ITEM_SECTION) {
- const CONF_SECTION *cs_new = cf_itemtosection(ci_new);
-
- if (!cs->section_tree) {
- cs->section_tree = rbtree_create(section_cmp, NULL, 0);
- /* ignore any errors */
- }
-
- if (cs->section_tree) {
- rbtree_insert(cs->section_tree, cs_new);
- }
-
- /*
- * Two names: find the named instance.
- */
- if (cs_new->name2) {
- CONF_SECTION *old_cs;
+ switch (ci_new->type) {
+ case CONF_ITEM_PAIR:
+ rbtree_insert(cs->pair_tree, ci_new);
+ break;
- /*
- * Find the FIRST CONF_SECTION having the
- * given name1, and create a new tree
- * under it.
- */
- old_cs = rbtree_finddata(cs->section_tree, cs_new);
- if (!old_cs) return; /* this is a bad error! */
+ case CONF_ITEM_SECTION: {
+ const CONF_SECTION *cs_new = cf_itemtosection(ci_new);
- if (!old_cs->name2_tree) {
- old_cs->name2_tree = rbtree_create(name2_cmp,
- NULL, 0);
+ if (!cs->section_tree) {
+ cs->section_tree = rbtree_create(section_cmp, NULL, 0);
+ /* ignore any errors */
}
- if (old_cs->name2_tree) {
- rbtree_insert(old_cs->name2_tree, cs_new);
+
+ if (cs->section_tree) {
+ rbtree_insert(cs->section_tree, cs_new);
}
- } /* had a name2 */
- } /* was a section */
+
+ /*
+ * Two names: find the named instance.
+ */
+ if (cs_new->name2) {
+ CONF_SECTION *old_cs;
+
+ /*
+ * Find the FIRST
+ * CONF_SECTION having
+ * the given name1, and
+ * create a new tree
+ * under it.
+ */
+ old_cs = rbtree_finddata(cs->section_tree, cs_new);
+ if (!old_cs) return; /* this is a bad error! */
+
+ if (!old_cs->name2_tree) {
+ old_cs->name2_tree = rbtree_create(name2_cmp,
+ NULL, 0);
+ }
+ if (old_cs->name2_tree) {
+ rbtree_insert(old_cs->name2_tree, cs_new);
+ }
+ } /* had a name2 */
+ break;
+ } /* was a section */
+ default: /* FIXME: assert & error! */
+ break;
+
+ } /* switch over conf types */
ci_new = ci_new->next;
} /* loop over ci_new */
}
/*
- * Find a CONF_SECTION with both names.
+ * Find a CONF_SECTION with both names.
*/
CONF_SECTION *cf_section_sub_find_name2(const CONF_SECTION *cs,
const char *name1, const char *name2)
if (!cs) cs = mainconfig.config;
- if (cs->section_tree) {
+ if (name1 && (cs->section_tree)) {
CONF_SECTION mycs, *master_cs;
mycs.name1 = name1;
continue;
subcs = cf_itemtosection(ci);
+ if (!name1) {
+ if (!subcs->name2) {
+ if (strcmp(subcs->name1, name2) == 0) break;
+ } else {
+ if (strcmp(subcs->name2, name2) == 0) break;
+ }
+ continue; /* don't do the string comparisons below */
+ }
+
if ((strcmp(subcs->name1, name1) == 0) &&
(subcs->name2 != NULL) &&
(strcmp(subcs->name2, name2) == 0))
}
+static CONF_DATA *cf_data_alloc(CONF_SECTION *parent, const char *name,
+ void *data, void (*data_free)(void *))
+{
+ CONF_DATA *cd;
+
+ cd = rad_malloc(sizeof(*cd));
+ memset(cd, 0, sizeof(*cd));
+
+ cd->item.type = CONF_ITEM_DATA;
+ cd->item.parent = parent;
+ cd->name = strdup(name);
+ cd->data = data;
+ cd->free = data_free;
+
+ return cd;
+}
+
+
+/*
+ * Find data from a particular section.
+ */
+void *cf_data_find(CONF_SECTION *cs, const char *name)
+{
+ CONF_ITEM *ci;
+
+ if (!cs || !name) return NULL;
+
+ for (ci = cs->children; ci != NULL; ci = ci->next) {
+ CONF_DATA *cd;
+
+ /*
+ * Data is always inserted at the front of the
+ * list.
+ */
+ if (ci->type != CONF_ITEM_DATA) return NULL;
+
+ cd = cf_itemtodata(ci);
+ if (strcmp(name, cd->name) == 0) return cd->data;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Add named data to a configuration section.
+ */
+int cf_data_add(CONF_SECTION *cs, const char *name,
+ void *data, void (*data_free)(void *))
+{
+ CONF_ITEM *ci;
+ CONF_DATA *cd;
+
+ if (!cs || !name || !data) return -1;
+
+ /*
+ * Already exists. Can't add it.
+ */
+ if (cf_data_find(cs, name) != NULL) return -1;
+
+ ci = cs->children;
+
+ cd = cf_data_alloc(cs, name, data, data_free);
+
+ /*
+ * Insert at the TOP of the list.
+ */
+ ci = cf_datatoitem(cd);
+
+ ci->next = cs->children;
+ cs->children = ci;
+
+ return 0;
+}
+
+
#if 0
/*
* JMG dump_config tries to dump the config structure in a readable format
* so I had to get creative. --Pac. */
for (ci = cs->children; ci; ci = ci->next) {
- if (ci->type == CONF_ITEM_PAIR) {
+ switch (ci->type) {
+ case CONF_ITEM_PAIR:
cp=cf_itemtopair(ci);
DEBUG("%.*s%s = %s",
indent, "\t\t\t\t\t\t\t\t\t\t\t",
cp->attr, cp->value);
- } else {
+ break;
+
+ case CONF_ITEM_SECTION:
scs=cf_itemtosection(ci);
DEBUG("%.*s%s %s%s{",
indent, "\t\t\t\t\t\t\t\t\t\t\t",
dump_config_section(scs, indent+1);
DEBUG("%.*s}",
indent, "\t\t\t\t\t\t\t\t\t\t\t");
+ break;
+
+ default: /* FIXME: Do more! */
+ break;
}
}
* See if the module is a virtual one. If so, return that,
* rather than doing anything here.
*/
- this = find_module_instance(modrefname);
+ this = find_module_instance(cf_section_find("modules"), modrefname);
if (!this) {
CONF_SECTION *cs, *subcs;
/*
- * Then, look for a named "modules virtual {" section.
+ * Then, look for it in the "instantiate" section.
*/
if (((subcs = cf_section_find(NULL)) != NULL) &&
((cs = cf_section_sub_find_name2(subcs, "instantiate", NULL)) != NULL)) {
- const char *name1, *name2;
-
- name1 = name2 = NULL;
- for (subcs = cf_subsection_find_next(cs, NULL, NULL);
- subcs != NULL;
- subcs=cf_subsection_find_next(cs, subcs, NULL)) {
- name1 = cf_section_name1(subcs);
- name2 = cf_section_name2(subcs);
- if ((name2 && (strcmp(name2, modrefname) == 0)) ||
- (!name2 && (strcmp(name1, modrefname) == 0))) {
- break;
- }
- }
+ subcs = cf_section_sub_find_name2(cs, NULL, modrefname);
if (subcs) {
/*
* As it's sole configuration, the
*/
static module_list_t *module_list = NULL;
-/*
- * Internal list of each module instance.
- */
-static module_instance_t *module_instance_list = NULL;
-
typedef struct indexed_modcallable {
struct indexed_modcallable *next;
int idx;
*cf = NULL;
}
-static void instance_list_free(module_instance_t **i)
+/*
+ * Free a module instance.
+ */
+static void module_instance_free(module_instance_t *this)
{
- module_instance_t *c, *next;
-
- c = *i;
- while (c) {
- next = c->next;
- if(c->entry->module->detach)
- (c->entry->module->detach)(c->insthandle);
+ if (this->entry->module->detach)
+ (this->entry->module->detach)(this->insthandle);
#ifdef HAVE_PTHREAD_H
- if (c->mutex) {
- /*
- * FIXME
- * The mutex MIGHT be locked...
- * we'll check for that later, I guess.
- */
- pthread_mutex_destroy(c->mutex);
- free(c->mutex);
- }
-#endif
- free(c);
- c = next;
+ if (this->mutex) {
+ /*
+ * FIXME
+ * The mutex MIGHT be locked...
+ * we'll check for that later, I guess.
+ */
+ pthread_mutex_destroy(this->mutex);
+ free(this->mutex);
}
- *i = NULL;
+#endif
+ free(this);
}
+
/*
* Remove all of the modules.
*/
indexed_modcallable_free(&components[i]);
}
- instance_list_free(&module_instance_list);
-
ml = module_list;
while (ml) {
next = ml->next;
/*
* Find a module instance.
*/
-module_instance_t *find_module_instance(const char *instname)
+module_instance_t *find_module_instance(CONF_SECTION *modules,
+ const char *instname)
{
- CONF_SECTION *cs, *inst_cs;
+ CONF_SECTION *cs;
const char *name1, *name2;
- module_instance_t *node, **last;
+ module_instance_t *node;
char module_name[256];
- /*
- * Look through the global module instance list for the
- * named module.
- */
- last = &module_instance_list;
- for (node = module_instance_list; node != NULL; node = node->next) {
- /*
- * Found the named instance. Return it.
- */
- if (strcmp(node->name, instname) == 0)
- return node;
-
- /*
- * Keep a pointer to the last entry to update...
- */
- last = &node->next;
- }
-
- /*
- * Instance doesn't exist yet. Try to find the
- * corresponding configuration section and create it.
- */
-
- /*
- * Look for the 'modules' configuration section.
- */
- cs = cf_section_find("modules");
- if (cs == NULL) {
- radlog(L_ERR|L_CONS, "ERROR: Cannot find a 'modules' section in the configuration file.\n");
- return NULL;
- }
+ if (!modules) return NULL;
/*
* Module instances are declared in the modules{} block
* name2 from the config section, or name1 if there was
* no name2.
*/
- name1 = name2 = NULL;
- for(inst_cs=cf_subsection_find_next(cs, NULL, NULL);
- inst_cs != NULL;
- inst_cs=cf_subsection_find_next(cs, inst_cs, NULL)) {
- name1 = cf_section_name1(inst_cs);
- name2 = cf_section_name2(inst_cs);
- if ( (name2 && !strcmp(name2, instname)) ||
- (!name2 && !strcmp(name1, instname)) )
- break;
- }
- if (inst_cs == NULL) {
+ cs = cf_section_sub_find_name2(modules, NULL, instname);
+ if (cs == NULL) {
radlog(L_ERR|L_CONS, "ERROR: Cannot find a configuration entry for module \"%s\".\n", instname);
return NULL;
}
/*
+ * If there's already module instance, return it.
+ */
+ node = cf_data_find(cs, "instance");
+ if (node) return node;
+
+ name1 = cf_section_name1(cs);
+ name2 = cf_section_name2(cs);
+
+ /*
* Found the configuration entry.
*/
node = rad_malloc(sizeof(*node));
snprintf(module_name, sizeof(module_name), "rlm_%s", name1);
node->entry = linkto_module(module_name, mainconfig.radiusd_conf,
- cf_section_lineno(inst_cs));
+ cf_section_lineno(cs));
if (!node->entry) {
free(node);
/* linkto_module logs any errors */
* Call the module's instantiation routine.
*/
if ((node->entry->module->instantiate) &&
- ((node->entry->module->instantiate)(inst_cs,
- &node->insthandle) < 0)) {
+ ((node->entry->module->instantiate)(cs, &node->insthandle) < 0)) {
radlog(L_ERR|L_CONS,
"%s[%d]: %s: Module instantiation failed.\n",
- mainconfig.radiusd_conf, cf_section_lineno(inst_cs),
+ mainconfig.radiusd_conf, cf_section_lineno(cs),
instname);
free(node);
return NULL;
}
#endif
- *last = node;
+ cf_data_add(cs, "instance", node, module_instance_free);
DEBUG("Module: Instantiated %s (%s) ", name1, node->name);
int idx;
indexed_modcallable *subcomp;
const char *modname;
- char *visiblename;
+ const char *visiblename;
/*
* Loop over the entries in the named section.
int setup_modules(void)
{
int comp;
- CONF_SECTION *cs;
+ CONF_SECTION *cs, *modules;
int do_component[RLM_COMPONENT_COUNT];
rad_listen_t *listener;
} /* over the sections which can have redundent sub-sections */
/*
+ * Remember where the modules were stored.
+ */
+ modules = cf_section_find("modules");
+ if (!modules) {
+ radlog(L_ERR, "Cannot find a \"modules\" section in the configuration file!");
+ return -1;
+ }
+
+ /*
* Look for the 'instantiate' section, which tells us
* the instantiation order of the modules, and also allows
* us to load modules with no authorize/authenticate/etc.
cp = cf_itemtopair(ci);
name = cf_pair_attr(cp);
- module = find_module_instance(name);
+ module = find_module_instance(modules, name);
if (!module) {
return -1;
}