Index: .hgtags
===================================================================
--- .hgtags	(revision 1353)
+++ .hgtags	(revision 1350)
@@ -80,3 +80,2 @@
 2cb8d71a405df19cf385e49e237f649589513e8d 1.2.1
 73b9f2aefb75f066d891a03a9145cc7addb2f2d3 1.3.0
-08a82e81951356c913285e9d54989e52549e8d63 1.3.1
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 1352)
+++ CMakeLists.txt	(revision 1287)
@@ -11,5 +11,5 @@
 # Version of the source code
 SET(FD_PROJECT_VERSION_MAJOR 1)
-SET(FD_PROJECT_VERSION_MINOR 3)
+SET(FD_PROJECT_VERSION_MINOR 2)
 SET(FD_PROJECT_VERSION_REV 1)
 
Index: INSTALL.Ubuntu
===================================================================
--- INSTALL.Ubuntu	(revision 1351)
+++ INSTALL.Ubuntu	(revision 1011)
@@ -47,6 +47,4 @@
 sudo apt-get -y install mercurial cmake make gcc g++ bison flex libsctp-dev libgnutls-dev libgcrypt-dev libidn11-dev ssl-cert debhelper fakeroot \
    libpq-dev libmysqlclient-dev libxml2-dev swig python-dev
-   
-# On latest Ubuntu you will need libgnutls28-dev instead of libgnutls-dev
 
 # Retrieve the latest version of the source package
Index: doc/acl_wl.conf.sample
===================================================================
--- doc/acl_wl.conf.sample	(revision 162)
+++ doc/acl_wl.conf.sample	(revision 1354)
@@ -4,4 +4,9 @@
 # maintaining this connection ourselves (as it would be the case by declaring the 
 # peer in a ConnectPeer directive).
+#
+# This extension supports configuration reload at runtime. Send
+# signal SIGUSR1 to the process to cause the process to reload its
+# config.
+#
 # The format of this file is very simple. It contains a list of peer names
 # separated by spaces or newlines. 
Index: extensions/acl_wl/acl_wl.c
===================================================================
--- extensions/acl_wl/acl_wl.c	(revision 741)
+++ extensions/acl_wl/acl_wl.c	(revision 1354)
@@ -38,5 +38,14 @@
  */
 
+#include <pthread.h>
+#include <signal.h>
+
 #include "acl_wl.h"
+
+static pthread_rwlock_t acl_wl_lock;
+
+#define MODULE_NAME "acl_wl"
+
+static char *acl_wl_config_file;
 
 /* The validator function */
@@ -54,7 +63,18 @@
 	/* Default to unknown result */
 	*auth = 0;
-	
+
+        if (pthread_rwlock_rdlock(&acl_wl_lock) != 0) {
+		fd_log_notice("%s: read-lock failed, skipping handler", MODULE_NAME);
+		return 0;
+	}
+
 	/* Now search the peer in our tree */
 	CHECK_FCT( aw_tree_lookup(info->pi_diamid, &res) );
+
+        if (pthread_rwlock_unlock(&acl_wl_lock) != 0) {
+		fd_log_notice("%s: read-unlock failed after aw_tree_lookup, exiting", MODULE_NAME);
+		exit(1);
+	}
+
 	if (res < 0) {
 		/* The peer is not whitelisted */
@@ -88,4 +108,49 @@
 }
 
+static volatile int in_signal_handler = 0;
+
+/* signal handler */
+static void sig_hdlr(void)
+{
+	struct fd_list old_tree;
+
+	if (in_signal_handler) {
+		fd_log_error("%s: already handling a signal, ignoring new one", MODULE_NAME);
+		return;
+	}
+	in_signal_handler = 1;
+
+	if (pthread_rwlock_wrlock(&acl_wl_lock) != 0) {
+		fd_log_error("%s: locking failed, aborting config reload", MODULE_NAME);
+		return;
+	}
+
+	/* save old config in case reload goes wrong */
+	old_tree = tree_root;
+	fd_list_init(&tree_root, NULL);
+
+	if (aw_conf_handle(acl_wl_config_file) != 0) {
+		fd_log_error("%s: error reloading configuration, restoring previous configuration", MODULE_NAME);
+		aw_tree_destroy();
+		tree_root = old_tree;
+	} else {
+		struct fd_list new_tree;
+		new_tree = tree_root;
+		tree_root = old_tree;
+		aw_tree_destroy();
+		tree_root = new_tree;
+	}
+
+	if (pthread_rwlock_unlock(&acl_wl_lock) != 0) {
+		fd_log_error("%s: unlocking failed after config reload, exiting", MODULE_NAME);
+		exit(1);
+	}
+
+	fd_log_notice("%s: reloaded configuration", MODULE_NAME);
+
+	in_signal_handler = 0;
+}
+
+
 /* entry point */
 static int aw_entry(char * conffile)
@@ -93,13 +158,30 @@
 	TRACE_ENTRY("%p", conffile);
 	CHECK_PARAMS(conffile);
-	
+
+	acl_wl_config_file = conffile;
+
+        pthread_rwlock_init(&acl_wl_lock, NULL);
+
+        if (pthread_rwlock_wrlock(&acl_wl_lock) != 0) {
+                fd_log_notice("%s: write-lock failed, aborting", MODULE_NAME);
+                return EDEADLK;
+        }
+
 	/* Parse configuration file */
 	CHECK_FCT( aw_conf_handle(conffile) );
-	
+
 	TRACE_DEBUG(INFO, "Extension ACL_wl initialized with configuration: '%s'", conffile);
 	if (TRACE_BOOL(ANNOYING)) {
 		aw_tree_dump();
 	}
-	
+
+	if (pthread_rwlock_unlock(&acl_wl_lock) != 0) {
+		fd_log_notice("%s: write-unlock failed, aborting", MODULE_NAME);
+		return EDEADLK;
+	}
+
+	/* Register reload callback */
+	CHECK_FCT(fd_event_trig_regcb(SIGUSR1, MODULE_NAME, sig_hdlr));
+
 	/* Register the validator function */
 	CHECK_FCT( fd_peer_validate_register ( aw_validate ) );
@@ -115,3 +197,3 @@
 }
 
-EXTENSION_ENTRY("acl_wl", aw_entry);
+EXTENSION_ENTRY(MODULE_NAME, aw_entry);
Index: extensions/acl_wl/acl_wl.h
===================================================================
--- extensions/acl_wl/acl_wl.h	(revision 741)
+++ extensions/acl_wl/acl_wl.h	(revision 1354)
@@ -44,4 +44,6 @@
 #include <freeDiameter/extension.h>
 
+extern struct fd_list tree_root;
+
 /* Parse the configuration file */
 int aw_conf_handle(char * conffile);
Index: extensions/acl_wl/aw_conf.l
===================================================================
--- extensions/acl_wl/aw_conf.l	(revision 1057)
+++ extensions/acl_wl/aw_conf.l	(revision 1354)
@@ -36,5 +36,5 @@
 /* Lex extension's configuration parser.
  *
- * The configuration file contains a default priority, and a list of peers with optional overwite priority.
+ * The configuration file contains a default priority, and a list of peers with optional overwrite priority.
  * -- see the app_test.conf.sample file for more detail.
  */
Index: extensions/acl_wl/aw_conf.y
===================================================================
--- extensions/acl_wl/aw_conf.y	(revision 1057)
+++ extensions/acl_wl/aw_conf.y	(revision 1354)
@@ -58,4 +58,5 @@
 /* Forward declaration */
 int yyparse(char * conffile);
+void aw_confrestart(FILE *input_file);
 
 static int fqdn_added = 0;
@@ -75,8 +76,9 @@
 		ret = errno;
 		fd_log_debug("Unable to open extension configuration file %s for reading: %s", conffile, strerror(ret));
-		TRACE_DEBUG (INFO, "Error occurred, message logged -- configuration file.");
+		TRACE_DEBUG (INFO, "acl_wl: Error occurred, message logged -- configuration file.");
 		return ret;
 	}
 
+	aw_confrestart(aw_confin);
 	ret = yyparse(conffile);
 
@@ -84,8 +86,8 @@
 
 	if (ret != 0) {
-		TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+		TRACE_DEBUG (INFO, "acl_wl: Unable to parse the configuration file.");
 		return EINVAL;
 	} else {
-		TRACE_DEBUG(FULL, "Read %d FQDN entries successfully.", fqdn_added);
+		TRACE_DEBUG(FULL, "acl_wl: Read %d FQDN entries successfully.", fqdn_added);
 	}
 	
@@ -99,5 +101,5 @@
 void yyerror (YYLTYPE *ploc, char * conffile, char const *s)
 {
-	TRACE_DEBUG(INFO, "Error in configuration parsing");
+	TRACE_DEBUG(INFO, "acl_wl: Error in configuration parsing");
 	
 	if (ploc->first_line != ploc->last_line)
@@ -131,9 +133,9 @@
 			{
 				fqdn_added++;
-				TRACE_DEBUG(FULL, "Added FQDN: %s", $2);
+				TRACE_DEBUG(FULL, "acl_wl: Added FQDN: %s", $2);
 			}
 			| conffile LEX_ERROR
 			{
-				yyerror(&yylloc, conffile, "An error occurred while parsing the configuration file");
+				yyerror(&yylloc, conffile, "acl_wl: An error occurred while parsing the configuration file");
 				return EINVAL;
 			}
Index: extensions/acl_wl/aw_tree.c
===================================================================
--- extensions/acl_wl/aw_tree.c	(revision 1127)
+++ extensions/acl_wl/aw_tree.c	(revision 1354)
@@ -70,7 +70,7 @@
 
 /* The root of the tree */
-static struct fd_list tree_root = FD_LIST_INITIALIZER(tree_root);
-
-/* Note: we don't need to lock, since we add only when parsing the conf, and then read only */
+struct fd_list tree_root = FD_LIST_INITIALIZER(tree_root);
+
+/* Note: we lock accesses to the tree with acl_wl_lock because of config reload */
 
 
