]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Allow virtual servers to be reloaded dynamically on HUP
authorAlan T. DeKok <aland@freeradius.org>
Thu, 23 Apr 2009 09:00:10 +0000 (11:00 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 23 Apr 2009 09:07:28 +0000 (11:07 +0200)
src/include/modules.h
src/main/mainconfig.c
src/main/modules.c

index 0034abcb3c561dd853a8d92269cc695a60a336e2..6b8e211483cefc613b2151f38e0117976b8d3e77 100644 (file)
@@ -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 */
index 91bd158a524a25c83ef82ccfae59f7b3e2b0bd8c..5cd517716cbaf3ffb1b6ac4268a10221f90514a9 100644 (file)
@@ -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"));
 }
index 1d8572ef221ea014d7f5732f03a88a66a528b62b..1a3ffe6fc742aebc9650cbcdd088edda06cb3762 100644 (file)
@@ -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;
 }