From: Alan T. DeKok Date: Thu, 23 Apr 2009 09:00:10 +0000 (+0200) Subject: Allow virtual servers to be reloaded dynamically on HUP X-Git-Tag: release_2_1_7~194 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2073a04826e8fe5f1d65f5518324491c690126dd;p=thirdparty%2Ffreeradius-server.git Allow virtual servers to be reloaded dynamically on HUP --- diff --git a/src/include/modules.h b/src/include/modules.h index 0034abcb3c5..6b8e211483c 100644 --- a/src/include/modules.h +++ b/src/include/modules.h @@ -70,4 +70,11 @@ int module_post_proxy(int type, REQUEST *request); int module_post_auth(int type, REQUEST *request); int indexed_modcall(int comp, int idx, REQUEST *request); +/* + * For now, these are strongly tied together. + */ +int virtual_servers_load(CONF_SECTION *config); +void virtual_servers_free(time_t when); + + #endif /* RADIUS_MODULES_H */ diff --git a/src/main/mainconfig.c b/src/main/mainconfig.c index 91bd158a524..5cd517716cb 100644 --- a/src/main/mainconfig.c +++ b/src/main/mainconfig.c @@ -62,6 +62,14 @@ struct main_config_t mainconfig; char *request_log_file = NULL; char *debug_condition = NULL; +typedef struct cached_config_t { + struct cached_config_t *next; + time_t created; + CONF_SECTION *cs; +} cached_config_t; + +static cached_config_t *cs_cache = NULL; + /* * Temporary local variables for parsing the configuration * file. @@ -730,6 +738,7 @@ int read_mainconfig(int reload) CONF_PAIR *cp; CONF_SECTION *cs; struct stat statbuf; + cached_config_t *cc; char buffer[1024]; if (stat(radius_dir, &statbuf) < 0) { @@ -913,6 +922,13 @@ int read_mainconfig(int reload) } } + cc = rad_malloc(sizeof(*cc)); + memset(cc, 0, sizeof(*cc)); + + cc->cs = cs; + rad_assert(cs_cache == NULL); + cs_cache = cc; + return 0; } @@ -921,11 +937,23 @@ int read_mainconfig(int reload) */ int free_mainconfig(void) { + cached_config_t *cc, *next; + + virtual_servers_free(0); + + /* + * Free all of the cached configurations. + */ + for (cc = cs_cache; cc != NULL; cc = next) { + next = cc->next; + cf_section_free(&cc->cs); + free(cc); + } + /* * Clean up the configuration data * structures. */ - cf_section_free(&mainconfig.config); realms_free(); listen_free(&mainconfig.listen); dict_free(); @@ -935,5 +963,35 @@ int free_mainconfig(void) void hup_mainconfig(void) { + cached_config_t *cc; + CONF_SECTION *cs; + char buffer[1024]; + + /* Read the configuration file */ + snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf", + radius_dir, mainconfig.name); + if ((cs = cf_file_read(buffer)) == NULL) { + radlog(L_ERR, "Failed to re-read %s", buffer); + return; + } + + cc = rad_malloc(sizeof(*cc)); + memset(cc, 0, sizeof(*cc)); + + cc->created = time(NULL); + cc->cs = cs; + cc->next = cs_cache; + cs_cache = cc; + + /* + * Load new servers BEFORE freeing old ones. + */ + virtual_servers_load(cs); + + virtual_servers_free(cc->created - 120); + + /* + * Unfortunatelty... we use the OLD configuration here. + */ module_hup(cf_section_sub_find(mainconfig.config, "modules")); } diff --git a/src/main/modules.c b/src/main/modules.c index 1d8572ef221..1a3ffe6fc74 100644 --- a/src/main/modules.c +++ b/src/main/modules.c @@ -40,6 +40,7 @@ typedef struct indexed_modcallable { typedef struct virtual_server_t { const char *name; + time_t created; CONF_SECTION *cs; rbtree_t *components; struct virtual_server_t *next; @@ -159,6 +160,37 @@ static void virtual_server_free(virtual_server_t *server) free(server); } +void virtual_servers_free(time_t when) +{ + int i; + virtual_server_t **last; + + for (i = 0; i < VIRTUAL_SERVER_HASH_SIZE; i++) { + virtual_server_t *server, *next; + + last = &virtual_servers[i]; + for (server = virtual_servers[i]; + server != NULL; + server = next) { + next = server->next; + + /* + * If we delete it, fix the links so that + * we don't orphan anything. + * + * Otherwise, the last pointer gets set to + * the one we didn't delete. + */ + if ((when == 0) || (server->created < when)) { + *last = server->next; + virtual_server_free(server); + } else { + last = &(server->next); + } + } + } +} + static void indexed_modcallable_free(void *data) { indexed_modcallable *c = data; @@ -283,19 +315,6 @@ static void module_entry_free(void *data) */ int detach_modules(void) { - int i; - - for (i = 0; i < VIRTUAL_SERVER_HASH_SIZE; i++) { - virtual_server_t *server, *next; - - for (server = virtual_servers[i]; - server != NULL; - server = next) { - next = server->next; - virtual_server_free(server); - } - } - rbtree_free(instance_tree); rbtree_free(module_tree); @@ -839,6 +858,7 @@ static int load_byserver(CONF_SECTION *cs) memset(server, 0, sizeof(*server)); server->name = name; + server->created = time(NULL); server->cs = cs; server->components = components; @@ -1021,7 +1041,7 @@ static int load_byserver(CONF_SECTION *cs) /* * Load all of the virtual servers. */ -int virtual_server_load(CONF_SECTION *config) +int virtual_servers_load(CONF_SECTION *config) { int null_server = FALSE; CONF_SECTION *cs; @@ -1068,7 +1088,6 @@ int virtual_server_load(CONF_SECTION *config) return 0; } - int module_hup_module(CONF_SECTION *cs, module_instance_t *node, time_t when) { void *insthandle = NULL; @@ -1287,7 +1306,7 @@ int setup_modules(int reload, CONF_SECTION *config) } } - if (virtual_server_load(config) < 0) return -1; + if (virtual_servers_load(config) < 0) return -1; return 0; }