Skip to content

Commit 2571008

Browse files
committed
Merge branch 'master' into features/af-xdp
2 parents a6398cb + 3b901a2 commit 2571008

File tree

171 files changed

+5014
-885
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

171 files changed

+5014
-885
lines changed

.github/workflows/analysis_ports.yml

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
- uses: actions/checkout@v4
5252
with:
5353
submodules: recursive
54+
persist-credentials: false
5455
- name: cross-platform-action on ${{ matrix.cross_platform_os }} ${{ matrix.cross_platform_version }}
5556
if: ${{ matrix.with_cross_platform_action == 'yes' }}
5657
uses: cross-platform-actions/[email protected]

.github/workflows/build-test.yml

+9-3
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ jobs:
1616
cc: clang
1717
cflags: -g2 -O0 -fsanitize=address,undefined,leak -fno-sanitize-recover=all
1818
packages: autoconf automake libtool make libevent-dev libssl-dev flex bison
19-
- os: macos-12
19+
- os: macos-15
2020
cflags: -g2 -O0 -fsanitize=address,undefined -fno-sanitize-recover=all
21-
packages: autoconf automake libtool openssl libevent flex bison
21+
packages: autoconf automake libtool flex bison
22+
# The libevent and openssl packages are already installed.
2223
steps:
2324
- uses: actions/checkout@v4
2425
with:
2526
submodules: recursive
27+
persist-credentials: false
2628
- name: 'Workaround for actions/runner-images#9491'
2729
if: runner.os == 'Linux'
2830
run: sudo sysctl vm.mmap_rnd_bits=28
@@ -47,7 +49,11 @@ jobs:
4749
autoconf && autoheader
4850
(cd simdzone && autoconf && autoheader)
4951
libtoolize -c -i || glibtoolize -c -i
50-
./configure --enable-checking --disable-flto --with-ssl=yes --with-libevent=yes
52+
if test "${{runner.os}}" = 'macOS'; then
53+
./configure --enable-checking --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libevent=/opt/homebrew/opt/libevent
54+
else
55+
./configure --enable-checking --disable-flto --with-ssl=yes --with-libevent=yes
56+
fi
5157
make -j 2
5258
- name: 'Run tests'
5359
id: test

.github/workflows/coverity-scan.yml

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
- uses: actions/checkout@v4
2626
with:
2727
submodules: recursive
28+
persist-credentials: false
2829
- id: install_packages
2930
shell: bash
3031
run: |

Makefile.in

+46-27
Large diffs are not rendered by default.

configlexer.lex

+6
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ server-key-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_KEY_FILE;
258258
server-cert-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_SERVER_CERT_FILE;}
259259
control-key-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_KEY_FILE;}
260260
control-cert-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONTROL_CERT_FILE;}
261+
metrics-enable{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_METRICS_ENABLE;}
262+
metrics-interface{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_METRICS_INTERFACE;}
263+
metrics-port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_METRICS_PORT;}
264+
metrics-path{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_METRICS_PATH;}
261265
AXFR { LEXOUT(("v(%s) ", yytext)); return VAR_AXFR;}
262266
UDP { LEXOUT(("v(%s) ", yytext)); return VAR_UDP;}
263267
rrl-size{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_RRL_SIZE;}
@@ -286,6 +290,7 @@ dnstap-version{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_VERSION; }
286290
dnstap-log-auth-query-messages{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_LOG_AUTH_QUERY_MESSAGES; }
287291
dnstap-log-auth-response-messages{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DNSTAP_LOG_AUTH_RESPONSE_MESSAGES; }
288292
log-time-ascii{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_LOG_TIME_ASCII;}
293+
log-time-iso{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_LOG_TIME_ISO;}
289294
round-robin{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ROUND_ROBIN;}
290295
minimal-responses{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MINIMAL_RESPONSES;}
291296
confine-to-zone{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CONFINE_TO_ZONE;}
@@ -312,6 +317,7 @@ proxy-protocol-port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_PROXY_PROTOC
312317
answer-cookie{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ANSWER_COOKIE;}
313318
cookie-secret{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_COOKIE_SECRET;}
314319
cookie-secret-file{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_COOKIE_SECRET_FILE;}
320+
cookie-staging-secret{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_COOKIE_STAGING_SECRET;}
315321
xfrd-tcp-max{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_TCP_MAX;}
316322
xfrd-tcp-pipeline{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_TCP_PIPELINE;}
317323
verify{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_VERIFY; }

configparser.y

+77-2
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ struct component {
111111
%token VAR_STATISTICS
112112
%token VAR_XFRD_RELOAD_TIMEOUT
113113
%token VAR_LOG_TIME_ASCII
114+
%token VAR_LOG_TIME_ISO
114115
%token VAR_ROUND_ROBIN
115116
%token VAR_MINIMAL_RESPONSES
116117
%token VAR_CONFINE_TO_ZONE
@@ -138,6 +139,10 @@ struct component {
138139
%token VAR_DROP_UPDATES
139140
%token VAR_XFRD_TCP_MAX
140141
%token VAR_XFRD_TCP_PIPELINE
142+
%token VAR_METRICS_ENABLE
143+
%token VAR_METRICS_INTERFACE
144+
%token VAR_METRICS_PORT
145+
%token VAR_METRICS_PATH
141146

142147
/* dnstap */
143148
%token VAR_DNSTAP
@@ -195,6 +200,7 @@ struct component {
195200
%token VAR_ANSWER_COOKIE
196201
%token VAR_COOKIE_SECRET
197202
%token VAR_COOKIE_SECRET_FILE
203+
%token VAR_COOKIE_STAGING_SECRET
198204
%token VAR_MAX_REFRESH_TIME
199205
%token VAR_MIN_REFRESH_TIME
200206
%token VAR_MAX_RETRY_TIME
@@ -461,6 +467,11 @@ server_option:
461467
cfg_parser->opt->log_time_ascii = $2;
462468
log_time_asc = cfg_parser->opt->log_time_ascii;
463469
}
470+
| VAR_LOG_TIME_ISO boolean
471+
{
472+
cfg_parser->opt->log_time_iso = $2;
473+
log_time_iso = cfg_parser->opt->log_time_iso;
474+
}
464475
| VAR_ROUND_ROBIN boolean
465476
{
466477
cfg_parser->opt->round_robin = $2;
@@ -516,9 +527,39 @@ server_option:
516527
| VAR_ANSWER_COOKIE boolean
517528
{ cfg_parser->opt->answer_cookie = $2; }
518529
| VAR_COOKIE_SECRET STRING
519-
{ cfg_parser->opt->cookie_secret = region_strdup(cfg_parser->opt->region, $2); }
530+
{
531+
uint8_t secret[32];
532+
ssize_t len = hex_pton($2, secret, NSD_COOKIE_SECRET_SIZE);
533+
534+
if(len != NSD_COOKIE_SECRET_SIZE) {
535+
yyerror("expected a 128 bit hex string");
536+
} else {
537+
cfg_parser->opt->cookie_secret = region_strdup(cfg_parser->opt->region, $2);
538+
}
539+
}
540+
| VAR_COOKIE_STAGING_SECRET STRING
541+
{
542+
uint8_t secret[32];
543+
ssize_t len = hex_pton($2, secret, NSD_COOKIE_SECRET_SIZE);
544+
545+
if(len != NSD_COOKIE_SECRET_SIZE) {
546+
yyerror("expected a 128 bit hex string");
547+
} else {
548+
cfg_parser->opt->cookie_staging_secret = region_strdup(cfg_parser->opt->region, $2);
549+
}
550+
}
520551
| VAR_COOKIE_SECRET_FILE STRING
521-
{ cfg_parser->opt->cookie_secret_file = region_strdup(cfg_parser->opt->region, $2); }
552+
{
553+
/* Empty filename means explicitly disabled cookies from file, internally
554+
* represented as NULL.
555+
* Note that after parsing, if no value was configured, then
556+
* cookie_secret_file_is_default is still 1, then the default cookie
557+
* secret file value will be assigned to cookie_secret_file.
558+
*/
559+
if(*$2) cfg_parser->opt->cookie_secret_file = region_strdup(cfg_parser->opt->region, $2);
560+
cfg_parser->opt->cookie_secret_file_is_default = 0;
561+
}
562+
522563
| VAR_XFRD_TCP_MAX number
523564
{ cfg_parser->opt->xfrd_tcp_max = (int)$2; }
524565
| VAR_XFRD_TCP_PIPELINE number
@@ -578,6 +619,40 @@ server_option:
578619
#ifdef USE_XDP
579620
cfg_parser->opt->xdp_bpffs_path = region_strdup(cfg_parser->opt->region, $2);
580621
#endif
622+
}
623+
| VAR_METRICS_ENABLE boolean
624+
{
625+
#ifdef USE_METRICS
626+
cfg_parser->opt->metrics_enable = $2;
627+
#endif /* USE_METRICS */
628+
}
629+
| VAR_METRICS_INTERFACE ip_address
630+
{
631+
#ifdef USE_METRICS
632+
struct ip_address_option *ip = cfg_parser->opt->metrics_interface;
633+
if(ip == NULL) {
634+
cfg_parser->opt->metrics_interface = $2;
635+
} else {
636+
while(ip->next != NULL) { ip = ip->next; }
637+
ip->next = $2;
638+
}
639+
#endif /* USE_METRICS */
640+
}
641+
| VAR_METRICS_PORT number
642+
{
643+
#ifdef USE_METRICS
644+
if($2 == 0) {
645+
yyerror("metrics port number expected");
646+
} else {
647+
cfg_parser->opt->metrics_port = (int)$2;
648+
}
649+
#endif /* USE_METRICS */
650+
}
651+
| VAR_METRICS_PATH STRING
652+
{
653+
#ifdef USE_METRICS
654+
cfg_parser->opt->metrics_path = region_strdup(cfg_parser->opt->region, $2);
655+
#endif /* USE_METRICS */
581656
}
582657
;
583658

configure.ac

+20-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ sinclude(dnstap/dnstap.m4)
77

88
# autoconf-2.70 is needed for @runstatedir@
99
AC_PREREQ([2.70])
10-
AC_INIT([NSD],[4.10.1],[https://github.com/NLnetLabs/nsd/issues or [email protected]])
10+
AC_INIT([NSD],[4.11.2],[https://github.com/NLnetLabs/nsd/issues or [email protected]])
1111
AC_CONFIG_HEADERS([config.h])
1212

1313
#
@@ -126,6 +126,12 @@ AC_ARG_WITH([zonelistfile], AS_HELP_STRING([--with-zonelistfile=path],[Pathname
126126
AC_DEFINE_UNQUOTED(ZONELISTFILE, ["`eval echo $zonelistfile`"], [Pathname to the NSD zone list file.])
127127
AC_SUBST(zonelistfile)
128128

129+
# default cookiesecrets file location.
130+
cookiesecretsfile=${dbdir}/cookiesecrets.txt
131+
AC_ARG_WITH([cookiesecretsfile], AS_HELP_STRING([--with-cookiesecretsfile=path],[Pathname to the NSD cookie secrets file]), [cookiesecretsfile=$withval])
132+
AC_DEFINE_UNQUOTED(COOKIESECRETSFILE, ["`eval echo $cookiesecretsfile`"], [Pathname to the NSD cookies secrets file.])
133+
AC_SUBST(cookiesecretsfile)
134+
129135
# default xfr dir location.
130136
xfrdir="/tmp"
131137
AC_ARG_WITH([xfrdir], AS_HELP_STRING([--with-xfrdir=path],[Pathname to where the NSD transfer dir is created]), [xfrdir=$withval])
@@ -1177,6 +1183,19 @@ case "$enable_xdp" in
11771183
esac
11781184
AC_SUBST(xdp)
11791185

1186+
AC_ARG_ENABLE(prometheus-metrics, AS_HELP_STRING([--enable-prometheus-metrics],[Enable prometheus metrics support.]))
1187+
case "$enable_prometheus_metrics" in
1188+
yes)
1189+
AC_DEFINE_UNQUOTED([USE_METRICS], [], [Define this to expose NSD statistics via a prometheus metrics HTTP endpoint.])
1190+
AC_DEFINE_UNQUOTED([NSD_METRICS_PORT], [9100], [Define to the default metrics HTTP endpoint port.])
1191+
AC_SEARCH_LIBS(evhttp_free, [event], , AC_MSG_ERROR(Cannot find libevent, but is needed for prometheus metrics support.))
1192+
AC_SUBST([METRICS_SRC], ["metrics.c"])
1193+
AC_SUBST([METRICS_OBJ], ["metrics.o"])
1194+
;;
1195+
no|*)
1196+
;;
1197+
esac
1198+
11801199
# check for dnstap if requested
11811200
dt_DNSTAP([${localstatedir}/run/nsd-dnstap.sock],
11821201
[

dbaccess.c

+54-15
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ namedb_zone_create(namedb_type* db, const dname_type* dname,
7575
zone->opts = zo;
7676
zone->ixfr = NULL;
7777
zone->filename = NULL;
78+
zone->includes.count = 0;
79+
zone->includes.paths = NULL;
7880
zone->logstr = NULL;
7981
zone->mtime.tv_sec = 0;
8082
zone->mtime.tv_nsec = 0;
@@ -89,6 +91,34 @@ namedb_zone_create(namedb_type* db, const dname_type* dname,
8991
return zone;
9092
}
9193

94+
void
95+
namedb_zone_free_filenames(namedb_type *db, zone_type* zone)
96+
{
97+
assert(!zone->includes.paths == !zone->includes.count);
98+
99+
if (zone->filename) {
100+
region_recycle(
101+
db->region, zone->filename, strlen(zone->filename) + 1);
102+
zone->filename = NULL;
103+
}
104+
105+
if (zone->includes.count) {
106+
for (size_t i=0; i < zone->includes.count; i++) {
107+
region_recycle(
108+
db->region,
109+
zone->includes.paths[i],
110+
strlen(zone->includes.paths[i]) + 1);
111+
}
112+
113+
region_recycle(
114+
db->region,
115+
zone->includes.paths,
116+
zone->includes.count * sizeof(*zone->includes.paths));
117+
zone->includes.count = 0;
118+
zone->includes.paths = NULL;
119+
}
120+
}
121+
92122
void
93123
namedb_zone_delete(namedb_type* db, zone_type* zone)
94124
{
@@ -119,9 +149,7 @@ namedb_zone_delete(namedb_type* db, zone_type* zone)
119149
hash_tree_delete(db->region, zone->dshashtree);
120150
#endif
121151
zone_ixfr_free(zone->ixfr);
122-
if(zone->filename)
123-
region_recycle(db->region, zone->filename,
124-
strlen(zone->filename)+1);
152+
namedb_zone_free_filenames(db, zone);
125153
if(zone->logstr)
126154
region_recycle(db->region, zone->logstr,
127155
strlen(zone->logstr)+1);
@@ -236,12 +264,27 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
236264
/* if zone_fname, then the file was acquired from reading it,
237265
* and see if filename changed or mtime newer to read it */
238266
} else if(zone_fname && strcmp(zone_fname, fname) == 0 &&
239-
timespec_compare(&zone_mtime, &mtime) == 0) {
240-
VERBOSITY(3, (LOG_INFO, "zonefile %s is not modified",
241-
fname));
242-
return;
267+
timespec_compare(&zone_mtime, &mtime) == 0) {
268+
int changed = 0;
269+
struct timespec include_mtime;
270+
/* one of the includes may have been deleted, changed, etc */
271+
for (size_t i=0; i < zone->includes.count; i++) {
272+
if (!file_get_mtime(zone->includes.paths[i], &include_mtime, &nonexist)) {
273+
changed = 1;
274+
} else if (timespec_compare(&zone_mtime, &include_mtime) < 0) {
275+
mtime = include_mtime;
276+
changed = 1;
277+
}
278+
}
279+
280+
if (!changed) {
281+
VERBOSITY(3, (LOG_INFO, "zonefile %s is not modified",
282+
fname));
283+
return;
284+
}
243285
}
244286
}
287+
245288
if(ixfr_create_from_difference(zone, fname,
246289
&ixfr_create_already_done)) {
247290
ixfrcr = ixfr_create_start(zone, fname,
@@ -252,6 +295,9 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
252295
}
253296
}
254297

298+
namedb_zone_free_filenames(nsd->db, zone);
299+
zone->filename = region_strdup(nsd->db->region, fname);
300+
255301
/* wipe zone from memory */
256302
#ifdef NSEC3
257303
nsec3_clear_precompile(nsd->db, zone);
@@ -271,10 +317,7 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
271317
zone->nsec3_param = NULL;
272318
#endif
273319
delete_zone_rrs(nsd->db, zone);
274-
if(zone->filename)
275-
region_recycle(nsd->db->region, zone->filename,
276-
strlen(zone->filename)+1);
277-
zone->filename = NULL;
320+
namedb_zone_free_filenames(nsd->db, zone);
278321
if(zone->logstr)
279322
region_recycle(nsd->db->region, zone->logstr,
280323
strlen(zone->logstr)+1);
@@ -286,10 +329,6 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
286329
zone->is_changed = 0;
287330
/* store zone into udb */
288331
zone->mtime = mtime;
289-
if(zone->filename)
290-
region_recycle(nsd->db->region, zone->filename,
291-
strlen(zone->filename)+1);
292-
zone->filename = region_strdup(nsd->db->region, fname);
293332
if(zone->logstr)
294333
region_recycle(nsd->db->region, zone->logstr,
295334
strlen(zone->logstr)+1);

dbcreate.c

+2
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt)
256256
return;
257257
}
258258
zone->is_changed = 0;
259+
VERBOSITY(3, (LOG_INFO, "zone %s written to file %s",
260+
zone->opts->name, zfile));
259261
/* fetch the mtime of the just created zonefile so we
260262
* do not waste effort reading it back in */
261263
if(!file_get_mtime(zfile, &mtime, &notexist)) {

0 commit comments

Comments
 (0)