summaryrefslogtreecommitdiff
path: root/extensions/rt_default
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/rt_default')
-rw-r--r--extensions/rt_default/rt_default.c81
-rw-r--r--extensions/rt_default/rt_default.h5
-rw-r--r--extensions/rt_default/rtd_conf.y17
-rw-r--r--extensions/rt_default/rtd_rules.c52
4 files changed, 132 insertions, 23 deletions
diff --git a/extensions/rt_default/rt_default.c b/extensions/rt_default/rt_default.c
index dd4057a..0fdfd44 100644
--- a/extensions/rt_default/rt_default.c
+++ b/extensions/rt_default/rt_default.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) 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,38 +37,101 @@
* Configurable routing of messages for freeDiameter.
*/
+#include <signal.h>
+
#include "rt_default.h"
+#define MODULE_NAME "rt_default"
+
+#include <pthread.h>
+
+static pthread_rwlock_t rtd_lock;
+
+static char *rtd_config_file;
+
/* The callback called on new messages */
static int rtd_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
{
struct msg * msg = *pmsg;
TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
+ int ret;
CHECK_PARAMS(msg && candidates);
-
+
+ if (pthread_rwlock_rdlock(&rtd_lock) != 0) {
+ fd_log_notice("%s: read-lock failed, skipping handler", MODULE_NAME);
+ return 0;
+ }
/* Simply pass it to the appropriate function */
if (FD_IS_LIST_EMPTY(candidates)) {
- return 0;
+ ret = 0;
} else {
- return rtd_process( msg, candidates );
+ ret = rtd_process( msg, candidates );
+ }
+ if (pthread_rwlock_unlock(&rtd_lock) != 0) {
+ fd_log_notice("%s: read-unlock failed after rtd_out, exiting", MODULE_NAME);
+ exit(1);
}
+ return ret;
}
/* handler */
static struct fd_rt_out_hdl * rtd_hdl = NULL;
+static volatile int in_signal_handler = 0;
+
+/* signal handler */
+static void sig_hdlr(void)
+{
+ 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(&rtd_lock) != 0) {
+ fd_log_error("%s: locking failed, aborting config reload", MODULE_NAME);
+ return;
+ }
+ rtd_conf_reload(rtd_config_file);
+ if (pthread_rwlock_unlock(&rtd_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 rtd_entry(char * conffile)
{
TRACE_ENTRY("%p", conffile);
-
+
+ rtd_config_file = conffile;
+ pthread_rwlock_init(&rtd_lock, NULL);
+
+ if (pthread_rwlock_wrlock(&rtd_lock) != 0) {
+ fd_log_notice("%s: write-lock failed, aborting", MODULE_NAME);
+ return EDEADLK;
+ }
+
/* Initialize the repo */
CHECK_FCT( rtd_init() );
/* Parse the configuration file */
CHECK_FCT( rtd_conf_handle(conffile) );
-
+
+ if (pthread_rwlock_unlock(&rtd_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));
+
#if 0
/* Dump the rules */
rtd_dump();
@@ -91,9 +154,11 @@ void fd_ext_fini(void)
/* Destroy the data */
rtd_fini();
-
+
+ pthread_rwlock_destroy(&rtd_lock);
+
/* Done */
return ;
}
-EXTENSION_ENTRY("rt_default", rtd_entry);
+EXTENSION_ENTRY(MODULE_NAME, rtd_entry);
diff --git a/extensions/rt_default/rt_default.h b/extensions/rt_default/rt_default.h
index 8ecaa5e..b37e796 100644
--- a/extensions/rt_default/rt_default.h
+++ b/extensions/rt_default/rt_default.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 *
@@ -82,5 +82,8 @@ int rtd_add(enum rtd_crit_type ct, char * criteria, enum rtd_targ_type tt, char
/* Process a message & peer list through the rules repository, updating the scores */
int rtd_process( struct msg * msg, struct fd_list * candidates );
+/* Reload the config file */
+void rtd_conf_reload(char *config_file);
+
/* For debug: dump the rule repository */
void rtd_dump(void);
diff --git a/extensions/rt_default/rtd_conf.y b/extensions/rt_default/rtd_conf.y
index d6ed329..e02303c 100644
--- a/extensions/rt_default/rtd_conf.y
+++ b/extensions/rt_default/rtd_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 *
@@ -54,6 +54,7 @@
/* Forward declaration */
int yyparse(char * conffile);
+void rtd_confrestart(FILE *input_file);
static int rules_added = 0;
@@ -65,25 +66,27 @@ int rtd_conf_handle(char * conffile)
TRACE_ENTRY("%p", conffile);
- TRACE_DEBUG (FULL, "Parsing configuration file: %s...", conffile);
-
+ TRACE_DEBUG (FULL, "rt_default: Parsing configuration file: %s...", conffile);
+
+ rules_added = 0;
rtd_confin = fopen(conffile, "r");
if (rtd_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, "rt_default: Error occurred, message logged -- configuration file.");
return ret;
}
+ rtd_confrestart(rtd_confin);
ret = yyparse(conffile);
fclose(rtd_confin);
if (ret != 0) {
- TRACE_DEBUG (INFO, "Unable to parse the configuration file.");
+ TRACE_DEBUG (INFO, "rt_default: Unable to parse the configuration file.");
return EINVAL;
} else {
- TRACE_DEBUG(FULL, "Added %d RULES routing entries successfully.", rules_added);
+ TRACE_DEBUG(INFO, "rt_default: Added %d RULES routing entries successfully.", rules_added);
}
return 0;
@@ -95,7 +98,7 @@ int rtd_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, "rt_default: 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);
diff --git a/extensions/rt_default/rtd_rules.c b/extensions/rt_default/rtd_rules.c
index 8d3a53c..c1cfe7f 100644
--- a/extensions/rt_default/rtd_rules.c
+++ b/extensions/rt_default/rtd_rules.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) 2019, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
@@ -46,7 +46,7 @@
*
* Under each TARGET element, we have the list of RULES that are defined for this target, ordered by CRITERIA type, then is_regex, then string value.
*
- * Note: Except during configuration parsing and module termination, the lists are only ever accessed read-only, so we do not need a lock.
+ * Note: Access these only when holding rtd_lock; config reload may change the underlying data.
*/
/* Structure to hold the data that is used for matching. */
@@ -389,19 +389,23 @@ int rtd_init(void)
return 0;
}
-/* Destroy the module's data */
-void rtd_fini(void)
+static void free_targets(void)
{
int i;
-
- TRACE_ENTRY();
for (i = 0; i < RTD_TAR_MAX; i++) {
while (!FD_IS_LIST_EMPTY(&TARGETS[i])) {
del_target((struct target *) TARGETS[i].next);
}
}
-
+}
+
+/* Destroy the module's data */
+void rtd_fini(void)
+{
+ TRACE_ENTRY();
+
+ free_targets();
}
/* Add a new rule in the repository. this is called when the configuration file is being parsed */
@@ -494,6 +498,40 @@ int rtd_add(enum rtd_crit_type ct, char * criteria, enum rtd_targ_type tt, char
return 0;
}
+void rtd_conf_reload(char *config_file)
+{
+ /* save old config in case reload goes wrong */
+ struct fd_list old_config[RTD_TAR_MAX];
+ int i;
+
+ for (i = 0; i < RTD_TAR_MAX; i++) {
+ old_config[i] = TARGETS[i];
+ }
+ memset(TARGETS, 0, sizeof(*TARGETS) * RTD_TAR_MAX);
+ for (i = 0; i < RTD_TAR_MAX; i++) {
+ fd_list_init(&TARGETS[i], NULL);
+ }
+
+ if (rtd_conf_handle(config_file) != 0) {
+ fd_log_notice("rt_default: error reloading configuration, restoring previous configuration");
+ free_targets();
+ for (i = 0; i < RTD_TAR_MAX; i++) {
+ TARGETS[i] = old_config[i];
+ }
+ } else {
+ /* this has to be done in this weird way because the items contain back pointers referencing TARGETS */
+ struct fd_list save_config[RTD_TAR_MAX];
+ for (i = 0; i < RTD_TAR_MAX; i++) {
+ save_config[i] = TARGETS[i];
+ TARGETS[i] = old_config[i];
+ }
+ free_targets();
+ for (i = 0; i < RTD_TAR_MAX; i++) {
+ TARGETS[i] = save_config[i];
+ }
+ }
+}
+
/* Check if a message and list of eligible candidate match any of our rules, and update its score according to it. */
int rtd_process( struct msg * msg, struct fd_list * candidates )
{