summaryrefslogtreecommitdiff
path: root/extensions/acl_wl
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/acl_wl')
-rw-r--r--extensions/acl_wl/acl_wl.c94
-rw-r--r--extensions/acl_wl/acl_wl.h4
-rw-r--r--extensions/acl_wl/aw_conf.l4
-rw-r--r--extensions/acl_wl/aw_conf.y16
-rw-r--r--extensions/acl_wl/aw_tree.c8
5 files changed, 106 insertions, 20 deletions
diff --git a/extensions/acl_wl/acl_wl.c b/extensions/acl_wl/acl_wl.c
index c28ddd9..39c7339 100644
--- a/extensions/acl_wl/acl_wl.c
+++ b/extensions/acl_wl/acl_wl.c
@@ -2,7 +2,7 @@
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@freediameter.net> *
* *
-* Copyright (c) 2011, WIDE Project and NICT *
+* Copyright (c) 2019, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
@@ -37,8 +37,17 @@
* Whitelist extension for freeDiameter.
*/
+#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 */
static int aw_validate(struct peer_info * info, int * auth, int (**cb2)(struct peer_info *))
{
@@ -53,9 +62,20 @@ static int aw_validate(struct peer_info * info, int * auth, int (**cb2)(struct p
/* 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 */
return 0;
@@ -87,20 +107,82 @@ static int aw_validate(struct peer_info * info, int * auth, int (**cb2)(struct p
return 0;
}
+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)
{
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 ) );
@@ -114,4 +196,4 @@ void fd_ext_fini(void)
aw_tree_destroy();
}
-EXTENSION_ENTRY("acl_wl", aw_entry);
+EXTENSION_ENTRY(MODULE_NAME, aw_entry);
diff --git a/extensions/acl_wl/acl_wl.h b/extensions/acl_wl/acl_wl.h
index 8606c2a..56ae203 100644
--- a/extensions/acl_wl/acl_wl.h
+++ b/extensions/acl_wl/acl_wl.h
@@ -2,7 +2,7 @@
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@freediameter.net> *
* *
-* Copyright (c) 2011, WIDE Project and NICT *
+* Copyright (c) 2019, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
@@ -43,6 +43,8 @@
#include <freeDiameter/extension.h>
+extern struct fd_list tree_root;
+
/* Parse the configuration file */
int aw_conf_handle(char * conffile);
diff --git a/extensions/acl_wl/aw_conf.l b/extensions/acl_wl/aw_conf.l
index d6b55c8..b74cc20 100644
--- a/extensions/acl_wl/aw_conf.l
+++ b/extensions/acl_wl/aw_conf.l
@@ -2,7 +2,7 @@
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@freediameter.net> *
* *
-* Copyright (c) 2013, WIDE Project and NICT *
+* Copyright (c) 2019, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
@@ -35,7 +35,7 @@
/* 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.
*/
diff --git a/extensions/acl_wl/aw_conf.y b/extensions/acl_wl/aw_conf.y
index 4ace8e5..3825aa2 100644
--- a/extensions/acl_wl/aw_conf.y
+++ b/extensions/acl_wl/aw_conf.y
@@ -2,7 +2,7 @@
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@freediameter.net> *
* *
-* Copyright (c) 2013, WIDE Project and NICT *
+* Copyright (c) 2019, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
@@ -57,6 +57,7 @@
/* Forward declaration */
int yyparse(char * conffile);
+void aw_confrestart(FILE *input_file);
static int fqdn_added = 0;
@@ -74,19 +75,20 @@ int aw_conf_handle(char * conffile)
if (aw_confin == NULL) {
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);
fclose(aw_confin);
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);
}
return 0;
@@ -98,7 +100,7 @@ int aw_conflex(YYSTYPE *lvalp, YYLTYPE *llocp);
/* Function to report the errors */
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)
fd_log_debug("%s:%d.%d-%d.%d : %s", conffile, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
@@ -130,11 +132,11 @@ conffile: /* empty grammar is OK */
| conffile FQDN
{
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;
}
;
diff --git a/extensions/acl_wl/aw_tree.c b/extensions/acl_wl/aw_tree.c
index 9b9cbd8..82e79f4 100644
--- a/extensions/acl_wl/aw_tree.c
+++ b/extensions/acl_wl/aw_tree.c
@@ -2,7 +2,7 @@
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@freediameter.net> *
* *
-* Copyright (c) 2013, WIDE Project and NICT *
+* Copyright (c) 2020, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
@@ -69,9 +69,9 @@ struct tree_item {
};
/* The root of the tree */
-static struct fd_list tree_root = FD_LIST_INITIALIZER(tree_root);
+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 */
+/* Note: we lock accesses to the tree with acl_wl_lock because of config reload */
/* The parsed name */
@@ -339,7 +339,7 @@ int aw_tree_lookup(char * name, int * result)
{
struct split_name sn;
int lbl, found;
- struct tree_item * ti;
+ struct tree_item * ti = NULL;
struct fd_list * senti, *li;
TRACE_ENTRY("%p %p", name, result);