extern "C" {
#endif
-typedef struct fr_module_hup_t fr_module_hup_t;
-
/** Per instance data
*
* Per-instance data structure, to correlate the modules with the
CONF_SECTION *cs; //!< Configuration section in modules {}.
- time_t last_hup; //!< Last time the module was 'hupped'.
-
bool instantiated; //!< Whether the module has been instantiated yet.
bool force; //!< Force the module to return a specific code.
rlm_rcode_t code; //!< Code module will return when 'force' has
//!< has been set to true.
- fr_module_hup_t *hup; //!< Previous versions of the module's
- //!< instance data.
} module_instance_t;
module_instance_t *module_find_with_method(rlm_components_t *method,
CONF_SECTION *modules, char const *asked_name);
module_instance_t *module_find(CONF_SECTION *modules, char const *asked_name);
int module_sibling_section_find(CONF_SECTION **out, CONF_SECTION *module, char const *name);
-int module_hup(CONF_SECTION *cs, module_instance_t *node, time_t when);
-
int unlang_fixup_update(vp_map_t *map, void *ctx);
#ifdef __cplusplus
#define RLM_TYPE_THREAD_UNSAFE (1 << 0) //!< Module is not threadsafe.
//!< Server will protect calls
//!< with mutex.
-#define RLM_TYPE_HUP_SAFE (1 << 2) //!< Will be restarted on HUP.
- //!< Server will instantiated
- //!< new instance, and then
- //!< destroy old instance.
-#define RLM_TYPE_RESUMABLE (1 << 3) //!< does yield / resume
+#define RLM_TYPE_RESUMABLE (1 << 2) //!< does yield / resume
/** Module section callback
*
int modules_bootstrap(CONF_SECTION *root) CC_HINT(nonnull);
int modules_instantiate(CONF_SECTION *root) CC_HINT(nonnull);
int modules_free(void);
-int modules_hup(CONF_SECTION *modules);
int module_instance_read_only(TALLOC_CTX *ctx, char const *name);
/*
return CMD_FAIL;
}
- if ((instance->module->type & RLM_TYPE_HUP_SAFE) == 0) {
- cprintf_error(listener, "Module %s cannot be hup'd\n",
- argv[0]);
- return CMD_FAIL;
- }
-
- if (!module_hup(instance->cs, instance, time(NULL))) {
- cprintf_error(listener, "Failed to reload module\n");
- return CMD_FAIL;
- }
-
- snprintf(buffer, sizeof(buffer), "modules.%s.hup",
- cf_section_name1(instance->cs));
- trigger_exec(NULL, instance->cs, buffer, true, NULL);
+ cprintf_error(listener, "HUP - NYI in version 4", argv[0]);
- return CMD_OK;
+ return CMD_FAIL;
}
static int command_terminate(UNUSED rad_listen_t *listener,
if ((instance->module->type & RLM_TYPE_THREAD_UNSAFE) != 0) cprintf(listener, "thread-unsafe\n");
- if ((instance->module->type & RLM_TYPE_HUP_SAFE) != 0) cprintf(listener, "reload-on-hup\n");
-
return CMD_OK;
}
return 0;
}
- if ((instance->module->type & RLM_TYPE_HUP_SAFE) == 0) {
- cprintf_error(listener, "Cannot change configuration of module as it is cannot be HUP'd.\n");
- return 0;
- }
-
variables = cf_section_parse_table(instance->cs);
if (!variables) {
cprintf_error(listener, "Cannot find configuration for module\n");
}
}
-static int hup_callback(void *ctx, void *data)
-{
- CONF_SECTION *modules = ctx;
- CONF_SECTION *cs = data;
- CONF_SECTION *parent;
- char const *name;
- module_instance_t *instance;
-
- /*
- * Files may be defined in sub-sections of a module
- * config. Walk up the tree until we find the module
- * definition.
- */
- parent = cf_item_parent(cf_section_to_item(cs));
- while (parent != modules) {
- cs = parent;
- parent = cf_item_parent(cf_section_to_item(cs));
-
- /*
- * Something went wrong. Oh well...
- */
- if (!parent) return 0;
- }
-
- name = cf_section_name2(cs);
- if (!name) name = cf_section_name1(cs);
-
- instance = module_find(modules, name);
- if (!instance) return 0;
-
- if ((instance->module->type & RLM_TYPE_HUP_SAFE) == 0) return 0;
-
- if (!module_hup(instance->cs, instance, time(NULL))) return 0;
-
- return 1;
-}
-
void main_config_hup(void)
{
- int rcode;
- cached_config_t *cc;
- CONF_SECTION *cs;
- time_t when;
- char buffer[1024];
+ time_t when;
- static time_t last_hup = 0;
+ static time_t last_hup = 0;
/*
* Re-open the log file. If we can't, then keep logging
}
last_hup = when;
+#if 0
rcode = cf_file_changed(cs_cache->cs, hup_callback);
if (rcode == CF_FILE_NONE) {
INFO("HUP - No files changed. Ignoring");
INFO("HUP - Cannot read configuration files. Ignoring");
return;
}
+#endif
- /*
- * No config files have changed.
- */
- if ((rcode & CF_FILE_CONFIG) == 0) {
- if ((rcode & CF_FILE_MODULE) != 0) {
- INFO("HUP - Files loaded by a module have changed.");
-
- /*
- * FIXME: reload the module.
- */
-
- }
- return;
- }
-
- cs = cf_section_alloc(NULL, "main", NULL);
- if (!cs) return;
-
- /* Read the configuration file */
- snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf", radius_dir, main_config.name);
-
- INFO("HUP - Re-reading configuration files");
- if (cf_file_read(cs, buffer) < 0) {
- ERROR("Failed to re-read or parse %s", buffer);
- talloc_free(cs);
- return;
- }
-
- cc = talloc_zero(cs_cache, cached_config_t);
- if (!cc) {
- ERROR("Out of memory");
- return;
- }
-
- /*
- * Save the current configuration. Note that we do NOT
- * free older ones. We should probably do so at some
- * point. Doing so will require us to mark which modules
- * are still in use, and which aren't. Modules that
- * can't be HUPed always use the original configuration.
- * Modules that can be HUPed use one of the newer
- * configurations.
- */
- cc->created = time(NULL);
- cc->cs = talloc_steal(cc, cs);
- cc->next = cs_cache;
- cs_cache = cc;
-
- INFO("HUP - loading modules");
-
- /*
- * Prefer the new module configuration.
- */
- modules_hup(cf_section_sub_find(cs, "modules"));
-
- /*
- * Load the new servers.
- */
- virtual_servers_init(cs);
+ INFO("HUP - NYI in version 4"); /* Not yet implemented in v4 */
}
static TALLOC_CTX *instance_ctx = NULL;
-struct fr_module_hup_t {
- module_instance_t *mi;
- time_t when;
- void *insthandle;
- fr_module_hup_t *next;
-};
-
/*
* Ordered by component
*/
return inst;
}
-/** Free old instances from HUPs
- *
- */
-static void module_hup_free(module_instance_t *instance, time_t when)
-{
- fr_module_hup_t *mh, **last;
-
- /*
- * Walk the list, freeing up old instances.
- */
- last = &(instance->hup);
- while (*last) {
- mh = *last;
-
- /*
- * Free only every 60 seconds.
- */
- if ((when - mh->when) < 60) {
- last = &(mh->next);
- continue;
- }
-
- talloc_free(mh->insthandle);
-
- *last = mh->next;
- talloc_free(mh);
- }
-}
-
-int module_hup(CONF_SECTION *cs, module_instance_t *instance, time_t when)
-{
- void *insthandle;
- fr_module_hup_t *mh;
-
- if (!instance ||
- instance->module->bootstrap ||
- !instance->module->instantiate ||
- ((instance->module->type & RLM_TYPE_HUP_SAFE) == 0)) {
- return 1;
- }
-
- /*
- * Silently ignore multiple HUPs within a short time period.
- */
- if ((instance->last_hup + 2) >= when) return 1;
- instance->last_hup = when;
-
- cf_log_module(cs, "Trying to reload module \"%s\"", instance->name);
-
- /*
- * Parse the module configuration, and setup destructors so the
- * module's detach method is called when it's instance data is
- * about to be freed.
- */
- if (dl_module_instance_data_alloc(&insthandle, instance, instance->handle, cs) < 0) {
- cf_log_err_cs(cs, "HUP failed for module \"%s\" (parsing config failed). "
- "Using old configuration", instance->name);
-
- return 0;
- }
-
- if ((instance->module->instantiate)(cs, insthandle) < 0) {
- cf_log_err_cs(cs, "HUP failed for module \"%s\". Using old configuration.", instance->name);
- talloc_free(insthandle);
-
- return 0;
- }
-
- INFO("Module: Reloaded module \"%s\"", instance->name);
-
- module_hup_free(instance, when);
-
- /*
- * Save the old instance handle for later deletion.
- */
- mh = talloc_zero(instance_ctx, fr_module_hup_t);
- mh->mi = instance;
- mh->when = when;
- mh->insthandle = instance->data;
- mh->next = instance->hup;
- instance->hup = mh;
-
- /*
- * Replace the instance handle while the module is running.
- */
- instance->data = insthandle;
-
- /*
- * FIXME: Set a timeout to come back in 60s, so that
- * we can pro-actively clean up the old instances.
- */
-
- return 1;
-}
-
-/** Reload the configurations of modules that support it
- *
- * @param modules CONF_SECTION.
- * @return
- * - 0 on failure.
- * - 1 on success.
- */
-int modules_hup(CONF_SECTION *modules)
-{
- time_t when;
- CONF_ITEM *ci;
- CONF_SECTION *cs;
- module_instance_t *instance;
-
- if (!modules) return 0;
-
- when = time(NULL);
-
- /*
- * Loop over the modules
- */
- for (ci = cf_item_find_next(modules, NULL);
- ci != NULL;
- ci = cf_item_find_next(modules, ci)) {
- char const *instance_name;
-
- /*
- * If it's not a section, ignore it.
- */
- if (!cf_item_is_section(ci)) continue;
-
- cs = cf_item_to_section(ci);
-
- instance_name = cf_section_name2(cs);
- if (!instance_name) instance_name = cf_section_name1(cs);
-
- instance = module_find(modules, instance_name);
- if (!instance) continue;
-
- module_hup(cs, instance, when);
- }
-
- return 1;
-}
-
/** Free all modules loaded by the server
*
* @return 0.
#endif
inst->instantiated = true;
- inst->last_hup = time(NULL); /* don't let us load it, then immediately hup it */
return 0;
}
pthread_mutex_destroy(instance->mutex);
}
- /*
- * Free HUP versions of the module's instance data
- */
- module_hup_free(instance, time(NULL) + 100);
-
xlat_unregister(instance->data, instance->name, NULL);
/*
rad_module_t rlm_always = {
.magic = RLM_MODULE_INIT,
.name = "always",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(rlm_always_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_attr_filter = {
.magic = RLM_MODULE_INIT,
.name = "attr_filter",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(rlm_attr_filter_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_detail = {
.magic = RLM_MODULE_INIT,
.name = "detail",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(rlm_detail_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_files = {
.magic = RLM_MODULE_INIT,
.name = "files",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(rlm_files_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_krb5 = {
.magic = RLM_MODULE_INIT,
.name = "krb5",
- .type = RLM_TYPE_HUP_SAFE
#ifdef KRB5_IS_THREAD_SAFE
- | RLM_TYPE_THREAD_SAFE
+ .type = RLM_TYPE_THREAD_SAFE,
#endif
- ,
.inst_size = sizeof(rlm_krb5_t),
.config = module_config,
.instantiate = mod_instantiate,
{ FR_CONF_OFFSET("certificate_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_certificate_file) },
- { FR_CONF_OFFSET("private_key_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_private_key_file) }, // OK if it changes on HUP
+ { FR_CONF_OFFSET("private_key_file", PW_TYPE_FILE_INPUT, rlm_ldap_t, tls_private_key_file) },
{ FR_CONF_OFFSET("random_file", PW_TYPE_FILE_EXISTS, rlm_ldap_t, tls_random_file) },
rad_module_t rlm_linelog = {
.magic = RLM_MODULE_INIT,
.name = "linelog",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(linelog_instance_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_pap = {
.magic = RLM_MODULE_INIT,
.name = "pap",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(rlm_pap_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_passwd = {
.magic = RLM_MODULE_INIT,
.name = "passwd",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(rlm_passwd_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_radutmp = {
.magic = RLM_MODULE_INIT,
.name = "radutmp",
- .type = RLM_TYPE_THREAD_UNSAFE | RLM_TYPE_HUP_SAFE,
+ .type = RLM_TYPE_THREAD_UNSAFE,
.inst_size = sizeof(rlm_radutmp_t),
.config = module_config,
.methods = {
rad_module_t rlm_realm = {
.magic = RLM_MODULE_INIT,
.name = "realm",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(struct rlm_realm_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_securid = {
.magic = RLM_MODULE_INIT,
.name = "securid",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(rlm_securid_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_sometimes = {
.magic = RLM_MODULE_INIT,
.name = "sometimes",
- .type = RLM_TYPE_HUP_SAFE, /* needed for radmin */
.inst_size = sizeof(rlm_sometimes_t),
.config = module_config,
.instantiate = mod_instantiate,
rad_module_t rlm_winbind = {
.magic = RLM_MODULE_INIT,
.name = "winbind",
- .type = RLM_TYPE_HUP_SAFE,
.inst_size = sizeof(rlm_winbind_t),
.config = module_config,
.instantiate = mod_instantiate,