*/
INFO("%s", fr_debug_state_to_msg(fr_debug_state));
+ /*
+ * Track configuration versions. This lets us know if the configuration changed.
+ */
+ if (fr_debug_lvl) {
+ uint8_t digest[16];
+
+ cf_md5_final(digest);
+
+ INFO("Configuration version: %02x%02x-%02x%02x-%02x%02x-%02x%02x",
+ digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7]);
+ }
+
/*
* Call this again now we've loaded the configuration. Yes I know...
*/
#include <freeradius-devel/util/file.h>
#include <freeradius-devel/util/misc.h>
#include <freeradius-devel/util/perm.h>
+#include <freeradius-devel/util/md5.h>
#include <freeradius-devel/util/syserror.h>
#include <sys/types.h>
}
+static fr_md5_ctx_t *cf_md5_ctx = NULL;
+
+void cf_md5_init(void)
+{
+ cf_md5_ctx = fr_md5_ctx_alloc();
+}
+
+
+static void cf_md5_update(char const *p)
+{
+ if (!cf_md5_ctx) return;
+
+ fr_md5_update(cf_md5_ctx, (uint8_t const *)p, strlen(p));
+}
+
+void cf_md5_final(uint8_t *digest)
+{
+ if (!cf_md5_ctx) {
+ memset(digest, 0, MD5_DIGEST_LENGTH);
+ return;
+ }
+
+ fr_md5_final(digest, cf_md5_ctx);
+ fr_md5_ctx_free(cf_md5_ctx);
+ cf_md5_ctx = NULL;
+}
+
static int cf_file_fill(cf_stack_t *stack)
{
bool at_eof, has_spaces;
* Get data, and remember if we are at EOF.
*/
at_eof = (fgets(stack->fill, stack->bufsize - (stack->fill - stack->buff[0]), frame->fp) == NULL);
+ cf_md5_update(stack->fill);
frame->lineno++;
/*
bool cf_file_check(CONF_PAIR *cp, bool check_perms);
void cf_file_check_user(uid_t uid, gid_t gid);
+void cf_md5_init(void);
+void cf_md5_final(uint8_t *digest);
+
/*
* Config file writing
*/
if (cf_section_rules_push(cs, lib_dir_on_read_config) < 0) goto failure;
if (cf_section_rules_push(cs, virtual_servers_on_read_config) < 0) goto failure;
+ /*
+ * Track the status of the configuration.
+ */
+ if (fr_debug_lvl) cf_md5_init();
+
/* Read the configuration file */
snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf", config->raddb_dir, config->name);
if (cf_file_read(cs, buffer) < 0) {