diff options
Diffstat (limited to 'extensions/acl_wl')
| -rw-r--r-- | extensions/acl_wl/acl_wl.c | 94 | ||||
| -rw-r--r-- | extensions/acl_wl/acl_wl.h | 4 | ||||
| -rw-r--r-- | extensions/acl_wl/aw_conf.l | 4 | ||||
| -rw-r--r-- | extensions/acl_wl/aw_conf.y | 16 | ||||
| -rw-r--r-- | extensions/acl_wl/aw_tree.c | 8 |
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); |
