]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
On HUP, reload a module which has changed
authorAlan T. DeKok <aland@freeradius.org>
Wed, 2 Sep 2015 19:41:48 +0000 (15:41 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 2 Sep 2015 19:41:48 +0000 (15:41 -0400)
src/include/conffile.h
src/main/conffile.c
src/main/mainconfig.c

index 3ca330f260c5778a1c79e430f56e52659950853a..62d16b028d49a338cf5d257dc7234bfe8aa13b52 100644 (file)
@@ -292,7 +292,7 @@ CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs,
 #define CF_FILE_ERROR  (1)
 #define CF_FILE_CONFIG (1 << 2)
 #define CF_FILE_MODULE (1 << 3)
-int cf_file_changed(CONF_SECTION *cs);
+int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback);
 
 extern CONF_SECTION *root_config;
 extern bool cf_new_escape;
index cad30b4191c93109b71684b56fd60278d089f28c..855c0bb32ab943c8f7a9e47e2626cc21952e250f 100644 (file)
@@ -412,20 +412,27 @@ static bool cf_file_input(CONF_SECTION *cs, char const *filename)
 }
 
 
+typedef struct cf_file_callback_t {
+       int             rcode;
+       rb_walker_t     callback;
+       CONF_SECTION    *modules;
+} cf_file_callback_t;
+
+
 /*
  *     Return 0 for keep going, 1 for stop.
  */
 static int file_callback(void *ctx, void *data)
 {
-       int *rcode = ctx;
-       struct stat buf;
+       cf_file_callback_t *cb = ctx;
        cf_file_t *file = data;
+       struct stat buf;
 
        /*
         *      The file doesn't exist or we can no longer read it.
         */
        if (stat(file->filename, &buf) < 0) {
-               *rcode = CF_FILE_ERROR;
+               cb->rcode = CF_FILE_ERROR;
                return 1;
        }
 
@@ -434,9 +441,10 @@ static int file_callback(void *ctx, void *data)
         */
        if (buf.st_mtime != file->buf.st_mtime) {
                if (!file->input) {
-                       *rcode |= CF_FILE_CONFIG;
+                       cb->rcode |= CF_FILE_CONFIG;
                } else {
-                       *rcode |= CF_FILE_MODULE;
+                       (void) cb->callback(cb->modules, file->cs);
+                       cb->rcode |= CF_FILE_MODULE;
                }
        }
 
@@ -447,11 +455,11 @@ static int file_callback(void *ctx, void *data)
 /*
  *     See if any of the files have changed.
  */
-int cf_file_changed(CONF_SECTION *cs)
+int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback)
 {
-       int rcode;
        CONF_DATA *cd;
        CONF_SECTION *top;
+       cf_file_callback_t cb;
        rbtree_t *tree;
 
        top = cf_top_section(cs);
@@ -460,10 +468,13 @@ int cf_file_changed(CONF_SECTION *cs)
 
        tree = cd->data;
 
-       rcode = CF_FILE_NONE;
-       (void) rbtree_walk(tree, RBTREE_IN_ORDER, file_callback, &rcode);
+       cb.rcode = CF_FILE_NONE;
+       cb.callback = callback;
+       cb.modules = cf_section_sub_find(cs, "modules");
 
-       return rcode;
+       (void) rbtree_walk(tree, RBTREE_IN_ORDER, file_callback, &cb);
+
+       return cb.rcode;
 }
 
 static int _cf_section_free(CONF_SECTION *cs)
index fd6881d70a10389080791c5f5640c70559e1ad05..550e025579bf5c511e3b6715e3c5b17348f5364e 100644 (file)
@@ -25,6 +25,7 @@ RCSID("$Id$")
 
 #include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/modules.h>
+#include <freeradius-devel/modpriv.h>
 #include <freeradius-devel/rad_assert.h>
 
 #include <sys/stat.h>
@@ -1081,6 +1082,43 @@ void hup_logfile(void)
        }
 }
 
+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 *mi;
+
+       /*
+        *      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);
+
+       mi = module_find(modules, name);
+       if (!mi) return 0;
+
+       if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) return 0;
+
+       if (!module_hup_module(mi->cs, mi, time(NULL))) return 0;
+
+       return 0;
+}
+
 void main_config_hup(void)
 {
        int rcode;
@@ -1110,7 +1148,7 @@ void main_config_hup(void)
        }
        last_hup = when;
 
-       rcode = cf_file_changed(cs_cache->cs);
+       rcode = cf_file_changed(cs_cache->cs, hup_callback);
        if (rcode == CF_FILE_NONE) {
                INFO("HUP - No files changed.  Ignoring");
                return;