Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for reloading configuration on SIGHUP #373

Merged
merged 4 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configlexer.lex
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ rrl-ipv4-prefix-length{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_IPV4_
rrl-ipv6-prefix-length{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_IPV6_PREFIX_LENGTH;}
rrl-whitelist-ratelimit{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_WHITELIST_RATELIMIT;}
rrl-whitelist{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_WHITELIST;}
reload-config{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RELOAD_CONFIG; }
zonefiles-check{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILES_CHECK;}
zonefiles-write{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILES_WRITE;}
dnstap{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP;}
Expand Down
3 changes: 3 additions & 0 deletions configparser.y
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ struct component {
%token VAR_MINIMAL_RESPONSES
%token VAR_CONFINE_TO_ZONE
%token VAR_REFUSE_ANY
%token VAR_RELOAD_CONFIG
%token VAR_ZONEFILES_CHECK
%token VAR_ZONEFILES_WRITE
%token VAR_RRL_SIZE
Expand Down Expand Up @@ -445,6 +446,8 @@ server_option:
cfg_parser->opt->rrl_whitelist_ratelimit = (size_t)$2;
#endif
}
| VAR_RELOAD_CONFIG boolean
{ cfg_parser->opt->reload_config = $2; }
| VAR_ZONEFILES_CHECK boolean
{ cfg_parser->opt->zonefiles_check = $2; }
| VAR_ZONEFILES_WRITE number
Expand Down
4 changes: 4 additions & 0 deletions nsd.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,10 @@ the response with one RRset. Popular and not large types, like A, AAAA and
MX are preferred, and large types, like DNSKEY and RRSIG are picked with a
lower preference than other types. This makes the response smaller.
.TP
.B reload\-config:\fR <yes or no>
Reload configuration file and update TSIG keys and zones on SIGHUP.
Default is no.
.TP
.B zonefiles\-check:\fR <yes or no>
Make NSD check the mtime of zone files on start and sighup. If you
disable it it starts faster (less disk activity in case of a lot of zones).
Expand Down
3 changes: 3 additions & 0 deletions nsd.conf.sample.in
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ server:
# default is 3600.
# zonefiles-write: 3600

# Reload nsd.conf and update TSIG keys and zones on SIGHUP.
# reload-config: no

# RRLconfig
# Response Rate Limiting, size of the hashtable. Default 1000000.
# rrl-size: 1000000
Expand Down
1 change: 1 addition & 0 deletions options.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ nsd_options_create(region_type* region)
opt->dnstap_log_auth_query_messages = 0;
opt->dnstap_log_auth_response_messages = 0;
#endif
opt->reload_config = 0;
opt->zonefiles_check = 1;
opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL;
opt->xfrd_reload_timeout = 1;
Expand Down
1 change: 1 addition & 0 deletions options.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ struct nsd_options {
const char* zonelistfile;
const char* nsid;
int xfrd_reload_timeout;
int reload_config;
int zonefiles_check;
int zonefiles_write;
int log_time_ascii;
Expand Down
42 changes: 41 additions & 1 deletion remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
#else
# include "mini_event.h"
#endif
#include "remote.h"
#include "util.h"
#include "xfrd.h"
#include "xfrd-catalog-zones.h"
Expand All @@ -81,6 +80,7 @@
#include "options.h"
#include "difffile.h"
#include "ipc.h"
#include "remote.h"

#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
Expand Down Expand Up @@ -2038,6 +2038,46 @@ do_repattern(RES* ssl, xfrd_state_type* xfrd)
region_destroy(region);
}

static void print_cfg_err(void *unused, const char *message)
{
(void)unused;
log_msg(LOG_ERR, "%s", message);
}

/* mostly identical to do_repattern */
void xfrd_reload_config(xfrd_state_type *xfrd)
{
const char *chrootdir = xfrd->nsd->chrootdir;
const char *file = xfrd->nsd->options->configfile;

if (chrootdir && !file_inside_chroot(file, chrootdir))
{
log_msg(LOG_ERR, "%s is not relative to %s: %s",
xfrd->nsd->options->configfile, xfrd->nsd->chrootdir,
"chroot prevents reread of config");
goto error_chroot;
}

region_type *region = region_create(xalloc, free);
struct nsd_options *options = nsd_options_create(region);

if (!parse_options_file(
options, file, print_cfg_err, NULL, xfrd->nsd->options))
{
goto error_parse;
}

repat_keys(xfrd, options);
repat_patterns(xfrd, options); /* adds/deletes zones too */
repat_options(xfrd, options);
zonestat_inc_ifneeded(xfrd);

error_parse:
region_destroy(region);
error_chroot:
return;
}

/** do the serverpid command: printout pid of server process */
static void
do_serverpid(RES* ssl, xfrd_state_type* xfrd)
Expand Down
2 changes: 2 additions & 0 deletions remote.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,6 @@ void daemon_remote_attach(struct daemon_remote* rc, struct xfrd_state* xfrd);
*/
int create_local_accept_sock(const char* path, int* noproto);

void xfrd_reload_config(struct xfrd_state *xfrd);

#endif /* DAEMON_REMOTE_H */
4 changes: 4 additions & 0 deletions tpkg/reload-config.tdir/example.com.zone
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@ IN SOA ns1.example.com. hostmaster 2024080900 1800 900 604800 86400
IN NS ns1.example.com.
IN NS ns2.example.com.
IN A 192.0.2.1
4 changes: 4 additions & 0 deletions tpkg/reload-config.tdir/example.net.zone
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@ IN SOA ns1.example.net. hostmaster 2024090900 1800 900 604800 86400
IN NS ns1.example.net.
IN NS ns2.example.net.
IN A 192.0.2.2
13 changes: 13 additions & 0 deletions tpkg/reload-config.tdir/reload-config.1.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
server:
xfrdfile: "xfrd.state"
logfile: "/dev/stderr"
zonesdir: ""
username: ""
chroot: ""
verbosity: 1
ip-address: 127.0.0.1
reload-config: yes

zone:
name: example.com
zonefile: example.com.zone
17 changes: 17 additions & 0 deletions tpkg/reload-config.tdir/reload-config.2.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
server:
xfrdfile: "xfrd.state"
logfile: "/dev/stderr"
zonesdir: ""
username: ""
chroot: ""
verbosity: 1
ip-address: 127.0.0.1
reload-config: yes

zone:
name: example.com
zonefile: example.com.zone

zone:
name: example.net
zonefile: example.net.zone
16 changes: 16 additions & 0 deletions tpkg/reload-config.tdir/reload-config.dsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
BaseName: reload-config
Version: 1.0
Description: Test reread of nsd.conf on SIGHUP
CreationDate: Fri Aug 9 13:47:00 CEST 2024
Maintainer: Jeroen Koekkoek
Category:
Component:
CmdDepends:
Depends: 0000_nsd-compile.tpkg
Help:
Pre: reload-config.pre
Post: reload-config.post
Test: reload-config.test
AuxFiles:
Passed:
Failure:
19 changes: 19 additions & 0 deletions tpkg/reload-config.tdir/reload-config.post
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# #-- reload-config.post --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# source the test var file when it's there
[ -f .tpkg.var.test ] && source .tpkg.var.test
#
# do your teardown here
. ../common.sh

cat nsd.log

rm -f nsd.log
rm -f xfrd.state
rm -f nsd.zonelist

if test -f $NSD_PID; then
# the test must have failed
kill_pid `cat $NSD_PID`
fi
16 changes: 16 additions & 0 deletions tpkg/reload-config.tdir/reload-config.pre
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# #-- reload-config.pre --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh

# start NSD
get_random_port 1
NSD_PORT=$RND_PORT

NSD_PID="nsd.pid.$$"

# share the vars
echo "export NSD_PORT=$NSD_PORT" >> .tpkg.var.test
echo "export NSD_PID=$NSD_PID" >> .tpkg.var.test
37 changes: 37 additions & 0 deletions tpkg/reload-config.tdir/reload-config.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# #-- reload-config.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh

NSD="../../nsd"

cp reload-config.1.conf nsd.conf
$NSD -p $NSD_PORT -P $NSD_PID -V 5 -c nsd.conf > nsd.log 2>&1
wait_nsd_up nsd.log

dig @127.0.0.1 -p $NSD_PORT example.com. SOA | tee result
if ! grep hostmaster.example.com result; then
echo "zone example.com should be available" >&2
exit 1
fi

dig @127.0.0.1 -p $NSD_PORT example.net. SOA | tee result
if grep hostmaster.example.net result; then
echo "zone example.net should not be available" >&2
exit 1
fi

cp reload-config.2.conf nsd.conf
kill -SIGHUP $(head -n1 ${NSD_PID})

wait_logfile nsd.log "zone example.net read"

dig @127.0.0.1 -p $NSD_PORT example.net. SOA | tee result
if ! grep hostmaster.example.net result; then
echo "zone example.net should be available" >&2
exit 1
fi

exit 0
4 changes: 4 additions & 0 deletions xfrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ xfrd_sig_process(void)
} else if(xfrd->nsd->signal_hint_reload_hup) {
log_msg(LOG_WARNING, "SIGHUP received, reloading...");
xfrd->nsd->signal_hint_reload_hup = 0;
if(xfrd->nsd->options->reload_config) {
xfrd_reload_config(xfrd);
}
if(xfrd->nsd->options->zonefiles_check) {
task_new_check_zonefiles(xfrd->nsd->task[
xfrd->nsd->mytask], xfrd->last_task, NULL);
Expand Down Expand Up @@ -316,6 +319,7 @@ xfrd_main(void)
xfrd->shutdown = 0;
while(!xfrd->shutdown)
{
/* xfrd_sig_process takes care of reading zones on SIGHUP */
xfrd_process_catalog_producer_zones();
xfrd_process_catalog_consumer_zones();
/* process activated zones before blocking in select again */
Expand Down
Loading