```
cache {
-# driver = "rlm_cache_rbtree"
+# driver = "rbtree"
# memcached {
# options = "--SERVER=localhost"
# pool {
```
cache cache_tls_session {
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
key = &Session-Id
ttl = 3600 # 60 mins
update {
}
}
cache cache_ocsp {
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
key = &session-state.TLS-Client-Cert-Serial
update {
&control.TLS-OCSP-Cert-Valid := &TLS-OCSP-Cert-Valid
# [options="header,autowidth"]
# |===
# | Driver | Description
- # | `rlm_cache_rbtree` | An in memory, non persistent rbtree based datastore.
+ # | `rbtree` | An in memory, non persistent rbtree based datastore.
# Useful for caching data locally.
- # | `rlm_cache_memcached` | A non persistent "webscale" distributed datastore.
+ # | `memcached` | A non persistent "webscale" distributed datastore.
# Useful if the cached data need to be shared between
# a cluster of RADIUS servers.
- # | `rlm_cache_redis` | A persistent "webscale" clustered, sharded, data store.
+ # | `redis` | A persistent "webscale" clustered, sharded, data store.
# Extremely fast, and a good candidate for sharing
# data such as EAP session blobs, between a cluster of
# servers.
# |===
#
-# driver = "rlm_cache_rbtree"
+# driver = "rbtree"
#
# NOTE: Some drivers accept specific options, to set them a config section with the
#
# driver:: `cache` driver.
#
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
#
# key:: The `cache` key.
#
# driver:: `cache` driver.
#
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
#
# key:: `cache` key.
return CMP(a, b);
}
+/** Generic callback for CONF_PARSER to load a submodule
+ *
+ * CONF_PARSER entry should point to a module_instance_t field in the instance data
+ *
+ * @param[in] ctx unused.
+ * @param[out] out A pointer to a pointer to a module_instance_t.
+ * @param[in] parent This _must_ point to the instance data of the parent
+ * module.
+ * @param[in] ci The CONF_PAIR containing the name of the submodule to load.
+ * @param[in] rule unused.
+ * @return
+ * - 0 on success.
+ * - -1 if we failed to load the submodule.
+ */
+int module_submodule_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
+ CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
+{
+ char const *name = cf_pair_value(cf_item_to_pair(ci));
+ CONF_SECTION *cs = cf_item_to_section(cf_parent(ci));
+ CONF_SECTION *submodule_cs;
+ module_instance_t *mi;
+
+ /*
+ * We assume the submodule's config is the
+ * in a section with the same name as
+ * the submodule.
+ */
+ submodule_cs = cf_section_find(cs, name, NULL);
+
+ /*
+ * Allocate an empty section if one doesn't exist
+ * this is so defaults get parsed.
+ */
+ if (!submodule_cs) submodule_cs = cf_section_alloc(cs, cs, name, NULL);
+
+ mi = module_bootstrap(DL_MODULE_TYPE_SUBMODULE, module_by_data(parent), submodule_cs);
+ if (unlikely(mi == NULL)) {
+ cf_log_err(submodule_cs, "Failed loading submodule");
+ return -1;
+ }
+
+ *((module_instance_t **)out) = mi;
+
+ return 0;
+}
+
+
/** Find an existing module instance by its name and parent
*
* @param[in] parent to qualify search with.
* Do this after inserting the module instance into the tree
*/
if (dl_module_conf_parse(mi->dl_inst) < 0) {
- TALLOC_FREE(mi->dl_inst);
- return -1;
+ TALLOC_FREE(mi);
+ return NULL;
}
/*
module_method_t func; //!< State function.
} module_state_func_table_t;
+
+/** @name Callbacks for the CONF_PARSER
+ *
+ * @{
+ */
+int module_submodule_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
+ CONF_ITEM *ci, UNUSED CONF_PARSER const *rule);
+/** @} */
+
/** @name Module and module thread lookup
*
* @{
extern module_rlm_t rlm_cache;
static const CONF_PARSER module_config[] = {
- { FR_CONF_OFFSET("driver", FR_TYPE_STRING, rlm_cache_config_t, driver_name), .dflt = "rlm_cache_rbtree" },
+ { FR_CONF_OFFSET("driver", FR_TYPE_VOID, rlm_cache_t, driver_submodule), .dflt = "rbtree",
+ .func = module_submodule_parse },
{ FR_CONF_OFFSET("key", FR_TYPE_TMPL | FR_TYPE_REQUIRED, rlm_cache_config_t, key) },
{ FR_CONF_OFFSET("ttl", FR_TYPE_TIME_DELTA, rlm_cache_config_t, ttl), .dflt = "500s" },
{ FR_CONF_OFFSET("max_entries", FR_TYPE_UINT32, rlm_cache_config_t, max_entries), .dflt = "0" },
return 0;
}
- return inst->driver->acquire(out, &inst->config, inst->driver_inst->dl_inst->data, request);
+ return inst->driver->acquire(out, &inst->config, inst->driver_submodule->dl_inst->data, request);
}
/** Release a handle we previously acquired
if (!inst->driver->release) return;
if (!handle || !*handle) return;
- inst->driver->release(&inst->config, inst->driver_inst->dl_inst->data, request, *handle);
+ inst->driver->release(&inst->config, inst->driver_submodule->dl_inst->data, request, *handle);
*handle = NULL;
}
{
fr_assert(inst->driver->reconnect);
- return inst->driver->reconnect(handle, &inst->config, inst->driver_inst->dl_inst->data, request);
+ return inst->driver->reconnect(handle, &inst->config, inst->driver_submodule->dl_inst->data, request);
}
/** Allocate a cache entry
*/
static rlm_cache_entry_t *cache_alloc(rlm_cache_t const *inst, request_t *request)
{
- if (inst->driver->alloc) return inst->driver->alloc(&inst->config, inst->driver_inst->dl_inst->data, request);
+ if (inst->driver->alloc) return inst->driver->alloc(&inst->config, inst->driver_submodule->dl_inst->data, request);
return talloc_zero(NULL, rlm_cache_entry_t);
}
*out = NULL;
for (;;) {
- ret = inst->driver->find(&c, &inst->config, inst->driver_inst->dl_inst->data, request, *handle, key, key_len);
+ ret = inst->driver->find(&c, &inst->config, inst->driver_submodule->dl_inst->data, request, *handle, key, key_len);
switch (ret) {
case CACHE_RECONNECT:
RDEBUG2("Reconnecting...");
fr_box_time(request->packet->timestamp));
expired:
- inst->driver->expire(&inst->config, inst->driver_inst->dl_inst->data, request, handle, c->key, c->key_len);
+ inst->driver->expire(&inst->config, inst->driver_submodule->dl_inst->data, request, handle, c->key, c->key_len);
cache_free(inst, &c);
RETURN_MODULE_NOTFOUND; /* Couldn't find a non-expired entry */
}
rlm_cache_handle_t **handle, uint8_t const *key, size_t key_len)
{
RDEBUG2("Expiring cache entry");
- for (;;) switch (inst->driver->expire(&inst->config, inst->driver_inst->dl_inst->data, request,
+ for (;;) switch (inst->driver->expire(&inst->config, inst->driver_submodule->dl_inst->data, request,
*handle, key, key_len)) {
case CACHE_RECONNECT:
if (cache_reconnect(handle, inst, request) == 0) continue;
TALLOC_CTX *pool;
if ((inst->config.max_entries > 0) && inst->driver->count &&
- (inst->driver->count(&inst->config, inst->driver_inst->dl_inst->data, request, handle) > inst->config.max_entries)) {
+ (inst->driver->count(&inst->config, inst->driver_submodule->dl_inst->data, request, handle) > inst->config.max_entries)) {
RWDEBUG("Cache is full: %d entries", inst->config.max_entries);
RETURN_MODULE_FAIL;
}
for (;;) {
cache_status_t ret;
- ret = inst->driver->insert(&inst->config, inst->driver_inst->dl_inst->data, request, *handle, c);
+ ret = inst->driver->insert(&inst->config, inst->driver_submodule->dl_inst->data, request, *handle, c);
switch (ret) {
case CACHE_RECONNECT:
if (cache_reconnect(handle, inst, request) == 0) continue;
if (!inst->driver->set_ttl) for (;;) {
cache_status_t ret;
- ret = inst->driver->insert(&inst->config, inst->driver_inst->dl_inst->data, request, *handle, c);
+ ret = inst->driver->insert(&inst->config, inst->driver_submodule->dl_inst->data, request, *handle, c);
switch (ret) {
case CACHE_RECONNECT:
if (cache_reconnect(handle, inst, request) == 0) continue;
for (;;) {
cache_status_t ret;
- ret = inst->driver->set_ttl(&inst->config, inst->driver_inst->dl_inst->data, request, *handle, c);
+ ret = inst->driver->set_ttl(&inst->config, inst->driver_submodule->dl_inst->data, request, *handle, c);
switch (ret) {
case CACHE_RECONNECT:
if (cache_reconnect(handle, inst, request) == 0) continue;
static int mod_bootstrap(module_inst_ctx_t const *mctx)
{
rlm_cache_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_cache_t );
- CONF_SECTION *conf = mctx->inst->conf;
- CONF_SECTION *driver_cs;
- char const *name;
xlat_t *xlat;
- name = strrchr(inst->config.driver_name, '_');
- if (!name) {
- name = inst->config.driver_name;
- } else {
- name++;
- }
-
- driver_cs = cf_section_find(conf, name, NULL);
- if (!driver_cs) {
- driver_cs = cf_section_alloc(conf, conf, name, NULL);
- if (!driver_cs) return -1;
- }
-
- /*
- * Load the appropriate driver for our backend
- */
- inst->driver_inst = module_bootstrap(DL_MODULE_TYPE_SUBMODULE, module_by_data(inst), driver_cs);
- if (!inst->driver_inst) {
- cf_log_err(driver_cs, "Failed loading driver");
- return -1;
- }
- inst->driver = (rlm_cache_driver_t const *)inst->driver_inst->dl_inst->module->common;
-
- /*
- * Sanity check for crazy people.
- */
- if (strncmp(inst->config.driver_name, "rlm_cache_", 10) != 0) {
- cf_log_err(conf, "\"%s\" is NOT an Cache driver!", inst->config.driver_name);
- return -1;
- }
+ inst->driver = (rlm_cache_driver_t const *)inst->driver_submodule->dl_inst->module->common;
/*
* Non optional fields and callbacks
* rlm_cache instance data.
*/
typedef struct {
- char const *driver_name; //!< Driver name.
tmpl_t *key; //!< What to expand to get the value of the key.
fr_time_delta_t ttl; //!< How long an entry is valid for.
uint32_t max_entries; //!< Maximum entries allowed.
typedef struct {
rlm_cache_config_t config; //!< Must come first because of icky hacks.
- module_instance_t *driver_inst; //!< Driver's instance data.
+ module_instance_t *driver_submodule; //!< Driver's instance data.
rlm_cache_driver_t const *driver; //!< Driver's exported interface.
map_list_t maps; //!< Attribute map applied to users.
{ FR_CONF_OFFSET_IS_SET("default_eap_type", FR_TYPE_VOID, rlm_eap_t, default_method), .func = eap_type_parse },
- { FR_CONF_OFFSET("type", FR_TYPE_VOID | FR_TYPE_MULTI | FR_TYPE_NOT_EMPTY, rlm_eap_t, submodule_cs),
+ { FR_CONF_OFFSET("type", FR_TYPE_VOID | FR_TYPE_MULTI | FR_TYPE_NOT_EMPTY, rlm_eap_t, type_submodules),
.func = submodule_parse },
{ FR_CONF_OFFSET("ignore_unknown_eap_types", FR_TYPE_BOOL, rlm_eap_t, ignore_unknown_types), .dflt = "no" },
* - 0 on success.
* - -1 on failure.
*/
-static int submodule_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
- CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
+static int submodule_parse(TALLOC_CTX *ctx, void *out, void *parent,
+ CONF_ITEM *ci, CONF_PARSER const *rule)
{ char const *name = cf_pair_value(cf_item_to_pair(ci));
char *our_name = NULL;
char *p;
- CONF_SECTION *eap_cs = cf_item_to_section(cf_parent(ci));
- CONF_SECTION *submodule_cs;
eap_type_t method;
/*
}
method = eap_name2type(our_name);
+ talloc_free(our_name);
+
if (method == FR_EAP_METHOD_INVALID) {
talloc_free(our_name);
cf_log_err(ci, "Unknown EAP type %s", name);
case FR_EAP_METHOD_AKA:
case FR_EAP_METHOD_SIM:
{
+ CONF_SECTION *eap_cs = cf_item_to_section(cf_parent(ci));
+
module_inst_ctx_t *mctx = MODULE_INST_CTX(
((dl_module_inst_t *)cf_data_value(cf_data_find(eap_cs,
dl_module_inst_t, "rlm_eap"))));
WARN("Ignoring EAP method %s because we don't have OpenSSL support", name);
-
- talloc_free(our_name);
}
return 0;
break;
}
#endif
-
- /*
- * A bit hacky, we should really figure out a better way
- * of handling missing sections.
- */
- submodule_cs = cf_section_find(eap_cs, name, NULL);
- if (!submodule_cs) {
- submodule_cs = cf_section_alloc(eap_cs, eap_cs, name, NULL);
- cf_filename_set(submodule_cs, cf_filename(ci));
- cf_lineno_set(submodule_cs, cf_lineno(ci));
- }
-
- *(void **)out = submodule_cs;
-
- talloc_free(our_name);
-
- return 0;
+ return module_submodule_parse(ctx, out, parent, ci, rule);
}
/** Convert EAP type strings to eap_type_t values
* Because the submodule might want to look at its parent
* and we haven't completed our own bootstrap phase yet.
*/
- loaded = talloc_array_length(inst->submodule_cs);
+ loaded = talloc_array_length(inst->type_submodules);
/*
* Pre-allocate the method identity to be the number
}
for (i = 0; i < loaded; i++) {
- CONF_SECTION *submodule_cs = inst->submodule_cs[i];
+ module_instance_t *submodule_inst = inst->type_submodules[i];
rlm_eap_submodule_t const *submodule;
- module_instance_t *submodule_inst;
- if (!submodule_cs) continue; /* Skipped as we don't have SSL support */
+ if (!submodule_inst) continue; /* Skipped as we don't have SSL support */
- submodule_inst = module_bootstrap(DL_MODULE_TYPE_SUBMODULE, module_by_data(inst), submodule_cs);
- if (!submodule_inst) return -1;
submodule = (rlm_eap_submodule_t const *)submodule_inst->dl_inst->module->common;
/*
if (inst->methods[method].submodule) {
CONF_SECTION *conf = inst->methods[method].submodule_inst->dl_inst->conf;
- cf_log_err(submodule_cs, "Duplicate EAP-Type %s. Conflicting entry %s[%u]",
+ cf_log_err(submodule_inst->dl_inst->conf,
+ "Duplicate EAP-Type %s. Conflicting entry %s[%u]",
eap_type2name(method),
cf_filename(conf), cf_lineno(conf));
typedef struct {
char const *name; //!< Name of this instance.
- CONF_SECTION **submodule_cs; //!< Configuration sections for the submodules
- ///< we're going to load.
+ module_instance_t **type_submodules; //!< Submodules we loaded.
rlm_eap_method_t methods[FR_EAP_METHOD_MAX]; //!< Array of loaded (or not), submodules.
char const *default_method_name; //!< Default method to attempt to start.
rlm_eap_require_realm_t require_realm; //!< Whether we require the outer identity
///< to contain a realm.
- fr_dict_enum_value_t *auth_type;
+ fr_dict_enum_value_t *auth_type;
fr_randctx rand_pool; //!< Pool of random data.
} rlm_eap_t;
#include "rlm_radius.h"
-static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, CONF_PARSER const *rule);
static int type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, CONF_PARSER const *rule);
static int status_check_type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, CONF_PARSER const *rule);
static int status_check_update_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, CONF_PARSER const *rule);
*/
static CONF_PARSER const module_config[] = {
{ FR_CONF_OFFSET("transport", FR_TYPE_VOID, rlm_radius_t, io_submodule),
- .func = transport_parse },
+ .func = module_submodule_parse },
{ FR_CONF_OFFSET("type", FR_TYPE_UINT32 | FR_TYPE_MULTI | FR_TYPE_NOT_EMPTY | FR_TYPE_REQUIRED, rlm_radius_t, types),
.func = type_parse },
return 0;
}
-/** Wrapper around dl_instance
- *
- * @param[in] ctx to allocate data in (instance of proto_radius).
- * @param[out] out Where to write a dl_module_inst_t containing the module handle and instance.
- * @param[in] parent Base structure address.
- * @param[in] ci #CONF_PAIR specifying the name of the type module.
- * @param[in] rule unused.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-static int transport_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
- CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
-{
- rlm_radius_t *inst = talloc_get_type_abort(parent, rlm_radius_t);
- char const *name = cf_pair_value(cf_item_to_pair(ci));
- CONF_SECTION *cs = cf_item_to_section(cf_parent(ci));
- CONF_SECTION *transport_cs;
- module_instance_t *mi;
-
- fr_assert(out == &inst->io_submodule); /* Make sure we're being told to write in the right place */
-
- transport_cs = cf_section_find(cs, name, NULL);
-
- /*
- * Allocate an empty section if one doesn't exist
- * this is so defaults get parsed.
- */
- if (!transport_cs) transport_cs = cf_section_alloc(cs, cs, name, NULL);
-
- mi = module_bootstrap(DL_MODULE_TYPE_SUBMODULE, module_by_data(inst), transport_cs);
- if (unlikely(mi == NULL)) {
- cf_log_err(transport_cs, "Failed loading IO submodule");
- return -1;
- }
-
- *((module_instance_t **)out) = mi;
-
- inst->io = (rlm_radius_io_t const *)inst->io_submodule->module; /* Public symbol exported by the module */
-
- return 0;
-}
-
/** Allow for Status-Server ping checks
*
* @param[in] ctx to allocate data in (instance of proto_radius).
rlm_radius_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_radius_t);
CONF_SECTION *conf = mctx->inst->conf;
+ inst->io = (rlm_radius_io_t const *)inst->io_submodule->module; /* Public symbol exported by the module */
inst->name = mctx->inst->name;
/*
extern module_rlm_t rlm_sql;
-static int driver_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
- CONF_ITEM *ci, UNUSED CONF_PARSER const *rule);
-
/*
* So we can do pass2 xlat checks on the queries.
*/
};
static const CONF_PARSER module_config[] = {
- { FR_CONF_OFFSET("driver", FR_TYPE_VOID, rlm_sql_t, driver_submodule), .dflt = "rlm_sql_null",
- .func = driver_parse },
+ { FR_CONF_OFFSET("driver", FR_TYPE_VOID, rlm_sql_t, driver_submodule), .dflt = "null",
+ .func = module_submodule_parse },
{ FR_CONF_OFFSET("server", FR_TYPE_STRING, rlm_sql_config_t, sql_server), .dflt = "" }, /* Must be zero length so drivers can determine if it was set */
{ FR_CONF_OFFSET("port", FR_TYPE_UINT32, rlm_sql_config_t, sql_port), .dflt = "0" },
{ FR_CONF_OFFSET("login", FR_TYPE_STRING, rlm_sql_config_t, sql_login), .dflt = "" },
{ NULL }
};
-static int driver_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent,
- CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
-{
- rlm_sql_t *inst = talloc_get_type_abort(parent, rlm_sql_t);
- char const *name = cf_pair_value(cf_item_to_pair(ci));
- CONF_SECTION *cs = cf_item_to_section(cf_parent(ci));
- CONF_SECTION *driver_cs;
- module_instance_t *mi;
-
- fr_assert(out == &inst->driver_submodule); /* Make sure we're being told to write in the right place */
-
- driver_cs = cf_section_find(cs, name, NULL);
-
- /*
- * Allocate an empty section if one doesn't exist
- * this is so defaults get parsed.
- */
- if (!driver_cs) driver_cs = cf_section_alloc(cs, cs, name, NULL);
-
- mi = module_bootstrap(DL_MODULE_TYPE_SUBMODULE, module_by_data(parent), driver_cs);
- if (unlikely(mi == NULL)) {
- cf_log_err(driver_cs, "Failed loading SQL driver");
- return -1;
- }
-
- *((module_instance_t **)out) = mi;
-
- inst->driver = (rlm_sql_driver_t const *)inst->driver_submodule->module; /* Public symbol exported by the submodule */
-
- return 0;
-}
-
/*
* Fall-Through checking function from rlm_files.c
*/
xlat_arg_parser_t *sql_xlat_arg;
inst->name = mctx->inst->name; /* Need this for functions in sql.c */
+ inst->driver = (rlm_sql_driver_t const *)inst->driver_submodule->module; /* Public symbol exported by the submodule */
/*
* Register the group comparison attribute
#
# driver:: `cache` driver.
#
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
#
# key:: The `cache` key.
# Used by cache-logic
cache {
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
key = "%{Tmp-String-0}"
ttl = 2
}
cache cache_update {
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
key = "%{Tmp-String-0}"
ttl = 2
# Test some exotic keys
#
cache cache_bin_key_octets {
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
key = &Tmp-Octets-0
ttl = 2
}
cache cache_bin_key_ipaddr {
- driver = "rlm_cache_rbtree"
+ driver = "rbtree"
key = &Tmp-IP-Address-0
ttl = 2
# Used by cache-logic
cache {
- driver = "rlm_cache_redis"
+ driver = "redis"
redis {
server = $ENV{CACHE_REDIS_TEST_SERVER}:30001
}
cache cache_update {
- driver = "rlm_cache_redis"
+ driver = "redis"
redis {
server = $ENV{CACHE_REDIS_TEST_SERVER}:30001
# Test some exotic keys
#
cache cache_bin_key_octets {
- driver = "rlm_cache_redis"
+ driver = "redis"
redis {
server = $ENV{CACHE_REDIS_TEST_SERVER}:30001
}
cache cache_bin_key_ipaddr {
- driver = "rlm_cache_redis"
+ driver = "redis"
redis {
server = $ENV{CACHE_REDIS_TEST_SERVER}:30001