summaryrefslogtreecommitdiffstats
path: root/usr.sbin/nsd
diff options
context:
space:
mode:
authorflorian <florian@openbsd.org>2020-05-14 06:08:40 +0000
committerflorian <florian@openbsd.org>2020-05-14 06:08:40 +0000
commit308d25095010cc66b1b67286e27e62e265360b59 (patch)
treed0eade07702d4b6112c7bd5e4ffd7908f5029c74 /usr.sbin/nsd
parentWe forgot to keep ChangeLog in sync in previous updates. (diff)
downloadwireguard-openbsd-308d25095010cc66b1b67286e27e62e265360b59.tar.xz
wireguard-openbsd-308d25095010cc66b1b67286e27e62e265360b59.zip
Update to 4.3.1
Testing & OK sthen
Diffstat (limited to 'usr.sbin/nsd')
-rw-r--r--usr.sbin/nsd/Makefile.in70
-rw-r--r--usr.sbin/nsd/axfr.c19
-rw-r--r--usr.sbin/nsd/bitset.c109
-rw-r--r--usr.sbin/nsd/bitset.h40
-rw-r--r--usr.sbin/nsd/config.h.in58
-rw-r--r--usr.sbin/nsd/configlexer.lex38
-rw-r--r--usr.sbin/nsd/configparser.y256
-rw-r--r--usr.sbin/nsd/configure887
-rw-r--r--usr.sbin/nsd/configure.ac205
-rw-r--r--usr.sbin/nsd/dbaccess.c12
-rw-r--r--usr.sbin/nsd/dbcreate.c1
-rw-r--r--usr.sbin/nsd/difffile.c10
-rw-r--r--usr.sbin/nsd/doc/ChangeLog179
-rw-r--r--usr.sbin/nsd/doc/RELNOTES88
-rw-r--r--usr.sbin/nsd/edns.c7
-rw-r--r--usr.sbin/nsd/ipc.c8
-rw-r--r--usr.sbin/nsd/namedb.c62
-rw-r--r--usr.sbin/nsd/namedb.h19
-rw-r--r--usr.sbin/nsd/nsd-checkconf.8.in2
-rw-r--r--usr.sbin/nsd/nsd-checkconf.c41
-rw-r--r--usr.sbin/nsd/nsd-checkzone.8.in2
-rw-r--r--usr.sbin/nsd/nsd-control-setup.sh.in181
-rw-r--r--usr.sbin/nsd/nsd-control.8.in2
-rw-r--r--usr.sbin/nsd/nsd-control.c2
-rw-r--r--usr.sbin/nsd/nsd.8.in4
-rw-r--r--usr.sbin/nsd/nsd.c365
-rw-r--r--usr.sbin/nsd/nsd.conf.5.in41
-rw-r--r--usr.sbin/nsd/nsd.conf.sample.in83
-rw-r--r--usr.sbin/nsd/nsd.h32
-rw-r--r--usr.sbin/nsd/nsec3.c1
-rw-r--r--usr.sbin/nsd/options.c35
-rw-r--r--usr.sbin/nsd/options.h34
-rw-r--r--usr.sbin/nsd/packet.c11
-rw-r--r--usr.sbin/nsd/popen3.c176
-rw-r--r--usr.sbin/nsd/popen3.h27
-rw-r--r--usr.sbin/nsd/query.c56
-rw-r--r--usr.sbin/nsd/radtree.c2
-rw-r--r--usr.sbin/nsd/region-allocator.c4
-rw-r--r--usr.sbin/nsd/remote.c101
-rw-r--r--usr.sbin/nsd/server.c238
-rw-r--r--usr.sbin/nsd/tsig.c19
-rw-r--r--usr.sbin/nsd/udb.c14
-rw-r--r--usr.sbin/nsd/udb.h4
-rw-r--r--usr.sbin/nsd/udbradtree.c6
-rw-r--r--usr.sbin/nsd/util.c73
-rw-r--r--usr.sbin/nsd/util.h5
-rw-r--r--usr.sbin/nsd/xfrd-tcp.c4
-rw-r--r--usr.sbin/nsd/xfrd.c34
48 files changed, 3123 insertions, 544 deletions
diff --git a/usr.sbin/nsd/Makefile.in b/usr.sbin/nsd/Makefile.in
index ae81833822d..4e6915d4461 100644
--- a/usr.sbin/nsd/Makefile.in
+++ b/usr.sbin/nsd/Makefile.in
@@ -47,13 +47,17 @@ INSTALL = $(srcdir)/install-sh -c
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
-YACC = @YACC@
+SED = @SED@
+AWK = @AWK@
+GREP = @GREP@
+EGREP = @EGREP@
+YACC = @YACC@
LEX = @LEX@
PROTOC_C = @PROTOC_C@
COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS)
-EDIT = sed \
+EDIT = $(SED) \
-e 's,@prefix\@,$(prefix),g' \
-e 's,@exec_prefix\@,$(exec_prefix),g' \
-e 's,@sbindir\@,$(sbindir),g' \
@@ -74,14 +78,14 @@ EDIT = sed \
TARGETS=nsd nsd-checkconf nsd-checkzone nsd-control nsd.conf.sample nsd-control-setup.sh
MANUALS=nsd.8 nsd-checkconf.8 nsd-checkzone.8 nsd-control.8 nsd.conf.5
-COMMON_OBJ=answer.o axfr.o buffer.o configlexer.o configparser.o dname.o dns.o edns.o iterated_hash.o lookup3.o namedb.o nsec3.o options.o packet.o query.o rbtree.o radtree.o rdata.o region-allocator.o rrl.o tsig.o tsig-openssl.o udb.o udbradtree.o udbzone.o util.o
+COMMON_OBJ=answer.o axfr.o buffer.o configlexer.o configparser.o dname.o dns.o edns.o iterated_hash.o lookup3.o namedb.o nsec3.o options.o packet.o query.o rbtree.o radtree.o rdata.o region-allocator.o rrl.o tsig.o tsig-openssl.o udb.o udbradtree.o udbzone.o util.o bitset.o popen3.o
XFRD_OBJ=xfrd-disk.o xfrd-notify.o xfrd-tcp.o xfrd.o remote.o $(DNSTAP_OBJ)
NSD_OBJ=$(COMMON_OBJ) $(XFRD_OBJ) difffile.o ipc.o mini_event.o netio.o nsd.o server.o dbaccess.o dbcreate.o zlexer.o zonec.o zparser.o
ALL_OBJ=$(NSD_OBJ) nsd-checkconf.o nsd-checkzone.o nsd-control.o nsd-mem.o
NSD_CHECKCONF_OBJ=$(COMMON_OBJ) nsd-checkconf.o
NSD_CHECKZONE_OBJ=$(COMMON_OBJ) $(XFRD_OBJ) dbaccess.o dbcreate.o difffile.o ipc.o mini_event.o netio.o server.o zonec.o zparser.o zlexer.o nsd-checkzone.o
NSD_CONTROL_OBJ=$(COMMON_OBJ) nsd-control.o
-CUTEST_OBJ=$(COMMON_OBJ) $(XFRD_OBJ) dbaccess.o dbcreate.o difffile.o ipc.o mini_event.o netio.o server.o zonec.o zparser.o zlexer.o cutest_dname.o cutest_dns.o cutest_iterated_hash.o cutest_run.o cutest_radtree.o cutest_rbtree.o cutest_namedb.o cutest_options.o cutest_region.o cutest_rrl.o cutest_udb.o cutest_udbrad.o cutest_util.o cutest.o qtest.o
+CUTEST_OBJ=$(COMMON_OBJ) $(XFRD_OBJ) dbaccess.o dbcreate.o difffile.o ipc.o mini_event.o netio.o server.o zonec.o zparser.o zlexer.o cutest_dname.o cutest_dns.o cutest_iterated_hash.o cutest_run.o cutest_radtree.o cutest_rbtree.o cutest_namedb.o cutest_options.o cutest_region.o cutest_rrl.o cutest_udb.o cutest_udbrad.o cutest_util.o cutest_bitset.o cutest_popen3.o cutest_iter.o cutest_event.o cutest.o qtest.o
NSD_MEM_OBJ=$(COMMON_OBJ) $(XFRD_OBJ) dbaccess.o dbcreate.o difffile.o ipc.o mini_event.o netio.o server.o zonec.o zparser.o zlexer.o nsd-mem.o
all: $(TARGETS) $(MANUALS)
@@ -95,11 +99,11 @@ nsd-control-setup.sh: $(srcdir)/nsd-control-setup.sh.in config.h
nsd.conf.sample: $(srcdir)/nsd.conf.sample.in config.h
rm -f nsd.conf.sample
- $(EDIT) $(srcdir)/nsd.conf.sample.in | awk '/RRLconfig'@ratelimit@'/ { while($$0 !~ /.*RRLend.*/) { getline; } getline; } {print} ' > nsd.conf.sample
+ $(EDIT) $(srcdir)/nsd.conf.sample.in | $(AWK) '/RRLconfig'@ratelimit@'/ { while($$0 !~ /.*RRLend.*/) { getline; } getline; } {print} ' > nsd.conf.sample
nsd.conf.5: $(srcdir)/nsd.conf.5.in config.h
rm -f nsd.conf.5
- $(EDIT) $(srcdir)/nsd.conf.5.in | awk '/rrlstart'@ratelimit@'/ { while($$0 !~ /.*rrlend.*/) { getline; } getline; } {print} ' > nsd.conf.5
+ $(EDIT) $(srcdir)/nsd.conf.5.in | $(AWK) '/rrlstart'@ratelimit@'/ { while($$0 !~ /.*rrlend.*/) { getline; } getline; } {print} ' > nsd.conf.5
nsd.8: $(srcdir)/nsd.8.in config.h
rm -f nsd.8
@@ -166,7 +170,7 @@ nsd-control: $(NSD_CONTROL_OBJ) $(LIBOBJS)
nsd-mem: $(NSD_MEM_OBJ) $(LIBOBJS)
$(LINK) -o $@ $(NSD_MEM_OBJ) $(LIBOBJS) $(SSL_LIBS) $(LIBS)
-cutest: $(CUTEST_OBJ) $(LIBOBJS)
+cutest: $(CUTEST_OBJ) $(LIBOBJS) popen3_echo
$(LINK) -o $@ $(CUTEST_OBJ) $(LIBOBJS) $(SSL_LIBS) $(LIBS)
udb-inspect: udb-inspect.o $(COMMON_OBJ) $(LIBOBJS)
@@ -175,8 +179,25 @@ udb-inspect: udb-inspect.o $(COMMON_OBJ) $(LIBOBJS)
xfr-inspect: xfr-inspect.o $(COMMON_OBJ) $(LIBOBJS)
$(LINK) -o $@ xfr-inspect.o $(COMMON_OBJ) $(LIBOBJS) $(LIBS)
+popen3_echo: popen3.o popen3_echo.o
+ $(LINK) -o $@ popen3.o popen3_echo.o
+
+checksec:
+ wget -q -O checksec https://raw.githubusercontent.com/slimm609/checksec.sh/master/checksec
+ -chmod a+x checksec && xattr -d com.apple.quarantine checksec 2>/dev/null
+
+audit: nsd nsd-checkconf nsd-checkzone nsd-control nsd-mem checksec
+ ./checksec --file=nsd
+ ./checksec --file=nsd-checkconf
+ ./checksec --file=nsd-checkzone
+ ./checksec --file=nsd-control
+ ./checksec --file=nsd-mem
+
+test check: cutest
+ ./cutest
+
clean:
- rm -f *.o $(TARGETS) $(MANUALS) cutest udb-inspect xfr-inspect nsd-mem
+ rm -f *.o $(TARGETS) $(MANUALS) cutest popen3_echo udb-inspect xfr-inspect nsd-mem
distclean: clean
rm -f Makefile config.h config.log config.status dnstap/dnstap_config.h
@@ -227,6 +248,9 @@ strlcpy.o: $(srcdir)/compat/strlcpy.c
strptime.o: $(srcdir)/compat/strptime.c
$(COMPILE) -c $(srcdir)/compat/strptime.c
+setproctitle.o: $(srcdir)/compat/setproctitle.c
+ $(COMPILE) -c $(srcdir)/compat/setproctitle.c
+
vsnprintf.o: $(srcdir)/compat/vsnprintf.c
$(COMPILE) -c $(srcdir)/compat/vsnprintf.c
@@ -245,6 +269,9 @@ reallocarray.o: $(srcdir)/compat/reallocarray.c
fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c
$(COMPILE) -c $(srcdir)/compat/fake-rfc2553.c
+cpuset.o: $(srcdir)/compat/cpuset.c
+ $(COMPILE) -c $(srcdir)/compat/cpuset.c
+
cutest_dname.o: $(srcdir)/tpkg/cutest/cutest_dname.c
$(COMPILE) -c $(srcdir)/tpkg/cutest/cutest_dname.c
@@ -284,6 +311,21 @@ cutest_udbrad.o: $(srcdir)/tpkg/cutest/cutest_udbrad.c
cutest_util.o: $(srcdir)/tpkg/cutest/cutest_util.c
$(COMPILE) -c $(srcdir)/tpkg/cutest/cutest_util.c
+cutest_bitset.o: $(srcdir)/tpkg/cutest/cutest_bitset.c
+ $(COMPILE) -c $(srcdir)/tpkg/cutest/cutest_bitset.c
+
+cutest_popen3.o: $(srcdir)/tpkg/cutest/cutest_popen3.c
+ $(COMPILE) -c $(srcdir)/tpkg/cutest/cutest_popen3.c
+
+cutest_iter.o: $(srcdir)/tpkg/cutest/cutest_iter.c
+ $(COMPILE) -c $(srcdir)/tpkg/cutest/cutest_iter.c
+
+cutest_event.o: $(srcdir)/tpkg/cutest/cutest_event.c
+ $(COMPILE) -c $(srcdir)/tpkg/cutest/cutest_event.c
+
+popen3_echo.o: $(srcdir)/tpkg/cutest/popen3_echo.c
+ $(COMPILE) -c $(srcdir)/tpkg/cutest/popen3_echo.c
+
cutest.o: $(srcdir)/tpkg/cutest/cutest.c
$(COMPILE) -c $(srcdir)/tpkg/cutest/cutest.c
@@ -346,8 +388,8 @@ DEPEND_TARGET=Makefile
DEPEND_TARGET2=Makefile.in
depend:
(cd $(srcdir) ; $(CC) -MM $(CPPFLAGS) *.c compat/*.c `if test -d tpkg/cutest; then echo tpkg/cutest/*.c; fi`) | \
- sed -e 's? *\([^ ]*\.[ch]\)? $$(srcdir)/\1?g' | \
- sed -e 's?$$(srcdir)/config.h?config.h?g' \
+ $(SED) -e 's? *\([^ ]*\.[ch]\)? $$(srcdir)/\1?g' | \
+ $(SED) -e 's?$$(srcdir)/config.h?config.h?g' \
-e 's?$$(srcdir)/configlexer.c?configlexer.c?g' \
-e 's?$$(srcdir)/configparser.c?configparser.c?g' \
-e 's?$$(srcdir)/configparser.h?configparser.h?g' \
@@ -359,12 +401,12 @@ depend:
-e 's?$$(srcdir)/zparser.h?zparser.h?g' \
> $(DEPEND_TMP)
cp $(DEPEND_TARGET) $(DEPEND_TMP2)
- head -`egrep -n "# Dependencies" $(DEPEND_TARGET) | tail -1 | sed -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET)
+ head -`$(EGREP) -n "# Dependencies" $(DEPEND_TARGET) | tail -1 | $(SED) -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET)
cat $(DEPEND_TMP) >> $(DEPEND_TARGET)
@if diff $(DEPEND_TARGET) $(DEPEND_TMP2); then echo " $(DEPEND_TARGET) unchanged"; else echo " Updated $(DEPEND_TARGET))"; fi
@if test -f $(DEPEND_TARGET2); then \
cp $(DEPEND_TARGET2) $(DEPEND_TMP2); \
- head -`egrep -n "# Dependencies" $(DEPEND_TARGET2) | tail -1 | sed -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET2); \
+ head -`$(EGREP) -n "# Dependencies" $(DEPEND_TARGET2) | tail -1 | $(SED) -e 's/:.*$$//'` $(DEPEND_TMP2) > $(DEPEND_TARGET2); \
cat $(DEPEND_TMP) >> $(DEPEND_TARGET2); \
if diff $(DEPEND_TARGET2) $(DEPEND_TMP2); then echo " $(DEPEND_TARGET2) unchanged"; else echo " Updated $(DEPEND_TARGET2))"; fi; \
fi
@@ -432,6 +474,7 @@ options.o: $(srcdir)/options.c config.h $(srcdir)/options.h $(srcdir)/region-all
packet.o: $(srcdir)/packet.c config.h $(srcdir)/packet.h $(srcdir)/dns.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h \
$(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/radtree.h $(srcdir)/rbtree.h $(srcdir)/query.h $(srcdir)/nsd.h $(srcdir)/edns.h $(srcdir)/tsig.h \
$(srcdir)/rdata.h
+popen3.o: $(srcdir)/popen3.c $(srcdir)/popen3.h
query.o: $(srcdir)/query.c config.h $(srcdir)/answer.h $(srcdir)/dns.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h \
$(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/radtree.h $(srcdir)/rbtree.h $(srcdir)/packet.h $(srcdir)/query.h $(srcdir)/nsd.h \
$(srcdir)/edns.h $(srcdir)/tsig.h $(srcdir)/axfr.h $(srcdir)/options.h $(srcdir)/nsec3.h
@@ -464,6 +507,7 @@ udbzone.o: $(srcdir)/udbzone.c config.h $(srcdir)/udbzone.h $(srcdir)/udb.h $(sr
$(srcdir)/namedb.h $(srcdir)/radtree.h $(srcdir)/options.h
util.o: $(srcdir)/util.c config.h $(srcdir)/util.h $(srcdir)/region-allocator.h $(srcdir)/dname.h $(srcdir)/buffer.h \
$(srcdir)/namedb.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/rbtree.h $(srcdir)/rdata.h $(srcdir)/zonec.h
+bitset.o: $(srcdir)/bitset.c $(srcdir)/bitset.h
xfrd.o: $(srcdir)/xfrd.c config.h $(srcdir)/xfrd.h $(srcdir)/rbtree.h $(srcdir)/region-allocator.h $(srcdir)/namedb.h \
$(srcdir)/dname.h $(srcdir)/buffer.h $(srcdir)/util.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/options.h $(srcdir)/tsig.h $(srcdir)/xfrd-tcp.h \
$(srcdir)/xfrd-disk.h $(srcdir)/xfrd-notify.h $(srcdir)/netio.h $(srcdir)/nsd.h $(srcdir)/edns.h $(srcdir)/packet.h $(srcdir)/rdata.h \
@@ -491,6 +535,7 @@ b64_ntop.o: $(srcdir)/compat/b64_ntop.c config.h
b64_pton.o: $(srcdir)/compat/b64_pton.c config.h
basename.o: $(srcdir)/compat/basename.c
fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c $(srcdir)/compat/fake-rfc2553.h config.h
+cpuset.o: $(srcdir)/compat/cpuset.c $(srcdir)/compat/cpuset.h config.h
inet_aton.o: $(srcdir)/compat/inet_aton.c config.h
inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h
inet_pton.o: $(srcdir)/compat/inet_pton.c config.h
@@ -503,6 +548,7 @@ snprintf.o: $(srcdir)/compat/snprintf.c config.h
strlcat.o: $(srcdir)/compat/strlcat.c config.h
strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
strptime.o: $(srcdir)/compat/strptime.c
+setproctitle.o: $(srcdir)/compat/setproctitle.c config.h
cutest.o: $(srcdir)/tpkg/cutest/cutest.c config.h $(srcdir)/tpkg/cutest/cutest.h
cutest_dname.o: $(srcdir)/tpkg/cutest/cutest_dname.c config.h $(srcdir)/tpkg/cutest/cutest.h \
$(srcdir)/region-allocator.h $(srcdir)/dname.h $(srcdir)/buffer.h $(srcdir)/region-allocator.h $(srcdir)/util.h
diff --git a/usr.sbin/nsd/axfr.c b/usr.sbin/nsd/axfr.c
index dd34c0c3cee..50c1ea2eb60 100644
--- a/usr.sbin/nsd/axfr.c
+++ b/usr.sbin/nsd/axfr.c
@@ -14,7 +14,8 @@
#include "packet.h"
#include "options.h"
-#define AXFR_TSIG_SIGN_EVERY_NTH 96 /* tsig sign every N packets. */
+/* draft-ietf-dnsop-rfc2845bis-06, section 5.3.1 says to sign every packet */
+#define AXFR_TSIG_SIGN_EVERY_NTH 0 /* tsig sign every N packets. */
query_state_type
query_axfr(struct nsd *nsd, struct query *query)
@@ -150,9 +151,13 @@ return_answer:
/* check if it needs tsig signatures */
if(query->tsig.status == TSIG_OK) {
+#if AXFR_TSIG_SIGN_EVERY_NTH > 0
if(query->tsig.updates_since_last_prepare >= AXFR_TSIG_SIGN_EVERY_NTH) {
+#endif
query->tsig_sign_it = 1;
+#if AXFR_TSIG_SIGN_EVERY_NTH > 0
}
+#endif
}
query_clear_compression_tables(query);
return QUERY_IN_AXFR;
@@ -200,9 +205,17 @@ answer_axfr_ixfr(struct nsd *nsd, struct query *q)
}
return query_axfr(nsd, q);
}
- /** Fallthrough: AXFR over UDP queries are discarded. */
- /* fallthrough */
+ /* AXFR over UDP queries are discarded. */
+ RCODE_SET(q->packet, RCODE_IMPL);
+ return QUERY_PROCESSED;
case TYPE_IXFR:
+ /* get rid of authority section, if present */
+ NSCOUNT_SET(q->packet, 0);
+ if(QDCOUNT(q->packet) > 0 && (size_t)QHEADERSZ+4+
+ q->qname->name_size <= buffer_limit(q->packet)) {
+ buffer_set_position(q->packet, QHEADERSZ+4+
+ q->qname->name_size);
+ }
RCODE_SET(q->packet, RCODE_IMPL);
return QUERY_PROCESSED;
default:
diff --git a/usr.sbin/nsd/bitset.c b/usr.sbin/nsd/bitset.c
new file mode 100644
index 00000000000..f1f850e4db6
--- /dev/null
+++ b/usr.sbin/nsd/bitset.c
@@ -0,0 +1,109 @@
+/*
+ * bitset.h -- Dynamic bitset.
+ *
+ * Copyright (c) 2001-2020, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+#include "config.h"
+#include "bitset.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+size_t nsd_bitset_size(size_t bits)
+{
+ if(bits == 0)
+ bits++;
+
+ return (bits / CHAR_BIT) + ((bits % CHAR_BIT) != 0) + sizeof(size_t);
+}
+
+void nsd_bitset_zero(struct nsd_bitset *bset)
+{
+ size_t sz;
+
+ assert(bset != NULL);
+
+ sz = nsd_bitset_size(bset->size) - sizeof(bset->size);
+ assert(sz > 0);
+ memset(bset->bits, 0, sz);
+}
+
+void nsd_bitset_init(struct nsd_bitset *bset, size_t bits)
+{
+ assert(bset != NULL);
+ if (bits == 0)
+ bits++;
+
+ bset->size = bits;
+ nsd_bitset_zero(bset);
+}
+
+int nsd_bitset_isset(struct nsd_bitset *bset, size_t bit)
+{
+ assert(bset != NULL);
+ if(bit >= bset->size)
+ return 0;
+
+ return (bset->bits[ (bit / CHAR_BIT) ] & (1 << (bit % CHAR_BIT))) != 0;
+}
+
+void nsd_bitset_set(struct nsd_bitset *bset, size_t bit)
+{
+ assert(bset != NULL);
+ assert(bset->size > bit);
+ bset->bits[ (bit / CHAR_BIT) ] |= (1 << (bit % CHAR_BIT));
+}
+
+void nsd_bitset_unset(struct nsd_bitset *bset, size_t bit)
+{
+ assert(bset != NULL);
+ assert(bset->size > bit);
+ bset->bits[ (bit / CHAR_BIT) ] &= ~(1 << (bit % CHAR_BIT));
+}
+
+void nsd_bitset_or(
+ struct nsd_bitset *destset,
+ struct nsd_bitset *srcset1,
+ struct nsd_bitset *srcset2)
+{
+ size_t i, n, size, bytes;
+ unsigned char bits;
+ unsigned int mask;
+
+ assert(destset != NULL);
+ assert(srcset1 != NULL);
+ assert(srcset2 != NULL);
+
+ size = destset->size;
+ bytes = (size / CHAR_BIT) + ((size % CHAR_BIT) != 0);
+
+ for(i = 0; i < bytes; i++) {
+ bits = 0;
+
+ n = (srcset1->size / CHAR_BIT);
+ if (n > i) {
+ bits |= srcset1->bits[i];
+ } else {
+ n += ((srcset1->size % CHAR_BIT) != 0);
+ mask = (1 << ((srcset1->size % CHAR_BIT) + 1)) - 1;
+ if (n > i) {
+ bits |= (srcset1->bits[i] & mask);
+ }
+ }
+ n = (srcset2->size / CHAR_BIT);
+ if (n > i) {
+ bits |= srcset2->bits[i];
+ } else {
+ n += ((srcset2->size % CHAR_BIT) != 0);
+ mask = (1 << ((srcset2->size % CHAR_BIT) + 1)) - 1;
+ if (n > i) {
+ bits |= (srcset2->bits[i] & mask);
+ }
+ }
+ destset->bits[i] = bits;
+ }
+}
diff --git a/usr.sbin/nsd/bitset.h b/usr.sbin/nsd/bitset.h
new file mode 100644
index 00000000000..85ed3bfb16f
--- /dev/null
+++ b/usr.sbin/nsd/bitset.h
@@ -0,0 +1,40 @@
+/*
+ * bitset.h -- Dynamic bitset.
+ *
+ * Copyright (c) 2001-2020, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+#ifndef _BITSET_H_
+#define _BITSET_H_
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+typedef struct nsd_bitset nsd_bitset_type;
+
+struct nsd_bitset {
+ size_t size; /** Number of available bits in the set */
+ unsigned char bits[];
+};
+
+size_t nsd_bitset_size(size_t bits);
+
+void nsd_bitset_zero(struct nsd_bitset *bset);
+
+void nsd_bitset_init(struct nsd_bitset *bset, size_t bits);
+
+int nsd_bitset_isset(struct nsd_bitset *bset, size_t bit);
+
+void nsd_bitset_set(struct nsd_bitset *bset, size_t bit);
+
+void nsd_bitset_unset(struct nsd_bitset *bset, size_t bit);
+
+void nsd_bitset_or(
+ struct nsd_bitset *destset,
+ struct nsd_bitset *srcset1,
+ struct nsd_bitset *srcset2);
+
+#endif /* _BITSET_H_ */
diff --git a/usr.sbin/nsd/config.h.in b/usr.sbin/nsd/config.h.in
index 617e7390516..67cd876e427 100644
--- a/usr.sbin/nsd/config.h.in
+++ b/usr.sbin/nsd/config.h.in
@@ -15,6 +15,9 @@
/* Pathname to the NSD configuration file */
#undef CONFIGFILE
+/* number of arguments for CPU_OR is three */
+#undef CPU_OR_THREE_ARGS
+
/* Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work
*/
#undef DARWIN_BROKEN_SETREUID
@@ -73,12 +76,25 @@
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
+/* Define to 1 if the system has the type `cpuid_t'. */
+#undef HAVE_CPUID_T
+
+/* Define to 1 if the system has the type `cpuset_t'. */
+#undef HAVE_CPUSET_T
+
+/* Define to 1 if the system has the type `cpu_set_t'. */
+#undef HAVE_CPU_SET_T
+
/* Define to 1 if you have the `CRYPTO_memcmp' function. */
#undef HAVE_CRYPTO_MEMCMP
/* if time.h provides ctime_r prototype */
#undef HAVE_CTIME_R_PROTO
+/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you
+ don't. */
+#undef HAVE_DECL_REALLOCARRAY
+
/* Define to 1 if you have the declaration of `SSL_CTX_set_ecdh_auto', and to
0 if you don't. */
#undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
@@ -153,6 +169,9 @@
/* Define to 1 if you have the `getpwnam' function. */
#undef HAVE_GETPWNAM
+/* Define to 1 if you have the `getrandom' function. */
+#undef HAVE_GETRANDOM
+
/* Define to 1 if you have the `glob' function. */
#undef HAVE_GLOB
@@ -265,9 +284,18 @@
/* Define if recvmmsg is implemented */
#undef HAVE_RECVMMSG
+/* Define to 1 if you have the <sched.h> header file. */
+#undef HAVE_SCHED_H
+
+/* Define this if sched_setaffinity is available */
+#undef HAVE_SCHED_SETAFFINITY
+
/* Define if sendmmsg is implemented */
#undef HAVE_SENDMMSG
+/* Define to 1 if you have the `setproctitle' function. */
+#undef HAVE_SETPROCTITLE
+
/* Define to 1 if you have the `setregid' function. */
#undef HAVE_SETREGID
@@ -364,18 +392,27 @@
/* If time.h has a struct timespec (for pselect). */
#undef HAVE_STRUCT_TIMESPEC
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/bitypes.h> header file. */
#undef HAVE_SYS_BITYPES_H
+/* Define to 1 if you have the <sys/cpuset.h> header file. */
+#undef HAVE_SYS_CPUSET_H
+
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
+/* Define to 1 if you have the <sys/random.h> header file. */
+#undef HAVE_SYS_RANDOM_H
+
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
@@ -497,6 +534,9 @@
/* Define this to set ratelimit to off by default. */
#undef RATELIMIT_DEFAULT_OFF
+/* If reallocarray needs defines to appear in the headers */
+#undef REALLOCARRAY_NEEDS_DEFINES
+
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
@@ -707,7 +747,7 @@
/* define before includes as it specifies what standard to use. */
#if (defined(HAVE_PSELECT) && !defined (HAVE_PSELECT_PROTO)) \
|| !defined (HAVE_CTIME_R_PROTO) \
- || defined (STRPTIME_NEEDS_DEFINES)
+ || defined (STRPTIME_NEEDS_DEFINES) || defined(REALLOCARRAY_NEEDS_DEFINES)
# ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 600
# endif
@@ -725,7 +765,7 @@
# endif
# ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
-# endif
+# endif
# ifndef _STDC_C99
# define _STDC_C99 1
# endif
@@ -877,13 +917,23 @@ void* reallocarray(void *ptr, size_t nmemb, size_t size);
#endif
#ifndef HAVE_STRPTIME
#define HAVE_STRPTIME 1
-char *strptime(const char *s, const char *format, struct tm *tm);
+char *strptime(const char *s, const char *format, struct tm *tm);
#endif
#ifndef STRPTIME_WORKS
#define STRPTIME_WORKS 1
-char *nsd_strptime(const char *s, const char *format, struct tm *tm);
+char *nsd_strptime(const char *s, const char *format, struct tm *tm);
#define strptime(a,b,c) nsd_strptime((a),(b),(c))
#endif
+#if (HAVE_CPU_SET_T || HAVE_CPUSET_T)
+#include "compat/cpuset.h"
+#endif
+#ifndef HAVE_SETPROCTITLE
+#ifdef __linux__
+#define HAVE_SETPROCTITLE 1
+#include <stdarg.h>
+void setproctitle(char *fmt, ...);
+#endif
+#endif
diff --git a/usr.sbin/nsd/configlexer.lex b/usr.sbin/nsd/configlexer.lex
index cd92add3234..8469bbce35d 100644
--- a/usr.sbin/nsd/configlexer.lex
+++ b/usr.sbin/nsd/configlexer.lex
@@ -205,6 +205,7 @@ debug-mode{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DEBUG_MODE;}
use-systemd{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_USE_SYSTEMD;}
hide-version{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_VERSION;}
hide-identity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_IDENTITY;}
+drop-updates{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DROP_UPDATES; }
ip4-only{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP4_ONLY;}
ip6-only{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_IP6_ONLY;}
do-ip4{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_DO_IP4;}
@@ -289,13 +290,42 @@ max-refresh-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MAX_REFRESH_TIM
min-refresh-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MIN_REFRESH_TIME;}
max-retry-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MAX_RETRY_TIME;}
min-retry-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MIN_RETRY_TIME;}
-multi-master-check{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MULTI_MASTER_CHECK;}
-tls-service-key{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_KEY;}
+multi-master-check{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MULTI_MASTER_CHECK;}
+tls-service-key{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_KEY;}
tls-service-ocsp{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_OCSP;}
-tls-service-pem{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_PEM;}
-tls-port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_PORT;}
+tls-service-pem{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_SERVICE_PEM;}
+tls-port{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_TLS_PORT;}
{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;}
+servers={UNQUOTEDLETTER}* {
+ yyless(yyleng - (yyleng - 8));
+ LEXOUT(("v(%s) ", yytext));
+ return VAR_SERVERS;
+}
+bindtodevice={UNQUOTEDLETTER}* {
+ yyless(yyleng - (yyleng - 13));
+ LEXOUT(("v(%s) ", yytext));
+ return VAR_BINDTODEVICE;
+}
+setfib={UNQUOTEDLETTER}* {
+ yyless(yyleng - (yyleng - 7));
+ LEXOUT(("v(%s) ", yytext));
+ return VAR_SETFIB;
+}
+
+cpu-affinity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_CPU_AFFINITY; }
+xfrd-cpu-affinity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_CPU_AFFINITY; }
+server-[1-9][0-9]*-cpu-affinity{COLON} {
+ char *str = yytext;
+ LEXOUT(("v(%s) ", yytext));
+ /* Skip server- */
+ while (*str != '\0' && (*str < '0' || *str > '9')) {
+ str++;
+ }
+ yylval.llng = strtoll(str, NULL, 10);
+ return VAR_SERVER_CPU_AFFINITY;
+ }
+
/* Quoted strings. Strip leading and ending quotes */
\" { BEGIN(quotedstring); LEXOUT(("QS ")); }
<quotedstring><<EOF>> {
diff --git a/usr.sbin/nsd/configparser.y b/usr.sbin/nsd/configparser.y
index 179bc7e9155..8b898153c94 100644
--- a/usr.sbin/nsd/configparser.y
+++ b/usr.sbin/nsd/configparser.y
@@ -32,6 +32,9 @@ extern "C"
extern config_parser_state_type *cfg_parser;
static void append_acl(struct acl_options **list, struct acl_options *acl);
+static int parse_boolean(const char *str, int *bln);
+static int parse_number(const char *str, long long *num);
+static int parse_range(const char *str, long long *low, long long *high);
%}
%union {
@@ -39,12 +42,16 @@ static void append_acl(struct acl_options **list, struct acl_options *acl);
long long llng;
int bln;
struct ip_address_option *ip;
+ struct range_option *range;
+ struct cpu_option *cpu;
}
%token <str> STRING
%type <llng> number
%type <bln> boolean
%type <ip> ip_address
+%type <llng> service_cpu_affinity
+%type <cpu> cpus
/* server */
%token VAR_SERVER
@@ -105,6 +112,10 @@ static void append_acl(struct acl_options **list, struct acl_options *acl);
%token VAR_TLS_SERVICE_PEM
%token VAR_TLS_SERVICE_OCSP
%token VAR_TLS_PORT
+%token VAR_CPU_AFFINITY
+%token VAR_XFRD_CPU_AFFINITY
+%token <llng> VAR_SERVER_CPU_AFFINITY
+%token VAR_DROP_UPDATES
/* dnstap */
%token VAR_DNSTAP
@@ -158,6 +169,11 @@ static void append_acl(struct acl_options **list, struct acl_options *acl);
%token VAR_ZONE
%token VAR_RRL_WHITELIST
+/* socket options */
+%token VAR_SERVERS
+%token VAR_BINDTODEVICE
+%token VAR_SETFIB
+
%%
blocks:
@@ -180,14 +196,21 @@ server_block:
server_option:
VAR_IP_ADDRESS ip_address
- {
- struct ip_address_option *ip = cfg_parser->opt->ip_addresses;
- if(ip == NULL) {
- cfg_parser->opt->ip_addresses = $2;
- } else {
- while(ip->next) { ip = ip->next; }
- ip->next = $2;
+ {
+ struct ip_address_option *ip = cfg_parser->opt->ip_addresses;
+
+ if(ip == NULL) {
+ cfg_parser->opt->ip_addresses = $2;
+ } else {
+ while(ip->next) { ip = ip->next; }
+ ip->next = $2;
+ }
+
+ cfg_parser->ip = $2;
}
+ socket_options
+ {
+ cfg_parser->ip = NULL;
}
| VAR_SERVER_COUNT number
{
@@ -198,7 +221,7 @@ server_option:
}
}
| VAR_IP_TRANSPARENT boolean
- { cfg_parser->opt->ip_transparent = (int)$2; }
+ { cfg_parser->opt->ip_transparent = $2; }
| VAR_IP_FREEBIND boolean
{ cfg_parser->opt->ip_freebind = $2; }
| VAR_SEND_BUFFER_SIZE number
@@ -213,6 +236,8 @@ server_option:
{ cfg_parser->opt->hide_version = $2; }
| VAR_HIDE_IDENTITY boolean
{ cfg_parser->opt->hide_identity = $2; }
+ | VAR_DROP_UPDATES boolean
+ { cfg_parser->opt->drop_updates = $2; }
| VAR_IP4_ONLY boolean
{ if($2) { cfg_parser->opt->do_ip4 = 1; cfg_parser->opt->do_ip6 = 0; } }
| VAR_IP6_ONLY boolean
@@ -403,6 +428,123 @@ server_option:
(void)snprintf(buf, sizeof(buf), "%lld", $2);
cfg_parser->opt->tls_port = region_strdup(cfg_parser->opt->region, buf);
}
+ | VAR_CPU_AFFINITY cpus
+ {
+ cfg_parser->opt->cpu_affinity = $2;
+ }
+ | service_cpu_affinity number
+ {
+ if($2 < 0) {
+ yyerror("expected a non-negative number");
+ YYABORT;
+ } else {
+ struct cpu_map_option *opt, *tail;
+
+ opt = cfg_parser->opt->service_cpu_affinity;
+ while(opt && opt->service != $1) { opt = opt->next; }
+
+ if(opt) {
+ opt->cpu = $2;
+ } else {
+ opt = region_alloc_zero(cfg_parser->opt->region, sizeof(*opt));
+ opt->service = (int)$1;
+ opt->cpu = (int)$2;
+
+ tail = cfg_parser->opt->service_cpu_affinity;
+ if(tail) {
+ while(tail->next) { tail = tail->next; }
+ tail->next = opt;
+ } else {
+ cfg_parser->opt->service_cpu_affinity = opt;
+ }
+ }
+ }
+ }
+ ;
+
+socket_options:
+ | socket_options socket_option ;
+
+socket_option:
+ VAR_SERVERS STRING
+ {
+ char *tok, *ptr, *str;
+ struct range_option *servers = NULL;
+ long long first, last;
+
+ /* user may specify "0 1", "0" "1", 0 1 or a combination thereof */
+ for(str = $2; (tok = strtok_r(str, " \t", &ptr)); str = NULL) {
+ struct range_option *opt =
+ region_alloc(cfg_parser->opt->region, sizeof(*opt));
+ first = last = 0;
+ if(!parse_range(tok, &first, &last)) {
+ yyerror("invalid server range '%s'", tok);
+ YYABORT;
+ }
+ assert(first >= 0);
+ assert(last >= 0);
+ opt->next = NULL;
+ opt->first = (int)first;
+ opt->last = (int)last;
+ if(servers) {
+ servers = servers->next = opt;
+ } else {
+ servers = cfg_parser->ip->servers = opt;
+ }
+ }
+ }
+ | VAR_BINDTODEVICE boolean
+ { cfg_parser->ip->dev = $2; }
+ | VAR_SETFIB number
+ { cfg_parser->ip->fib = $2; }
+ ;
+
+cpus:
+ { $$ = NULL; }
+ | cpus STRING
+ {
+ char *tok, *ptr, *str;
+ struct cpu_option *tail;
+ long long cpu;
+
+ str = $2;
+ $$ = tail = $1;
+ if(tail) {
+ while(tail->next) { tail = tail->next; }
+ }
+
+ /* Users may specify "0 1", "0" "1", 0 1 or a combination thereof. */
+ for(str = $2; (tok = strtok_r(str, " \t", &ptr)); str = NULL) {
+ struct cpu_option *opt =
+ region_alloc(cfg_parser->opt->region, sizeof(*opt));
+ cpu = 0;
+ if(!parse_number(tok, &cpu) || opt->cpu < 0) {
+ yyerror("expected a positive number");
+ YYABORT;
+ }
+ assert(cpu >=0);
+ opt->cpu = (int)cpu;
+ if(tail) {
+ tail->next = opt;
+ tail = opt;
+ } else {
+ $$ = tail = opt;
+ }
+ }
+ }
+ ;
+
+service_cpu_affinity:
+ VAR_XFRD_CPU_AFFINITY
+ { $$ = -1; }
+ | VAR_SERVER_CPU_AFFINITY
+ {
+ if($1 <= 0) {
+ yyerror("invalid server identifier");
+ YYABORT;
+ }
+ $$ = $1;
+ }
;
dnstap:
@@ -720,26 +862,14 @@ ip_address:
struct ip_address_option *ip = region_alloc_zero(
cfg_parser->opt->region, sizeof(*ip));
ip->address = region_strdup(cfg_parser->opt->region, $1);
+ ip->fib = -1;
$$ = ip;
} ;
number:
STRING
{
- /* ensure string consists entirely of digits */
- const char *str = $1;
- size_t pos = 0;
- while(str[pos] >= '0' && str[pos] <= '9') {
- pos++;
- }
-
- $$ = 0;
- if(pos > 0 && str[pos] == '\0') {
- int err = errno;
- errno = 0;
- $$ = strtoll(str, NULL, 10);
- errno = err;
- } else {
+ if(!parse_number($1, &$$)) {
yyerror("expected a number");
YYABORT; /* trigger a parser error */
}
@@ -748,12 +878,7 @@ number:
boolean:
STRING
{
- $$ = 0;
- if(strcmp($1, "yes") == 0) {
- $$ = 1;
- } else if(strcmp($1, "no") == 0) {
- $$ = 0;
- } else {
+ if(!parse_boolean($1, &$$)) {
yyerror("expected yes or no");
YYABORT; /* trigger a parser error */
}
@@ -776,3 +901,78 @@ append_acl(struct acl_options **list, struct acl_options *acl)
}
}
+static int
+parse_boolean(const char *str, int *bln)
+{
+ if(strcmp(str, "yes") == 0) {
+ *bln = 1;
+ } else if(strcmp(str, "no") == 0) {
+ *bln = 0;
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+parse_number(const char *str, long long *num)
+{
+ /* ensure string consists entirely of digits */
+ size_t pos = 0;
+ while(str[pos] >= '0' && str[pos] <= '9') {
+ pos++;
+ }
+
+ if(pos != 0 && str[pos] == '\0') {
+ *num = strtoll(str, NULL, 10);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+parse_range(const char *str, long long *low, long long *high)
+{
+ const char *ptr = str;
+ long long num[2];
+
+ /* require range to begin with a number */
+ if(*ptr < '0' || *ptr > '9') {
+ return 0;
+ }
+
+ num[0] = strtoll(ptr, (char **)&ptr, 10);
+
+ /* require number to be followed by nothing at all or a dash */
+ if(*ptr == '\0') {
+ *low = num[0];
+ *high = num[0];
+ return 1;
+ } else if(*ptr != '-') {
+ return 0;
+ }
+
+ ++ptr;
+ /* require dash to be followed by a number */
+ if(*ptr < '0' || *ptr > '9') {
+ return 0;
+ }
+
+ num[1] = strtoll(ptr, (char **)&ptr, 10);
+
+ /* require number to be followed by nothing at all */
+ if(*ptr == '\0') {
+ if(num[0] < num[1]) {
+ *low = num[0];
+ *high = num[1];
+ } else {
+ *low = num[1];
+ *high = num[0];
+ }
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/usr.sbin/nsd/configure b/usr.sbin/nsd/configure
index f42b7ee7af0..00191db9e5d 100644
--- a/usr.sbin/nsd/configure
+++ b/usr.sbin/nsd/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for NSD 4.2.4.
+# Generated by GNU Autoconf 2.69 for NSD 4.3.1.
#
# Report bugs to <nsd-bugs@nlnetlabs.nl>.
#
@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='NSD'
PACKAGE_TARNAME='nsd'
-PACKAGE_VERSION='4.2.4'
-PACKAGE_STRING='NSD 4.2.4'
+PACKAGE_VERSION='4.3.1'
+PACKAGE_STRING='NSD 4.3.1'
PACKAGE_BUGREPORT='nsd-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@@ -632,16 +632,13 @@ HAVE_SSL
ratelimit_default
ratelimit
LIBOBJS
-YFLAGS
-YACC
-LEXLIB
-LEX_OUTPUT_ROOT
-LEX
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
LN_S
-AWK
+YFLAGS
+LEXLIB
+LEX_OUTPUT_ROOT
user
chrootdir
xfrdir
@@ -655,8 +652,6 @@ pidfile
logfile
nsd_conf_file
configdir
-EGREP
-GREP
CPP
OBJEXT
EXEEXT
@@ -665,6 +660,12 @@ CPPFLAGS
LDFLAGS
CFLAGS
CC
+YACC
+LEX
+EGREP
+GREP
+AWK
+SED
target_alias
host_alias
build_alias
@@ -749,13 +750,18 @@ enable_tcp_fastopen
ac_precious_vars='build_alias
host_alias
target_alias
+SED
+AWK
+GREP
+EGREP
+LEX
+YACC
CC
CFLAGS
LDFLAGS
LIBS
CPPFLAGS
CPP
-YACC
YFLAGS'
@@ -1297,7 +1303,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures NSD 4.2.4 to adapt to many kinds of systems.
+\`configure' configures NSD 4.3.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1358,7 +1364,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of NSD 4.2.4:";;
+ short | recursive ) echo "Configuration of NSD 4.3.1:";;
esac
cat <<\_ACEOF
@@ -1419,20 +1425,27 @@ Optional Packages:
--with-user=username User name or ID to answer the queries with
--with-libevent=pathname
use libevent (will check /usr/local /opt/local
- /usr/lib /usr/pkg /usr/sfw /usr or you can specify
- an explicit path), useful when the zone count is
- high.
+ /usr/lib /usr/pkg /usr/sfw /usr
+ /usr/local/opt/libevent or you can specify an
+ explicit path), useful when the zone count is high.
--with-facility=name Syslog default facility (LOG_DAEMON)
--with-tcp-timeout=number
Limit the default tcp timeout
--with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl
- /usr/ssl /usr/pkg /usr/sfw /usr/local /usr)
+ /usr/ssl /usr/pkg /usr/sfw /usr/local /usr
+ /usr/local/opt/openssl)
--with-dnstap-socket-path=pathname
set default dnstap socket path
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
--with-libfstrm=path Path where libfstrm is installed, for dnstap
Some influential environment variables:
+ SED location of the sed program
+ AWK location of the awk program
+ GREP location of the grep program
+ EGREP location of the egrep program
+ LEX location of the lex program with GNU extensions (flex)
+ YACC location of the yacc program with GNU extensions (bison)
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
@@ -1441,9 +1454,6 @@ Some influential environment variables:
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
- YACC The `Yet Another Compiler Compiler' implementation to use.
- Defaults to the first program found out of: `bison -y', `byacc',
- `yacc'.
YFLAGS The list of arguments that will be passed by default to $YACC.
This script will default YFLAGS to the empty string to avoid a
default value of `-d' given by some make applications.
@@ -1514,7 +1524,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-NSD configure 4.2.4
+NSD configure 4.3.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2223,7 +2233,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by NSD $as_me 4.2.4, which was
+It was created by NSD $as_me 4.3.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2574,6 +2584,17 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers config.h"
+#
+# Setup the standard programs
+# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html
+
+
+
+
+
+
+
+
CFLAGS="$CFLAGS"
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -4056,49 +4077,6 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
-# Checks for programs.
-for ac_prog in gawk mawk nawk awk
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AWK+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$AWK"; then
- ac_cv_prog_AWK="$AWK" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_AWK="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-AWK=$ac_cv_prog_AWK
-if test -n "$AWK"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
-$as_echo "$AWK" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$AWK" && break
-done
-
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4638,138 +4616,246 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
-$as_echo_n "checking whether ln -s works... " >&6; }
-LN_S=$as_ln_s
-if test "$LN_S" = "ln -s"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+ $as_echo_n "(cached) " >&6
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
-$as_echo "no, using $LN_S" >&6; }
+ ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for ac_i in 1 2 3 4 5 6 7; do
+ ac_script="$ac_script$as_nl$ac_script"
+ done
+ echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+ { ac_script=; unset ac_script;}
+ if test -z "$SED"; then
+ ac_path_SED_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+ # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+ ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo '' >> "conftest.nl"
+ "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_SED_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_SED="$ac_path_SED"
+ ac_path_SED_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_SED_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_SED"; then
+ as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+ fi
+else
+ ac_cv_path_SED=$SED
fi
-ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+ rm -f conftest.sed
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
fi
done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+ test -n "$AWK" && break
+done
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
-if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
$as_echo_n "(cached) " >&6
else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
- /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
- ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
- /usr/ucb/* ) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
- if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
- # program-specific install script used by HP pwplus--don't use.
- :
- else
- rm -rf conftest.one conftest.two conftest.dir
- echo one > conftest.one
- echo two > conftest.two
- mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
- test -s conftest.one && test -s conftest.two &&
- test -s conftest.dir/conftest.one &&
- test -s conftest.dir/conftest.two
- then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
- break 3
- fi
- fi
- fi
- done
- done
- ;;
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
+ $ac_path_GREP_found && break 3
+ done
+ done
done
IFS=$as_save_IFS
-
-rm -rf conftest.one conftest.two conftest.dir
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL=$ac_cv_path_install
- else
- # As a last resort, use the slow shell script. Don't cache a
- # value for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the value is a relative name.
- INSTALL=$ac_install_sh
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
+else
+ ac_cv_path_EGREP=$EGREP
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
for ac_prog in flex lex
do
@@ -4973,8 +5059,159 @@ fi
done
test -n "$YACC" || YACC="yacc"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
if test "$LEX" != ":" -a "$LEX" != ""; then
+# Solaris provides anemic tools, and they don't offer GNU extensions like
+# 'flex -i'. Solaris also does not offer GNU replacements in /usr/gnu/bin.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lex accepts -i" >&5
+$as_echo_n "checking whether lex accepts -i... " >&6; }
+if echo "%%" | $LEX -i -t >/dev/null 2>&1; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "unable to find a lexer that supports -i. If one is available then set the LEX variable" "$LINENO" 5
+
+
+fi
+
# Check if lex defines yy_current_buffer, because 2.4.6 and older use it,
# but later could define it as a macro and then we should not redefine it.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if lex defines yy_current_buffer" >&5
@@ -4982,8 +5219,8 @@ $as_echo_n "checking if lex defines yy_current_buffer... " >&6; }
cat <<EOF >conftest.lex
%%
EOF
- $LEX -i -t conftest.lex >> conftest.c
- if grep "^#define yy_current_buffer" conftest.c >/dev/null; then
+ $LEX -i -t conftest.lex >> conftest.c 2>/dev/null
+ if $GREP "^#define yy_current_buffer" conftest.c >/dev/null; then
cat >>confdefs.h <<_ACEOF
#define LEX_DEFINES_YY_CURRENT_BUFFER 1
@@ -5625,7 +5862,7 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libevent" >&5
$as_echo_n "checking for libevent... " >&6; }
if test x_$withval = x_ -o x_$withval = x_yes; then
- withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
+ withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr /usr/local/opt/libevent"
fi
for dir in $withval; do
thedir="$dir"
@@ -5644,7 +5881,7 @@ $as_echo_n "checking for libevent... " >&6; }
$as_echo "found in $thedir" >&6; }
CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
# remove evdns from linking
- ev_files_o=`ls $thedir/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o`
+ ev_files_o=`ls $thedir/*.o | $GREP -v evdns\.o | $GREP -v bufferevent_openssl\.o`
cp $ev_files_o .
LDFLAGS="$ev_files_o $LDFLAGS -lm"
else
@@ -6098,7 +6335,7 @@ $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
fi
-for ac_header in time.h arpa/inet.h signal.h string.h strings.h fcntl.h limits.h netinet/in.h netinet/tcp.h stddef.h sys/param.h sys/socket.h sys/un.h syslog.h unistd.h sys/select.h stdarg.h stdint.h netdb.h sys/bitypes.h tcpd.h glob.h grp.h endian.h
+for ac_header in time.h arpa/inet.h signal.h string.h strings.h fcntl.h limits.h netinet/in.h netinet/tcp.h stddef.h sys/param.h sys/socket.h sys/un.h syslog.h unistd.h sys/select.h stdarg.h stdint.h netdb.h sys/bitypes.h tcpd.h glob.h grp.h endian.h sys/random.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -8015,7 +8252,7 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
-for ac_func in arc4random arc4random_uniform
+for ac_func in getrandom arc4random arc4random_uniform
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -8205,12 +8442,246 @@ fi
esac
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
-if echo $target_os | grep darwin8 > /dev/null; then
+if echo $target_os | $GREP -i darwin8 > /dev/null; then
$as_echo "#define DARWIN_BROKEN_SETREUID 1" >>confdefs.h
fi
+# GNU HURD needs _GNU_SOURCE defined for cpu affinity gear
+if echo $target_os | $EGREP -i 'linux|hurd' > /dev/null; then
+ $as_echo "#define _GNU_SOURCE, 1, Define this if on Linux or GNU Hurd for cpu affinity interface 1" >>confdefs.h
+
+fi
+
+# see comment on _GNU_SOURCE above
+for ac_header in sched.h sys/cpuset.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Check for cpu_set_t (Linux) and cpuset_t (FreeBSD and NetBSD)
+ac_fn_c_check_type "$LINENO" "cpu_set_t" "ac_cv_type_cpu_set_t" "
+$ac_includes_default
+#if HAVE_SCHED_H
+# include <sched.h>
+#endif
+#if HAVE_SYS_CPUSET_H
+# include <sys/cpuset.h>
+#endif
+
+"
+if test "x$ac_cv_type_cpu_set_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_CPU_SET_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "cpuset_t" "ac_cv_type_cpuset_t" "
+$ac_includes_default
+#if HAVE_SCHED_H
+# include <sched.h>
+#endif
+#if HAVE_SYS_CPUSET_H
+# include <sys/cpuset.h>
+#endif
+
+"
+if test "x$ac_cv_type_cpuset_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_CPUSET_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "cpuid_t" "ac_cv_type_cpuid_t" "
+$ac_includes_default
+#if HAVE_SCHED_H
+# include <sched.h>
+#endif
+#if HAVE_SYS_CPUSET_H
+# include <sys/cpuset.h>
+#endif
+
+"
+if test "x$ac_cv_type_cpuid_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_CPUID_T 1
+_ACEOF
+
+
+fi
+
+
+
+
+if test x"$ac_cv_type_cpuset_t" = xyes -o x"$ac_cv_type_cpu_set_t" = xyes ; then :
+
+ ac_fn_c_check_func "$LINENO" "cpuset_create" "ac_cv_func_cpuset_create"
+if test "x$ac_cv_func_cpuset_create" = xyes; then :
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "cpuset_destroy" "ac_cv_func_cpuset_destroy"
+if test "x$ac_cv_func_cpuset_destroy" = xyes; then :
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "cpuset_zero" "ac_cv_func_cpuset_zero"
+if test "x$ac_cv_func_cpuset_zero" = xyes; then :
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "cpuset_set" "ac_cv_func_cpuset_set"
+if test "x$ac_cv_func_cpuset_set" = xyes; then :
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "cpuset_clr" "ac_cv_func_cpuset_clr"
+if test "x$ac_cv_func_cpuset_clr" = xyes; then :
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "cpuset_isset" "ac_cv_func_cpuset_isset"
+if test "x$ac_cv_func_cpuset_isset" = xyes; then :
+
+fi
+
+ ac_fn_c_check_func "$LINENO" "cpuset_size" "ac_cv_func_cpuset_size"
+if test "x$ac_cv_func_cpuset_size" = xyes; then :
+
+fi
+
+ case " $LIBOBJS " in
+ *" cpuset.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS cpuset.$ac_objext"
+ ;;
+esac
+
+ for ac_func in sysconf
+do :
+ ac_fn_c_check_func "$LINENO" "sysconf" "ac_cv_func_sysconf"
+if test "x$ac_cv_func_sysconf" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYSCONF 1
+_ACEOF
+
+fi
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether CPU_OR works with three arguments" >&5
+$as_echo_n "checking whether CPU_OR works with three arguments... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef HAVE_SCHED_H
+# include <sched.h>
+#endif
+#ifdef HAVE_SYS_CPUSET_H
+# include <sys/cpuset.h>
+#endif
+#include <string.h>
+#ifdef HAVE_CPUSET_T
+#define MY_CPUSET_TYPE cpuset_t
+#endif
+#ifdef HAVE_CPU_SET_T
+#define MY_CPUSET_TYPE cpu_set_t
+#endif
+void testing (void) {
+ MY_CPUSET_TYPE a, b;
+ memset(&a, 0, sizeof(a));
+ memset(&b, 0, sizeof(b));
+ CPU_OR(&a, &a, &b);
+}
+int
+main ()
+{
+
+ testing();
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define CPU_OR_THREE_ARGS 1" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+
+#
+# sched_setaffinity must be checked using proper includes.
+# also needs _GNU_SOURCE on Linux and Hurd; see above.
+# also see https://github.com/NLnetLabs/nsd/issues/82.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sched_setaffinity" >&5
+$as_echo_n "checking for sched_setaffinity... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #ifdef HAVE_SCHED_H
+ # include <sched.h>
+ #endif
+ #ifdef HAVE_SYS_CPUSET_H
+ #include <sys/cpuset.h>
+ #endif
+ #ifdef HAVE_CPUSET_T
+ #define MY_CPUSET_TYPE cpuset_t
+ #endif
+ #ifdef HAVE_CPU_SET_T
+ #define MY_CPUSET_TYPE cpu_set_t
+ #endif
+ void testing (void) {
+ MY_CPUSET_TYPE set;
+ CPU_ZERO(&set);
+ (void)sched_setaffinity(-1, sizeof(set), &set);
+ }
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SCHED_SETAFFINITY 1" >>confdefs.h
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
#
# Checking for missing functions we can replace
#
@@ -8354,15 +8825,31 @@ esac
fi
+ac_fn_c_check_func "$LINENO" "setproctitle" "ac_cv_func_setproctitle"
+if test "x$ac_cv_func_setproctitle" = xyes; then :
+ $as_echo "#define HAVE_SETPROCTITLE 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" setproctitle.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS setproctitle.$ac_objext"
+ ;;
+esac
+
+fi
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for reallocarray" >&5
$as_echo_n "checking for reallocarray... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-$ac_includes_default
#ifndef _OPENBSD_SOURCE
#define _OPENBSD_SOURCE 1
#endif
+
+$ac_includes_default
+
#include <stdlib.h>
int main(void) {
void* p = reallocarray(NULL, 10, 100);
@@ -8377,6 +8864,30 @@ $as_echo "yes" >&6; }
$as_echo "#define HAVE_REALLOCARRAY 1" >>confdefs.h
+ ac_fn_c_check_decl "$LINENO" "reallocarray" "ac_cv_have_decl_reallocarray" "
+$ac_includes_default
+#include <stdlib.h>
+
+"
+if test "x$ac_cv_have_decl_reallocarray" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_REALLOCARRAY $ac_have_decl
+_ACEOF
+if test $ac_have_decl = 1; then :
+
+else
+
+
+$as_echo "#define REALLOCARRAY_NEEDS_DEFINES 1" >>confdefs.h
+
+
+fi
+
else
@@ -8704,7 +9215,7 @@ case "$enable_checking" in
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -W" >&5
$as_echo_n "checking whether $CC supports -W... " >&6; }
-cache=`echo W | sed 'y%.=/+-%___p_%'`
+cache=`echo W | $SED 'y%.=/+-%___p_%'`
if eval \${cv_prog_cc_flag_$cache+:} false; then :
$as_echo_n "(cached) " >&6
else
@@ -8735,7 +9246,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5
$as_echo_n "checking whether $CC supports -Wall... " >&6; }
-cache=`echo Wall | sed 'y%.=/+-%___p_%'`
+cache=`echo Wall | $SED 'y%.=/+-%___p_%'`
if eval \${cv_prog_cc_flag_$cache+:} false; then :
$as_echo_n "(cached) " >&6
else
@@ -8766,7 +9277,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wextra" >&5
$as_echo_n "checking whether $CC supports -Wextra... " >&6; }
-cache=`echo Wextra | sed 'y%.=/+-%___p_%'`
+cache=`echo Wextra | $SED 'y%.=/+-%___p_%'`
if eval \${cv_prog_cc_flag_$cache+:} false; then :
$as_echo_n "(cached) " >&6
else
@@ -8797,7 +9308,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wdeclaration-after-statement" >&5
$as_echo_n "checking whether $CC supports -Wdeclaration-after-statement... " >&6; }
-cache=`echo Wdeclaration-after-statement | sed 'y%.=/+-%___p_%'`
+cache=`echo Wdeclaration-after-statement | $SED 'y%.=/+-%___p_%'`
if eval \${cv_prog_cc_flag_$cache+:} false; then :
$as_echo_n "(cached) " >&6
else
@@ -8901,7 +9412,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5
$as_echo_n "checking for SSL... " >&6; }
if test x_$withval = x_ -o x_$withval = x_yes; then
- withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/sfw /usr/local /usr"
+ withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/sfw /usr/local /usr /usr/local/opt/openssl"
fi
for dir in $withval; do
ssldir="$dir"
@@ -10303,7 +10814,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by NSD $as_me 4.2.4, which was
+This file was extended by NSD $as_me 4.3.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -10365,7 +10876,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-NSD config.status 4.2.4
+NSD config.status 4.3.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/usr.sbin/nsd/configure.ac b/usr.sbin/nsd/configure.ac
index 75907b70aca..4e011b65ed2 100644
--- a/usr.sbin/nsd/configure.ac
+++ b/usr.sbin/nsd/configure.ac
@@ -5,9 +5,20 @@ dnl
sinclude(acx_nlnetlabs.m4)
sinclude(dnstap/dnstap.m4)
-AC_INIT(NSD,4.2.4,nsd-bugs@nlnetlabs.nl)
+AC_INIT(NSD,4.3.1,nsd-bugs@nlnetlabs.nl)
AC_CONFIG_HEADER([config.h])
+#
+# Setup the standard programs
+# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html
+
+AC_ARG_VAR(SED, [location of the sed program])
+AC_ARG_VAR(AWK, [location of the awk program])
+AC_ARG_VAR(GREP, [location of the grep program])
+AC_ARG_VAR(EGREP, [location of the egrep program])
+AC_ARG_VAR(LEX, [location of the lex program with GNU extensions (flex)])
+AC_ARG_VAR(YACC, [location of the yacc program with GNU extensions (bison)])
+
CFLAGS="$CFLAGS"
AC_AIX
if test "$ac_cv_header_minix_config_h" = "yes"; then
@@ -112,21 +123,21 @@ AC_DEFINE_UNQUOTED(ZONESDIR, ["`eval echo $zonesdir`"], [NSD default location fo
# default xfrd file location.
xfrdfile=${dbdir}/xfrd.state
-AC_ARG_WITH([xfrdfile], AC_HELP_STRING([--with-xfrdfile=path],
+AC_ARG_WITH([xfrdfile], AC_HELP_STRING([--with-xfrdfile=path],
[Pathname to the NSD xfrd zone timer state file]), [xfrdfile=$withval])
AC_DEFINE_UNQUOTED(XFRDFILE, ["`eval echo $xfrdfile`"], [Pathname to the NSD xfrd zone timer state file.])
AC_SUBST(xfrdfile)
# default zonelist file location.
zonelistfile=${dbdir}/zone.list
-AC_ARG_WITH([zonelistfile], AC_HELP_STRING([--with-zonelistfile=path],
+AC_ARG_WITH([zonelistfile], AC_HELP_STRING([--with-zonelistfile=path],
[Pathname to the NSD zone list file]), [zonelistfile=$withval])
AC_DEFINE_UNQUOTED(ZONELISTFILE, ["`eval echo $zonelistfile`"], [Pathname to the NSD zone list file.])
AC_SUBST(zonelistfile)
# default xfr dir location.
xfrdir="/tmp"
-AC_ARG_WITH([xfrdir], AC_HELP_STRING([--with-xfrdir=path],
+AC_ARG_WITH([xfrdir], AC_HELP_STRING([--with-xfrdir=path],
[Pathname to where the NSD transfer dir is created]), [xfrdir=$withval])
AC_DEFINE_UNQUOTED(XFRDIR, ["`eval echo $xfrdir`"], [Pathname to where the NSD transfer dir is created.])
AC_SUBST(xfrdir)
@@ -163,23 +174,38 @@ AC_ARG_WITH([user],
AC_SUBST(user)
AC_DEFINE_UNQUOTED(USER, ["$user"], [the user name to drop privileges to])
-# Checks for programs.
-AC_PROG_AWK
AC_PROG_CC
-AC_PROG_LN_S
-AC_PROG_INSTALL
+AC_PROG_SED
+AC_PROG_AWK
+AC_PROG_GREP
+AC_PROG_EGREP
AC_PROG_LEX
AC_PROG_YACC
+AC_PROG_LN_S
+AC_PROG_INSTALL
if test "$LEX" != ":" -a "$LEX" != ""; then
+# Solaris provides anemic tools, and they don't offer GNU extensions like
+# 'flex -i'. Solaris also does not offer GNU replacements in /usr/gnu/bin.
+AC_MSG_CHECKING([whether lex accepts -i])
+AS_IF([echo "%%" | $LEX -i -t >/dev/null 2>&1],
+ [
+ AC_MSG_RESULT([yes])
+ ],
+ [
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([unable to find a lexer that supports -i. If one is available then set the LEX variable])
+ ]
+)
+
# Check if lex defines yy_current_buffer, because 2.4.6 and older use it,
# but later could define it as a macro and then we should not redefine it.
AC_MSG_CHECKING(if lex defines yy_current_buffer)
cat <<EOF >conftest.lex
%%
EOF
- $LEX -i -t conftest.lex >> conftest.c
- if grep "^#define yy_current_buffer" conftest.c >/dev/null; then
+ $LEX -i -t conftest.lex >> conftest.c 2>/dev/null
+ if $GREP "^#define yy_current_buffer" conftest.c >/dev/null; then
AC_DEFINE_UNQUOTED(LEX_DEFINES_YY_CURRENT_BUFFER, 1, [If flex defines yy_current_buffer as a macro])
AC_MSG_RESULT(yes)
else
@@ -257,7 +283,7 @@ AC_DEFUN([CHECK_COMPILER_FLAG],
[
AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING(whether $CC supports -$1)
-cache=`echo $1 | sed 'y%.=/+-%___p_%'`
+cache=`echo $1 | $SED 'y%.=/+-%___p_%'`
AC_CACHE_VAL(cv_prog_cc_flag_$cache,
[
echo 'void f(){}' >conftest.c
@@ -331,14 +357,14 @@ AC_CHECK_CTIME_R
AC_DEFUN([CHECK_SSL], [
AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
[enable SSL (will check /usr/local/ssl
- /usr/lib/ssl /usr/ssl /usr/pkg /usr/sfw /usr/local /usr)]),[
+ /usr/lib/ssl /usr/ssl /usr/pkg /usr/sfw /usr/local /usr /usr/local/opt/openssl)]),[
],[
withval="yes"
])
if test x_$withval != x_no; then
AC_MSG_CHECKING(for SSL)
if test x_$withval = x_ -o x_$withval = x_yes; then
- withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/sfw /usr/local /usr"
+ withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/sfw /usr/local /usr /usr/local/opt/openssl"
fi
for dir in $withval; do
ssldir="$dir"
@@ -350,12 +376,12 @@ AC_DEFUN([CHECK_SSL], [
fi
break;
fi
- done
+ done
if test x_$found_ssl != x_yes; then
AC_MSG_ERROR(Cannot find the SSL libraries in $withval)
else
AC_MSG_RESULT(found in $ssldir)
- HAVE_SSL=yes
+ HAVE_SSL=yes
if test x_$ssldir != x_/usr; then
LDFLAGS="$LDFLAGS -L$ssldir/lib";
fi
@@ -369,12 +395,12 @@ AC_DEFUN([CHECK_SSL], [
# check for libevent
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
- [use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr or you can specify an explicit path), useful when the zone count is high.]),
+ [use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr /usr/local/opt/libevent or you can specify an explicit path), useful when the zone count is high.]),
[ ],[ withval="yes" ])
if test x_$withval = x_yes -o x_$withval != x_no; then
AC_MSG_CHECKING(for libevent)
if test x_$withval = x_ -o x_$withval = x_yes; then
- withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
+ withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr /usr/local/opt/libevent"
fi
for dir in $withval; do
thedir="$dir"
@@ -393,7 +419,7 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
AC_MSG_RESULT(found in $thedir)
CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
# remove evdns from linking
- ev_files_o=`ls $thedir/*.o | grep -v evdns\.o | grep -v bufferevent_openssl\.o`
+ ev_files_o=`ls $thedir/*.o | $GREP -v evdns\.o | $GREP -v bufferevent_openssl\.o`
cp $ev_files_o .
LDFLAGS="$ev_files_o $LDFLAGS -lm"
else
@@ -439,7 +465,7 @@ fi
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS([time.h arpa/inet.h signal.h string.h strings.h fcntl.h limits.h netinet/in.h netinet/tcp.h stddef.h sys/param.h sys/socket.h sys/un.h syslog.h unistd.h sys/select.h stdarg.h stdint.h netdb.h sys/bitypes.h tcpd.h glob.h grp.h endian.h])
+AC_CHECK_HEADERS([time.h arpa/inet.h signal.h string.h strings.h fcntl.h limits.h netinet/in.h netinet/tcp.h stddef.h sys/param.h sys/socket.h sys/un.h syslog.h unistd.h sys/select.h stdarg.h stdint.h netdb.h sys/bitypes.h tcpd.h glob.h grp.h endian.h sys/random.h])
AC_DEFUN([CHECK_VALIST_DEF],
[
@@ -505,7 +531,7 @@ if test c${cross_compiling} = cno; then
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#define _XOPEN_SOURCE 600
#include <time.h>
-int main(void) { struct tm tm; char *res;
+int main(void) { struct tm tm; char *res;
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
if (!res) return 1; return 0; }
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"])
@@ -588,7 +614,7 @@ if test $ac_cv_type_$1 = no; then
fi
])
-AC_LIBGTOP_CHECK_TYPE(int8_t, char)
+AC_LIBGTOP_CHECK_TYPE(int8_t, char)
AC_LIBGTOP_CHECK_TYPE(int16_t, short)
AC_LIBGTOP_CHECK_TYPE(int32_t, int)
AC_LIBGTOP_CHECK_TYPE(int64_t, long long)
@@ -626,7 +652,7 @@ AC_FUNC_FSEEKO
AC_SYS_LARGEFILE
AC_CHECK_SIZEOF(void*)
AC_CHECK_SIZEOF(off_t)
-AC_CHECK_FUNCS([arc4random arc4random_uniform])
+AC_CHECK_FUNCS([getrandom arc4random arc4random_uniform])
AC_SEARCH_LIBS([setusercontext],[util],[AC_CHECK_HEADERS([login_cap.h])])
AC_CHECK_FUNCS([tzset alarm chroot dup2 endpwent gethostname memset memcpy pwrite socket strcasecmp strchr strdup strerror strncasecmp strtol writev getaddrinfo getnameinfo freeaddrinfo gai_strerror sigaction sigprocmask strptime strftime localtime_r setusercontext glob initgroups setresuid setreuid setresgid setregid getpwnam mmap ppoll clock_gettime accept4])
@@ -643,7 +669,7 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sys/socket.h>
#include <errno.h>
int main(void)
-{
+{
int s = socket(AF_INET, SOCK_DGRAM, 0);
int r = recvmmsg(s, 0, 0, 0, 0) == -1 && errno == ENOSYS;
close(s);
@@ -659,7 +685,7 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <sys/socket.h>
#include <errno.h>
int main(void)
-{
+{
int s = socket(AF_INET, SOCK_DGRAM, 0);
int r = sendmmsg(s, 0, 0, 0) == -1 && errno == ENOSYS;
close(s);
@@ -677,10 +703,103 @@ AC_DEFINE([HAVE_SENDMMSG], [1], [Define if sendmmsg exists])]
esac
# check if setreuid en setregid fail, on MacOSX10.4(darwin8).
-if echo $target_os | grep darwin8 > /dev/null; then
+if echo $target_os | $GREP -i darwin8 > /dev/null; then
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
fi
+# GNU HURD needs _GNU_SOURCE defined for cpu affinity gear
+if echo $target_os | $EGREP -i 'linux|hurd' > /dev/null; then
+ AC_DEFINE([_GNU_SOURCE, 1, [Define this if on Linux or GNU Hurd for cpu affinity interface]])
+fi
+
+# see comment on _GNU_SOURCE above
+AC_CHECK_HEADERS([sched.h sys/cpuset.h])
+
+# Check for cpu_set_t (Linux) and cpuset_t (FreeBSD and NetBSD)
+AC_CHECK_TYPES([cpu_set_t, cpuset_t, cpuid_t],,,[
+AC_INCLUDES_DEFAULT
+#if HAVE_SCHED_H
+# include <sched.h>
+#endif
+#if HAVE_SYS_CPUSET_H
+# include <sys/cpuset.h>
+#endif
+])
+
+AC_DEFUN([AC_CHECK_CPU_OR],
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING(whether CPU_OR works with three arguments)
+AC_TRY_COMPILE(
+[#ifdef HAVE_SCHED_H
+# include <sched.h>
+#endif
+#ifdef HAVE_SYS_CPUSET_H
+# include <sys/cpuset.h>
+#endif
+#include <string.h>
+#ifdef HAVE_CPUSET_T
+#define MY_CPUSET_TYPE cpuset_t
+#endif
+#ifdef HAVE_CPU_SET_T
+#define MY_CPUSET_TYPE cpu_set_t
+#endif
+void testing (void) {
+ MY_CPUSET_TYPE a, b;
+ memset(&a, 0, sizeof(a));
+ memset(&b, 0, sizeof(b));
+ CPU_OR(&a, &a, &b);
+}], [
+ testing();
+], [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE([CPU_OR_THREE_ARGS], 1, [number of arguments for CPU_OR is three])
+], [
+ AC_MSG_RESULT(no)
+])])
+
+AS_IF([test x"$ac_cv_type_cpuset_t" = xyes -o x"$ac_cv_type_cpu_set_t" = xyes ],[
+ AC_CHECK_FUNC(cpuset_create)
+ AC_CHECK_FUNC(cpuset_destroy)
+ AC_CHECK_FUNC(cpuset_zero)
+ AC_CHECK_FUNC(cpuset_set)
+ AC_CHECK_FUNC(cpuset_clr)
+ AC_CHECK_FUNC(cpuset_isset)
+ AC_CHECK_FUNC(cpuset_size)
+ AC_LIBOBJ(cpuset)
+ AC_CHECK_FUNCS([sysconf])
+ AC_CHECK_CPU_OR
+])
+
+#
+# sched_setaffinity must be checked using proper includes.
+# also needs _GNU_SOURCE on Linux and Hurd; see above.
+# also see https://github.com/NLnetLabs/nsd/issues/82.
+#
+AC_MSG_CHECKING(for sched_setaffinity)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+ [[
+ #ifdef HAVE_SCHED_H
+ # include <sched.h>
+ #endif
+ #ifdef HAVE_SYS_CPUSET_H
+ #include <sys/cpuset.h>
+ #endif
+ #ifdef HAVE_CPUSET_T
+ #define MY_CPUSET_TYPE cpuset_t
+ #endif
+ #ifdef HAVE_CPU_SET_T
+ #define MY_CPUSET_TYPE cpu_set_t
+ #endif
+ void testing (void) {
+ MY_CPUSET_TYPE set;
+ CPU_ZERO(&set);
+ (void)sched_setaffinity(-1, sizeof(set), &set);
+ }
+]])],
+[ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SCHED_SETAFFINITY, 1, [Define this if sched_setaffinity is available])],
+[ AC_MSG_RESULT(no)])
+
#
# Checking for missing functions we can replace
#
@@ -694,12 +813,16 @@ AC_REPLACE_FUNCS(strlcpy)
AC_REPLACE_FUNCS(strptime)
AC_REPLACE_FUNCS(pselect)
AC_REPLACE_FUNCS(memmove)
+AC_REPLACE_FUNCS(setproctitle)
AC_MSG_CHECKING([for reallocarray])
-AC_LINK_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT
+AC_LINK_IFELSE([AC_LANG_SOURCE(
[[
#ifndef _OPENBSD_SOURCE
#define _OPENBSD_SOURCE 1
#endif
+]]
+AC_INCLUDES_DEFAULT
+[[
#include <stdlib.h>
int main(void) {
void* p = reallocarray(NULL, 10, 100);
@@ -708,6 +831,12 @@ int main(void) {
}
]])], [AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_REALLOCARRAY, 1, [If we have reallocarray(3)])
+ AC_CHECK_DECLS([reallocarray], [], [
+ AC_DEFINE(REALLOCARRAY_NEEDS_DEFINES, 1, [If reallocarray needs defines to appear in the headers])
+ ], [
+AC_INCLUDES_DEFAULT
+#include <stdlib.h>
+ ])
], [
AC_MSG_RESULT(no)
AC_LIBOBJ(reallocarray)
@@ -749,11 +878,11 @@ else
fi
AC_MSG_CHECKING(for pselect prototype in sys/select.h)
-AC_EGREP_HEADER([[^a-zA-Z_]*pselect[^a-zA-Z_]], sys/select.h, AC_DEFINE(HAVE_PSELECT_PROTO, 1,
+AC_EGREP_HEADER([[^a-zA-Z_]*pselect[^a-zA-Z_]], sys/select.h, AC_DEFINE(HAVE_PSELECT_PROTO, 1,
[if sys/select.h provides pselect prototype]) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
AC_MSG_CHECKING(for ctime_r prototype in time.h)
-AC_EGREP_HEADER([[^a-zA-Z_]*ctime_r[^a-zA-Z_]], time.h, AC_DEFINE(HAVE_CTIME_R_PROTO, 1,
+AC_EGREP_HEADER([[^a-zA-Z_]*ctime_r[^a-zA-Z_]], time.h, AC_DEFINE(HAVE_CTIME_R_PROTO, 1,
[if time.h provides ctime_r prototype]) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
AC_CHECK_TYPE([struct timespec], AC_DEFINE(HAVE_STRUCT_TIMESPEC, 1, [If time.h has a struct timespec (for pselect).]), [], [
@@ -909,7 +1038,7 @@ if test x$HAVE_SSL = x"yes"; then
])
LIBS="$BAKLIBS"
- if test -n "$ssldir"; then
+ if test -n "$ssldir"; then
AC_CHECK_LIB(crypto, HMAC_Update,, [
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
])
@@ -1046,7 +1175,7 @@ AH_BOTTOM([
/* define before includes as it specifies what standard to use. */
#if (defined(HAVE_PSELECT) && !defined (HAVE_PSELECT_PROTO)) \
|| !defined (HAVE_CTIME_R_PROTO) \
- || defined (STRPTIME_NEEDS_DEFINES)
+ || defined (STRPTIME_NEEDS_DEFINES) || defined(REALLOCARRAY_NEEDS_DEFINES)
# ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 600
# endif
@@ -1064,7 +1193,7 @@ AH_BOTTOM([
# endif
# ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
-# endif
+# endif
# ifndef _STDC_C99
# define _STDC_C99 1
# endif
@@ -1196,13 +1325,23 @@ void* reallocarray(void *ptr, size_t nmemb, size_t size);
#endif
#ifndef HAVE_STRPTIME
#define HAVE_STRPTIME 1
-char *strptime(const char *s, const char *format, struct tm *tm);
+char *strptime(const char *s, const char *format, struct tm *tm);
#endif
#ifndef STRPTIME_WORKS
#define STRPTIME_WORKS 1
-char *nsd_strptime(const char *s, const char *format, struct tm *tm);
+char *nsd_strptime(const char *s, const char *format, struct tm *tm);
#define strptime(a,b,c) nsd_strptime((a),(b),(c))
#endif
+#if (HAVE_CPU_SET_T || HAVE_CPUSET_T)
+#include "compat/cpuset.h"
+#endif
+#ifndef HAVE_SETPROCTITLE
+#ifdef __linux__
+#define HAVE_SETPROCTITLE 1
+#include <stdarg.h>
+void setproctitle(char *fmt, ...);
+#endif
+#endif
])
AH_BOTTOM(
AHX_MEMCMP_BROKEN(nsd)
diff --git a/usr.sbin/nsd/dbaccess.c b/usr.sbin/nsd/dbaccess.c
index da0762e9750..9e432fea7ca 100644
--- a/usr.sbin/nsd/dbaccess.c
+++ b/usr.sbin/nsd/dbaccess.c
@@ -210,19 +210,19 @@ static void read_zone_recurse(udb_base* udb, namedb_type* db,
/* pre-order process of node->elem, for radix tree this is
* also in-order processing (identical to order tree_next()) */
read_node_elem(udb, db, dname_region, zone, (struct domain_d*)
- (udb->base + node->elem.data));
+ ((char*)udb->base + node->elem.data));
}
if(node->lookup.data) {
uint16_t i;
struct udb_radarray_d* a = (struct udb_radarray_d*)
- (udb->base + node->lookup.data);
+ ((char*)udb->base + node->lookup.data);
/* we do not care for what the exact radix key is, we want
* to add all of them and the read routine does not need
* the radix-key, it has it stored */
for(i=0; i<a->len; i++) {
if(a->array[i].node.data) {
read_zone_recurse(udb, db, dname_region, zone,
- (struct udb_radnode_d*)(udb->base +
+ (struct udb_radnode_d*)((char*)udb->base +
a->array[i].node.data));
}
}
@@ -240,7 +240,7 @@ read_zone_data(udb_base* udb, namedb_type* db, region_type* dname_region,
if(RADTREE(&dtree)->root.data)
read_zone_recurse(udb, db, dname_region, zone,
(struct udb_radnode_d*)
- (udb->base + RADTREE(&dtree)->root.data));
+ ((char*)udb->base + RADTREE(&dtree)->root.data));
udb_ptr_unlink(&dtree, udb);
}
@@ -527,6 +527,7 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
mtime.tv_sec = 0;
mtime.tv_nsec = 0;
fname = config_make_zonefile(zone->opts, nsd);
+ assert(fname);
if(!file_get_mtime(fname, &mtime, &nonexist)) {
if(nonexist) {
VERBOSITY(2, (LOG_INFO, "zonefile %s does not exist",
@@ -559,8 +560,7 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
/* if zone_fname, then the file was acquired from reading it,
* and see if filename changed or mtime newer to read it */
- } else if(zone_fname && fname &&
- strcmp(zone_fname, fname) == 0 &&
+ } else if(zone_fname && strcmp(zone_fname, fname) == 0 &&
timespec_compare(&zone_mtime, &mtime) == 0) {
VERBOSITY(3, (LOG_INFO, "zonefile %s is not modified",
fname));
diff --git a/usr.sbin/nsd/dbcreate.c b/usr.sbin/nsd/dbcreate.c
index 1d91225f092..b80d24083f1 100644
--- a/usr.sbin/nsd/dbcreate.c
+++ b/usr.sbin/nsd/dbcreate.c
@@ -296,6 +296,7 @@ create_dirs(const char* path)
if(errno != EEXIST) {
log_msg(LOG_ERR, "create dir %s: %s",
dir, strerror(errno));
+ *p = PATHSEP; /* restore input string */
return 0;
}
/* it already exists, OK, continue */
diff --git a/usr.sbin/nsd/difffile.c b/usr.sbin/nsd/difffile.c
index b3aee0b4530..445745d2d5f 100644
--- a/usr.sbin/nsd/difffile.c
+++ b/usr.sbin/nsd/difffile.c
@@ -1042,6 +1042,12 @@ apply_ixfr(namedb_type* db, FILE *in, const char* zone, uint32_t serialno,
qcount = QDCOUNT(packet);
ancount = ANCOUNT(packet);
buffer_skip(packet, QHEADERSZ);
+ /* qcount should be 0 or 1 really, ancount limited by 64k packet */
+ if(qcount > 64 || ancount > 65530) {
+ log_msg(LOG_ERR, "RR count impossibly high");
+ region_destroy(region);
+ return 0;
+ }
/* skip queries */
for(i=0; i<qcount; ++i)
@@ -1631,7 +1637,7 @@ void* task_new_stat_info(udb_base* udb, udb_ptr* last, struct nsdst* stat,
p = TASKLIST(&e)->zname;
memcpy(p, stat, sizeof(*stat));
udb_ptr_unlink(&e, udb);
- return p + sizeof(*stat);
+ return (char*)p + sizeof(*stat);
}
#endif /* BIND8_STATS */
@@ -1653,7 +1659,7 @@ task_new_add_zone(udb_base* udb, udb_ptr* last, const char* zone,
TASKLIST(&e)->yesno = zonestatid;
p = TASKLIST(&e)->zname;
memcpy(p, zone, zlen+1);
- memmove(p+zlen+1, pattern, plen+1);
+ memmove((char*)p+zlen+1, pattern, plen+1);
udb_ptr_unlink(&e, udb);
}
diff --git a/usr.sbin/nsd/doc/ChangeLog b/usr.sbin/nsd/doc/ChangeLog
index 5070b61afc6..09ea79bafd3 100644
--- a/usr.sbin/nsd/doc/ChangeLog
+++ b/usr.sbin/nsd/doc/ChangeLog
@@ -1,8 +1,185 @@
+8 April 2020: Wouter
+ - Tag for 4.3.1rc2.
+
+7 April 2020: Wouter
+ - Merge PR #91 by gearnode: nsd-control-setup recreate certificates.
+ The '-r' option recreates certificates. Without it it creates them
+ if they do not exist, and does not modify them otherwise.
+
+6 April 2020: Wouter
+ - Merge PR #90 by phicoh: O_CLOEXEC should be FD_CLOEXEC.
+ - Merge PR #92 by tonysgi: Fix typo.
+
+2 April 2020: Wouter
+ - Tag for 4.3.1rc1.
+
+1 April 2020: Wouter
+ - Fix for whitespace in minimal responses test for FreeBSD.
+
+25 March 2020: Wouter
+ - Merge PR #86 from noloader: Use precious variables for GREP, EGREP,
+ SED, AWK, LEX and YACC.
+ - For PR #86: Fix that programs loaded after CFLAGS and stuff is
+ set, specifically the compiler, so that it can work if it needs
+ special flags from that. Fix that lex only needs to support -i
+ if actually defined, otherwise the output included in the source
+ tarball can be used.
+ - Merge PR #72 from noloader: Increase Travis testing coverage
+
+23 March 2020: Wouter
+ - Fix unterminated ifdef in nsd.h.
+ - Fix unknown u_long in util.c for Issue #80 .
+
+20 March 2020: Wouter
+ - Merge PR #83 from noloader: Fix GNU HURD sched_setaffinity compile.
+ - Fix #82: print error when system does not have setaffinity.
+ - Fix #80: NetBSD and implicit declaration of reallocarray.
+ - Fix for #80: Fix reallocarray test to define before include.
+ - Fix for #80: Define alternatives for IFNAMSIZ if it does not exist.
+
+19 March 2020: Wouter
+ - Fix #76: cpuid typedef for Hurd, DragonflyBSD compile.
+ - Fix #75: configure test for sched_setaffinity, and use
+ cpuset_setaffinity otherwise. Also test for presence of sysconf.
+ - Fix #74: GNU Hurd fix cast from pointer to integer of different size.
+ - Fix for #74, #75: cpuset test for header contents and provide code.
+ - Fix #78: Fix SO_SETFIB error on FreeBSD.
+
+18 March 2020: Wouter
+ - Fix #70: error: 'fd_set' undeclared.
+ - Fix #71: error: 'for' loop initial declaration used outside C99
+ mode.
+ - Fix to move declarations out of for loops in event test too.
+ - Fix to move declarations out of for loops in popen3 test too.
+ - Another fix to move declaration out of for loop for event test.
+ - Fix to move declarations out of for loops in cutest regex display.
+
+17 March 2020: Wouter
+ - tag for 4.3.0 release and master branch has version 4.3.1.
+
+10 March 2020: Wouter
+ - repository has version number 4.3.0. Tag for 4.3.0rc1.
+
+3 March 2020: Wouter
+ - Fix that the retry wait does not exceed one day for zone transfers.
+
+27 February 2020: Wouter
+ - Fix warning on FreeBSD about pointer size cast.
+
+26 February 2020: Wouter
+ - Fixup fix of reuseport TCP for server close of sockets not used
+ by it. And the unit test skips when the necessary debug output
+ is not enabled.
+
+25 February 2020: Wouter
+ - Fix event unit test, signal has to be registered with signal_add,
+ event_add not for every backend for signals. The event_initialized
+ is not possible for every backend, so event_added variable. The
+ agent write event fires after a timeout, instead of on event write
+ so that it does not trigger a sigpipe event when the handlers stop.
+ Timeout shorted to 0.1 second. event_get_fd was not implemented,
+ so used ev_fd. Debug output printfs added to see what happens.
+ - Fix checkconf test for new drop-updates config option.
+ - Fix errors with reuseport and TCP file descriptors, it was
+ closing them for server-1 in server-2 and server-3..
+
+7 February 2020: Jeroen
+ - Add feature to drop queries with opcode UPDATE.
+
+6 February 2020: Jeroen
+ - Support SO_BINDTODEVICE on Linux. Specify bindtodevice: yes
+ to bind sockets directly to the network interface.
+ - Support SO_SETFIB on FreeBSD. Add setfib=<FIB> after an ip-address
+ option to use the specified FIB for that socket.
+ - Require user to add servers=<range> after an ip-address option to
+ specify the servers that must listen on that socket.
+
+6 February 2020: Wouter
+ - Merge PR#60: Minor portability fixes from michaelforney, with
+ avoid pointer arithmetic on void* and avoid unnecessary VLA.
+
+4 February 2020: Wouter
+ - Merge PR#22: minimise-any: prefer polular and not large RRset,
+ from Daisuke Higashi.
+ - Fix responses for IXFR so that the authority section is not echoed
+ in the response.
+
+21 January 2020: Wouter
+ - Fix leak in server bitset setup.
+
+16 January 2020: Jeroen
+ - Add zone resource record iterator for future zone-verification port.
+ - Set FD_CLOEXEC on opened sockets.
+ - Add popen3 implementation for future zone-verification port.
+ - Add -r option to cutest so that a subset of tests can be run.
+
+15 January 2020: Jeroen
+ - Add feature to pin server proccesses to specific cpus.
+ - Add feature to pin IP addresses to selected server processes.
+ - Set process title to identify individual processes.
+
+13 January 2020: Wouter
+ - Merge pull request #59 from buddyns: add FreeBSD support
+ for conf key ip-transparent.
+
+10 January 2020: Wouter
+ - Fix unreachable code in ssl set options code.
+ - Fix bad shift in assertion code analyzer complaint.
+
+6 January 2020: Wouter
+ - Fix #56: Drop sparse TSIG signing support in NSD.
+ Sign every axfr packet with TSIG, according to the latest
+ draft-ietf-dnsop-rfc2845bis-06, Section 5.3.1.
+
+12 December 2019: Wouter
+ - Note that use-systemd is not necessary and ignored in man page.
+
+11 December 2019: Wouter
+ - Fix whitespace in nsd.conf.sample.in, patch from Paul Wouters.
+ - use-systemd is ignored in nsd.conf, when NSD is compiled with
+ libsystemd it always signals readiness, if possible.
+
+9 December 2019: Wouter
+ - Fix to define upper bounds on rr counts read from untrusted packet
+ data.
+ - Try different annotation for radix_find_prefix_node not reachable.
+ - Separate acl_addr_match_range functions for ip4 and ip6, to
+ please checkers.
+ - Avoid unused variable warning in new match_range_v4 function.
+
+6 December 2019: Wouter
+ - Fix to define max number of EDNS records we are willing to
+ spend time on.
+ - Fix size of string len and capacity type cast in udbradtree.
+ - Fix to protect rrcount in tsig_find_rr from overflow.
+ - Annotate radix_find_prefix_node not reachable trail code.
+ - Fix to protect rrcount in packet_find_notify_serial from overflow.
+ - Fix to close socket on error in create_tcp_accept_sock.
+ - Fix to log on failure to chmod for socket for remote control.
+ - Fix to remove unneeded if in open of socket for remote control.
+ - Fix to restore input parameter on call failure in create_dirs.
+ - Please checker by terminating and initialising string read
+ by remote control.
+ - Fixup of random_generate negative modulo, from previous commit,
+ and return srandom when random is used if no getrandom.
+
+5 December 2019: Wouter
+ - Fix fname null check of fname in namedb_read_zonefile.
+ - Fix implicit cast of size in udb_radnode_array_grow.
+ - Fix ignore of return value of ssl_printf in remote.c.
+ - Fix unused check of fd in parent_handle_reload_command.
+ - Fix to use getrandom() for randomness, if available.
+ - Attempt to fix signedness of nscount lookup in ixfr query_process.
+ - Fix identical branches for ssl_print of errors in remote.c.
+ - Fix type cast bounds, signedness of opt_rdlen in edns_parse_record.
+ - Fix to separate header and data lines in parse_zone_list_file.
+
3 December 2019: Wouter
- Fix #52: do not log transient network full errors unless higher
verbosity is set.
- Fix checkconf test for new error output string.
- - tag for 4.2.4rc1 release.
+ - tag for 4.2.4rc1 release. This became the 4.2.4 release,
+ and the master branch continues with 4.2.5 in development.
27 November 2017 Jeroen
- Fix regressions in configparser.y
diff --git a/usr.sbin/nsd/doc/RELNOTES b/usr.sbin/nsd/doc/RELNOTES
index d4f1dc66b8e..f1d30850703 100644
--- a/usr.sbin/nsd/doc/RELNOTES
+++ b/usr.sbin/nsd/doc/RELNOTES
@@ -1,5 +1,93 @@
NSD RELEASE NOTES
+4.3.1
+================
+BUG FIXES:
+ - Fix #70: error: 'fd_set' undeclared.
+ - Fix #71: error: 'for' loop initial declaration used outside C99
+ mode.
+ - Fix to move declarations out of for loops in event test too.
+ - Fix #76: cpuid typedef for Hurd, DragonflyBSD compile.
+ - Fix #75: configure test for sched_setaffinity, and use
+ cpuset_setaffinity otherwise. Also test for presence of sysconf.
+ - Fix #74: GNU Hurd fix cast from pointer to integer of different size.
+ - Fix for #74, #75: cpuset test for header contents and provide code.
+ - Fix #78: Fix SO_SETFIB error on FreeBSD.
+ - Merge PR #83 from noloader: Fix GNU HURD sched_setaffinity compile.
+ - Fix #80: NetBSD and implicit declaration of reallocarray.
+ - Fix unknown u_long in util.c for Issue #80 .
+ - Merge PR #86 from noloader: Use precious variables for GREP, EGREP,
+ SED, AWK, LEX and YACC.
+ - For PR #86: Fix that programs loaded after CFLAGS and stuff is
+ set, specifically the compiler, so that it can work if it needs
+ special flags from that. Fix that lex only needs to support -i
+ if actually defined, otherwise the output included in the source
+ tarball can be used.
+ - Merge PR #90 by phicoh: O_CLOEXEC should be FD_CLOEXEC.
+ - Merge PR #92 by tonysgi: Fix typo.
+ - Merge PR #91 by gearnode: nsd-control-setup recreate certificates.
+ The '-r' option recreates certificates. Without it it creates them
+ if they do not exist, and does not modify them otherwise.
+
+
+4.3.0
+================
+FEATURES:
+ - Fix to use getrandom() for randomness, if available.
+ - Fix #56: Drop sparse TSIG signing support in NSD.
+ Sign every axfr packet with TSIG, according to the latest
+ draft-ietf-dnsop-rfc2845bis-06, Section 5.3.1.
+ - Merge pull request #59 from buddyns: add FreeBSD support
+ for conf key ip-transparent.
+ - Add feature to pin server processes to specific cpus.
+ - Add feature to pin IP addresses to selected server processes.
+ - Set process title to identify individual processes.
+ - Merge PR#22: minimise-any: prefer polular and not large RRset,
+ from Daisuke Higashi.
+ - Add support for SO_BINDTODEVICE on Linux.
+ - Add support for SO_SETFIB on FreeBSD.
+ - Add feature to drop queries with opcode UPDATE.
+BUG FIXES:
+ - Fix fname null check of fname in namedb_read_zonefile.
+ - Fix implicit cast of size in udb_radnode_array_grow.
+ - Fix ignore of return value of ssl_printf in remote.c.
+ - Fix unused check of fd in parent_handle_reload_command.
+ - Attempt to fix signedness of nscount lookup in ixfr query_process.
+ - Fix identical branches for ssl_print of errors in remote.c.
+ - Fix type cast bounds, signedness of opt_rdlen in edns_parse_record.
+ - Fix to separate header and data lines in parse_zone_list_file.
+ - Fix to define max number of EDNS records we are willing to
+ spend time on.
+ - Fix size of string len and capacity type cast in udbradtree.
+ - Fix to protect rrcount in tsig_find_rr from overflow.
+ - Annotate radix_find_prefix_node not reachable trail code.
+ - Fix to protect rrcount in packet_find_notify_serial from overflow.
+ - Fix to close socket on error in create_tcp_accept_sock.
+ - Fix to log on failure to chmod for socket for remote control.
+ - Fix to remove unneeded if in open of socket for remote control.
+ - Fix to restore input parameter on call failure in create_dirs.
+ - Please checker by terminating and initialising string read
+ by remote control.
+ - Fix to define upper bounds on rr counts read from untrusted packet
+ data.
+ - Separate acl_addr_match_range functions for ip4 and ip6, to
+ please checkers.
+ - Avoid unused variable warning in new match_range_v4 function.
+ - Fix whitespace in nsd.conf.sample.in, patch from Paul Wouters.
+ - use-systemd is ignored in nsd.conf, when NSD is compiled with
+ libsystemd it always signals readiness, if possible.
+ - Note that use-systemd is not necessary and ignored in man page.
+ - Fix unreachable code in ssl set options code.
+ - Fix bad shift in assertion code analyzer complaint.
+ - Fix responses for IXFR so that the authority section is not echoed
+ in the response.
+ - Merge PR#60: Minor portability fixes from michaelforney, with
+ avoid pointer arithmetic on void* and avoid unnecessary VLA.
+ - Fix that the retry wait does not exceed one day for zone transfers.
+CHANGES:
+ - Set FD_CLOEXEC on opened sockets.
+
+
4.2.4
================
FEATURES:
diff --git a/usr.sbin/nsd/edns.c b/usr.sbin/nsd/edns.c
index 72a38d0a300..c6012b21111 100644
--- a/usr.sbin/nsd/edns.c
+++ b/usr.sbin/nsd/edns.c
@@ -128,13 +128,16 @@ edns_parse_record(edns_record_type *edns, buffer_type *packet,
if (opt_rdlen > 0) {
if(!buffer_available(packet, opt_rdlen))
return 0;
+ if(opt_rdlen > 65530)
+ return 0;
/* there is more to come, read opt code */
while(opt_rdlen >= 4) {
uint16_t optcode = buffer_read_u16(packet);
uint16_t optlen = buffer_read_u16(packet);
- if(opt_rdlen < 4+optlen)
+ opt_rdlen -= 4;
+ if(opt_rdlen < optlen)
return 0; /* opt too long, formerr */
- opt_rdlen -= (4+optlen);
+ opt_rdlen -= optlen;
if(!edns_handle_option(optcode, optlen, packet,
edns, query, nsd))
return 0;
diff --git a/usr.sbin/nsd/ipc.c b/usr.sbin/nsd/ipc.c
index 190e30a0cf0..86d5f5463da 100644
--- a/usr.sbin/nsd/ipc.c
+++ b/usr.sbin/nsd/ipc.c
@@ -530,10 +530,10 @@ parent_handle_reload_command(netio_type *ATTR_UNUSED(netio),
}
if (len == 0)
{
- if(handler->fd != -1) {
- close(handler->fd);
- handler->fd = -1;
- }
+ assert(handler->fd != -1); /* or read() would have failed */
+ close(handler->fd);
+ handler->fd = -1;
+
log_msg(LOG_ERR, "handle_reload_cmd: reload closed cmd channel");
nsd->reload_failed = 1;
return;
diff --git a/usr.sbin/nsd/namedb.c b/usr.sbin/nsd/namedb.c
index 9ca5ffcbebb..d034649af1a 100644
--- a/usr.sbin/nsd/namedb.c
+++ b/usr.sbin/nsd/namedb.c
@@ -701,3 +701,65 @@ namedb_lookup(struct namedb* db,
return domain_table_search(
db->domains, dname, closest_match, closest_encloser);
}
+
+void zone_rr_iter_init(struct zone_rr_iter *iter, struct zone *zone)
+{
+ assert(iter != NULL);
+ assert(zone != NULL);
+ memset(iter, 0, sizeof(*iter));
+ iter->zone = zone;
+}
+
+rr_type *zone_rr_iter_next(struct zone_rr_iter *iter)
+{
+ assert(iter != NULL);
+ assert(iter->zone != NULL);
+
+ if(iter->index == -1) {
+ assert(iter->domain == NULL);
+ assert(iter->rrset == NULL);
+ return NULL;
+ } else if(iter->rrset == NULL) {
+ /* ensure SOA RR is returned first */
+ assert(iter->domain == NULL);
+ assert(iter->index == 0);
+ iter->rrset = iter->zone->soa_rrset;
+ }
+
+ while(iter->rrset != NULL) {
+ if(iter->index < iter->rrset->rr_count) {
+ return &iter->rrset->rrs[iter->index++];
+ }
+ iter->index = 0;
+ if(iter->domain == NULL) {
+ assert(iter->rrset == iter->zone->soa_rrset);
+ iter->domain = iter->zone->apex;
+ iter->rrset = iter->domain->rrsets;
+ } else {
+ iter->rrset = iter->rrset->next;
+ }
+ /* ensure SOA RR is not returned again and RR belongs to zone */
+ while((iter->rrset == NULL && iter->domain != NULL) ||
+ (iter->rrset != NULL && (iter->rrset == iter->zone->soa_rrset ||
+ iter->rrset->zone != iter->zone)))
+ {
+ if(iter->rrset != NULL) {
+ iter->rrset = iter->rrset->next;
+ } else {
+ iter->domain = domain_next(iter->domain);
+ if(iter->domain != NULL &&
+ dname_is_subdomain(domain_dname(iter->domain),
+ domain_dname(iter->zone->apex)))
+ {
+ iter->rrset = iter->domain->rrsets;
+ }
+ }
+ }
+ }
+
+ assert(iter->rrset == NULL);
+ assert(iter->domain == NULL);
+ iter->index = -1;
+
+ return NULL;
+}
diff --git a/usr.sbin/nsd/namedb.h b/usr.sbin/nsd/namedb.h
index c7cf6d96802..4eb4d6852ed 100644
--- a/usr.sbin/nsd/namedb.h
+++ b/usr.sbin/nsd/namedb.h
@@ -443,4 +443,21 @@ rrset_rrclass(rrset_type* rrset)
return rrset->rrs[0].klass;
}
-#endif
+/*
+ * zone_rr_iter can be used to iterate over all RRs in a given zone. the
+ * SOA RRSET is guaranteed to be returned first.
+ */
+typedef struct zone_rr_iter zone_rr_iter_type;
+
+struct zone_rr_iter {
+ zone_type *zone;
+ domain_type *domain;
+ rrset_type *rrset;
+ ssize_t index;
+};
+
+void zone_rr_iter_init(zone_rr_iter_type *iter, zone_type *zone);
+
+rr_type *zone_rr_iter_next(zone_rr_iter_type *iter);
+
+#endif /* _NAMEDB_H_ */
diff --git a/usr.sbin/nsd/nsd-checkconf.8.in b/usr.sbin/nsd/nsd-checkconf.8.in
index 748cc25dec5..37179ffb0f6 100644
--- a/usr.sbin/nsd/nsd-checkconf.8.in
+++ b/usr.sbin/nsd/nsd-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-checkconf" "8" "Dec 10, 2019" "NLnet Labs" "nsd 4.2.4"
+.TH "nsd\-checkconf" "8" "Apr 16, 2020" "NLnet Labs" "nsd 4.3.1"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
diff --git a/usr.sbin/nsd/nsd-checkconf.c b/usr.sbin/nsd/nsd-checkconf.c
index 731a74fab40..0808d85dc73 100644
--- a/usr.sbin/nsd/nsd-checkconf.c
+++ b/usr.sbin/nsd/nsd-checkconf.c
@@ -367,6 +367,7 @@ config_print_zone(nsd_options_type* opt, const char* k, int s, const char *o,
SERV_GET_BIN(reuseport, o);
SERV_GET_BIN(hide_version, o);
SERV_GET_BIN(hide_identity, o);
+ SERV_GET_BIN(drop_updates, o);
SERV_GET_BIN(zonefiles_check, o);
SERV_GET_BIN(log_time_ascii, o);
SERV_GET_BIN(round_robin, o);
@@ -506,6 +507,7 @@ config_test_print_server(nsd_options_type* opt)
printf("\treceive-buffer-size: %d\n", opt->receive_buffer_size);
printf("\thide-version: %s\n", opt->hide_version?"yes":"no");
printf("\thide-identity: %s\n", opt->hide_identity?"yes":"no");
+ printf("\tdrop-updates: %s\n", opt->drop_updates?"yes":"no");
printf("\ttcp-reject-overflow: %s\n",
opt->tcp_reject_overflow ? "yes" : "no");
print_string_var("database:", opt->database);
@@ -514,6 +516,26 @@ config_test_print_server(nsd_options_type* opt)
print_string_var("nsid:", opt->nsid);
print_string_var("logfile:", opt->logfile);
printf("\tserver-count: %d\n", opt->server_count);
+ if(opt->cpu_affinity) {
+ cpu_option_type *n;
+ printf("\tcpu-affinity:");
+ for(n = opt->cpu_affinity; n; n = n->next) {
+ printf(" %d", n->cpu);
+ }
+ printf("\n");
+ }
+ if(opt->cpu_affinity && opt->service_cpu_affinity) {
+ cpu_map_option_type *n;
+ for(n = opt->service_cpu_affinity; n; n = n->next) {
+ if(n->service > 0) {
+ printf("\tserver-%d-cpu-affinity: %d\n",
+ n->service, n->cpu);
+ } else if(n->service == -1) {
+ printf("\txfrd-cpu-affinity: %d\n",
+ n->cpu);
+ }
+ }
+ }
printf("\ttcp-count: %d\n", opt->tcp_count);
printf("\ttcp-query-count: %d\n", opt->tcp_query_count);
printf("\ttcp-timeout: %d\n", opt->tcp_timeout);
@@ -540,7 +562,24 @@ config_test_print_server(nsd_options_type* opt)
printf("\tverbosity: %d\n", opt->verbosity);
for(ip = opt->ip_addresses; ip; ip=ip->next)
{
- print_string_var("ip-address:", ip->address);
+ printf("\tip-address: %s", ip->address);
+ if(ip->servers) {
+ const char *sep;
+ struct range_option *n;
+ printf(" servers=\"");
+ for(n=ip->servers, sep=""; n; n = n->next, sep=" ") {
+ if(n->first == n->last) {
+ printf("%s%d", sep, n->first);
+ } else {
+ printf("%s%d-%d", sep, n->first, n->last);
+ }
+ }
+ printf("\"");
+ }
+ if(ip->fib != -1) {
+ printf(" setfib=%d", ip->fib);
+ }
+ printf("\n");
}
#ifdef RATELIMIT
printf("\trrl-size: %d\n", (int)opt->rrl_size);
diff --git a/usr.sbin/nsd/nsd-checkzone.8.in b/usr.sbin/nsd/nsd-checkzone.8.in
index 227da662c07..7a57213f686 100644
--- a/usr.sbin/nsd/nsd-checkzone.8.in
+++ b/usr.sbin/nsd/nsd-checkzone.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-checkzone" "8" "Dec 10, 2019" "NLnet Labs" "nsd 4.2.4"
+.TH "nsd\-checkzone" "8" "Apr 16, 2020" "NLnet Labs" "nsd 4.3.1"
.\" Copyright (c) 2014, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
diff --git a/usr.sbin/nsd/nsd-control-setup.sh.in b/usr.sbin/nsd/nsd-control-setup.sh.in
index 705caefbe84..e0c52b70042 100644
--- a/usr.sbin/nsd/nsd-control-setup.sh.in
+++ b/usr.sbin/nsd/nsd-control-setup.sh.in
@@ -5,22 +5,22 @@
# Copyright (c) 2011, NLnet Labs. All rights reserved.
#
# This software is open source.
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
-#
+#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
-#
+#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
-#
+#
# Neither the name of the NLNET LABS nor the names of its contributors may
# be used to endorse or promote products derived from this software without
# specific prior written permission.
-#
+#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -57,56 +57,71 @@ SVR_BASE=nsd_server
# base name for nsd-control keys
CTL_BASE=nsd_control
+# flag to recreate generated certificates
+RECREATE=0
+
# we want -rw-r--- access (say you run this as root: grp=yes (server), all=no).
umask 0026
# end of options
-# functions:
-error ( ) {
- echo "$0 fatal error: $1"
- exit 1
+set -eu
+
+cleanup() {
+ echo "removing artifacts"
+
+ rm -rf \
+ server.cnf \
+ client.cnf \
+ "${SVR_BASE}_trust.pem" \
+ "${CTL_BASE}_trust.pem" \
+ "${SVR_BASE}_trust.srl"
}
-# check arguments:
-while test $# -ne 0; do
- case $1 in
- -d)
- if test $# -eq 1; then error "need argument for -d"; fi
- DESTDIR="$2"
- shift
- ;;
- *)
- echo "nsd-control-setup.sh - setup SSL keys for nsd-control"
- echo " -d dir use directory to store keys and certificates."
- echo " default: $DESTDIR"
- exit 1
- ;;
- esac
- shift
+fatal() {
+ printf "fatal error: $*\n" >/dev/stderr
+ exit 1
+}
+
+usage() {
+ cat <<EOF
+usage: $0 OPTIONS
+
+OPTIONS
+
+-d <dir> used directory to store keys and certificates (default: $DESTDIR)
+-h show help notice
+-r recreate certificates
+EOF
+}
+
+OPTIND=1
+while getopts 'd:hr' arg; do
+ case "$arg" in
+ d) DESTDIR="$OPTARG" ;;
+ h) usage; exit 0 ;;
+ r) RECREATE=1 ;;
+ ?) fatal "'$arg' unknown option" ;;
+ esac
done
+shift $((OPTIND - 1))
+
-# go!:
echo "setup in directory $DESTDIR"
-cd "$DESTDIR" || error "could not cd to $DESTDIR"
-
-# create certificate keys; do not recreate if they already exist.
-if test -f $SVR_BASE.key; then
- echo "$SVR_BASE.key exists"
-else
- echo "generating $SVR_BASE.key"
- openssl genrsa -out $SVR_BASE.key $BITS || error "could not genrsa"
-fi
-if test -f $CTL_BASE.key; then
- echo "$CTL_BASE.key exists"
-else
- echo "generating $CTL_BASE.key"
- openssl genrsa -out $CTL_BASE.key $BITS || error "could not genrsa"
+cd "$DESTDIR"
+
+trap cleanup SIGINT
+
+# ===
+# Generate server certificate
+# ===
+
+# generate private key; do no recreate it if they already exist.
+if [ ! -f "$SVR_BASE.key" ]; then
+ openssl genrsa -out "$SVR_BASE.key" "$BITS"
fi
-# create self-signed cert for server
-cat >request.cfg <<EOF
-[req]
+cat >server.cnf <<EOF
default_bits=$BITS
default_md=$HASH
prompt=no
@@ -115,15 +130,30 @@ distinguished_name=req_distinguished_name
[req_distinguished_name]
commonName=$SERVERNAME
EOF
-test -f request.cfg || error "could not create request.cfg"
-echo "create $SVR_BASE.pem (self signed certificate)"
-openssl req -key $SVR_BASE.key -config request.cfg -new -x509 -days $DAYS -out $SVR_BASE.pem || error "could not create $SVR_BASE.pem"
-# create trusted usage pem
-openssl x509 -in $SVR_BASE.pem -addtrust serverAuth -out $SVR_BASE"_trust.pem"
+[ -f server.cnf ] || fatal "cannot create openssl configuration"
+
+if [ ! -f "$SVR_BASE.pem" -o $RECREATE -eq 1 ]; then
+ openssl req \
+ -new -x509 \
+ -key "$SVR_BASE.key" \
+ -config server.cnf \
+ -days "$DAYS" \
+ -out "$SVR_BASE.pem"
+
+ [ ! -f "SVR_BASE.pem" ] || fatal "cannot create server certificate"
+fi
+
+# ===
+# Generate client certificate
+# ===
-# create client request and sign it, piped
-cat >request.cfg <<EOF
+# generate private key; do no recreate it if they already exist.
+if [ ! -f "$CTL_BASE.key" ]; then
+ openssl genrsa -out "$CTL_BASE.key" "$BITS"
+fi
+
+cat >client.cnf <<EOF
[req]
default_bits=$BITS
default_md=$HASH
@@ -133,11 +163,43 @@ distinguished_name=req_distinguished_name
[req_distinguished_name]
commonName=$CLIENTNAME
EOF
-test -f request.cfg || error "could not create request.cfg"
-echo "create $CTL_BASE.pem (signed client certificate)"
-openssl req -key $CTL_BASE.key -config request.cfg -new | openssl x509 -req -days $DAYS -CA $SVR_BASE"_trust.pem" -CAkey $SVR_BASE.key -CAcreateserial -$HASH -out $CTL_BASE.pem
-test -f $CTL_BASE.pem || error "could not create $CTL_BASE.pem"
+[ -f client.cnf ] || fatal "cannot create openssl configuration"
+
+if [ ! -f "$CTL_BASE.pem" -o $RECREATE -eq 1 ]; then
+ openssl x509 \
+ -addtrust serverAuth \
+ -in "$SVR_BASE.pem" \
+ -out "${SVR_BASE}_trust.pem"
+
+ openssl req \
+ -new \
+ -config client.cnf \
+ -key "$CTL_BASE.key" \
+ | openssl x509 \
+ -req \
+ -days "$DAYS" \
+ -CA "${SVR_BASE}_trust.pem" \
+ -CAkey "$SVR_BASE.key" \
+ -CAcreateserial \
+ -$HASH \
+ -out "$CTL_BASE.pem"
+
+ [ ! -f "CTL_BASE.pem" ] || fatal "cannot create signed client certificate"
+fi
+
+# remove unused permissions
+chmod o-rw \
+ "$SVR_BASE.pem" \
+ "$SVR_BASE.key" \
+ "$CTL_BASE.pem" \
+ "$CTL_BASE.key"
+
+cleanup
+
+echo "Setup success. Certificates created. Enable in nsd.conf file to use"
+
+
# create trusted usage pem
# openssl x509 -in $CTL_BASE.pem -addtrust clientAuth -out $CTL_BASE"_trust.pem"
@@ -147,14 +209,3 @@ test -f $CTL_BASE.pem || error "could not create $CTL_BASE.pem"
# echo "preferences - advanced - encryption - view certificates - your certs"
# echo "empty password is used, simply click OK on the password dialog box."
# openssl pkcs12 -export -in $CTL_BASE"_trust.pem" -inkey $CTL_BASE.key -name "nsd remote control client cert" -out $CTL_BASE"_browser.pfx" -password "pass:" || error "could not create browser certificate"
-
-# remove unused permissions
-chmod o-rw $SVR_BASE.pem $SVR_BASE.key $CTL_BASE.pem $CTL_BASE.key
-
-# remove crap
-rm -f request.cfg
-rm -f $CTL_BASE"_trust.pem" $SVR_BASE"_trust.pem" $SVR_BASE"_trust.srl"
-
-echo "Setup success. Certificates created. Enable in nsd.conf file to use"
-
-exit 0
diff --git a/usr.sbin/nsd/nsd-control.8.in b/usr.sbin/nsd/nsd-control.8.in
index 20e27a4fb09..cdb2104ee93 100644
--- a/usr.sbin/nsd/nsd-control.8.in
+++ b/usr.sbin/nsd/nsd-control.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-control" "8" "Dec 10, 2019" "NLnet Labs" "nsd 4.2.4"
+.TH "nsd\-control" "8" "Apr 16, 2020" "NLnet Labs" "nsd 4.3.1"
.\" Copyright (c) 2011, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
diff --git a/usr.sbin/nsd/nsd-control.c b/usr.sbin/nsd/nsd-control.c
index 649320eefa1..2152daa4dba 100644
--- a/usr.sbin/nsd/nsd-control.c
+++ b/usr.sbin/nsd/nsd-control.c
@@ -157,9 +157,11 @@ setup_ctx(struct nsd_options* cfg)
ctx = SSL_CTX_new(SSLv23_client_method());
if(!ctx)
ssl_err("could not allocate SSL_CTX pointer");
+#if SSL_OP_NO_SSLv2 != 0
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
!= SSL_OP_NO_SSLv2)
ssl_err("could not set SSL_OP_NO_SSLv2");
+#endif
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
!= SSL_OP_NO_SSLv3)
ssl_err("could not set SSL_OP_NO_SSLv3");
diff --git a/usr.sbin/nsd/nsd.8.in b/usr.sbin/nsd/nsd.8.in
index cdba544f297..06a96b15e29 100644
--- a/usr.sbin/nsd/nsd.8.in
+++ b/usr.sbin/nsd/nsd.8.in
@@ -1,9 +1,9 @@
-.TH "NSD" "8" "Dec 10, 2019" "NLnet Labs" "NSD 4.2.4"
+.TH "NSD" "8" "Apr 16, 2020" "NLnet Labs" "NSD 4.3.1"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
.B nsd
-\- Name Server Daemon (NSD) version 4.2.4.
+\- Name Server Daemon (NSD) version 4.3.1.
.SH "SYNOPSIS"
.B nsd
.RB [ \-4 ]
diff --git a/usr.sbin/nsd/nsd.c b/usr.sbin/nsd/nsd.c
index e65c8f9dc54..46f5fb18c48 100644
--- a/usr.sbin/nsd/nsd.c
+++ b/usr.sbin/nsd/nsd.c
@@ -41,6 +41,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <ifaddrs.h>
#include "nsd.h"
#include "options.h"
@@ -130,7 +131,9 @@ copyaddrinfo(struct nsd_addrinfo *dest, struct addrinfo *src)
}
static void
-setup_socket(struct nsd_socket *sock, const char *node, const char *port, struct addrinfo *hints)
+setup_socket(
+ struct nsd_socket *sock, const char *node, const char *port,
+ struct addrinfo *hints)
{
int ret;
char *sep = NULL;
@@ -139,6 +142,7 @@ setup_socket(struct nsd_socket *sock, const char *node, const char *port, struct
char service_buf[6 + 1 /* '\0' */]; /* 65535 */
struct addrinfo *addr = NULL;
+ sock->fib = -1;
if(node) {
host = host_buf;
sep = strchr(node, '@');
@@ -171,6 +175,59 @@ setup_socket(struct nsd_socket *sock, const char *node, const char *port, struct
}
static void
+figure_socket_servers(
+ struct nsd_socket *sock, struct ip_address_option *ip)
+{
+ int i;
+ struct range_option *server;
+
+ sock->servers = xalloc_zero(nsd_bitset_size(nsd.child_count));
+ region_add_cleanup(nsd.region, free, sock->servers);
+ nsd_bitset_init(sock->servers, nsd.child_count);
+
+ if(!ip || !ip->servers) {
+ /* every server must listen on this socket */
+ for(i = 0; i < (int)nsd.child_count; i++) {
+ nsd_bitset_set(sock->servers, i);
+ }
+ return;
+ }
+
+ /* only specific servers must listen on this socket */
+ for(server = ip->servers; server; server = server->next) {
+ if(server->first == server->last) {
+ if(server->first <= 0) {
+ error("server %d specified for ip-address %s "
+ "is invalid; server ranges are 1-based",
+ server->first, ip->address);
+ } else if(server->last > (int)nsd.child_count) {
+ error("server %d specified for ip-address %s "
+ "exceeds number of servers configured "
+ "in server-count",
+ server->first, ip->address);
+ }
+ } else {
+ /* parse_range must ensure range itself is valid */
+ assert(server->first < server->last);
+ if(server->first <= 0) {
+ error("server range %d-%d specified for "
+ "ip-address %s is invalid; server "
+ "ranges are 1-based",
+ server->first, server->last, ip->address);
+ } else if(server->last > (int)nsd.child_count) {
+ error("server range %d-%d specified for "
+ "ip-address %s exceeds number of servers "
+ "configured in server-count",
+ server->first, server->last, ip->address);
+ }
+ }
+ for(i = server->first - 1; i < server->last; i++) {
+ nsd_bitset_set(sock->servers, i);
+ }
+ }
+}
+
+static void
figure_default_sockets(
struct nsd_socket **udp, struct nsd_socket **tcp, size_t *ifs,
const char *udp_port, const char *tcp_port,
@@ -223,9 +280,13 @@ figure_default_sockets(
(r = getaddrinfo(NULL, tcp_port, &ai[1], &addrs[1])) == 0)
{
(*udp)[i].flags |= NSD_SOCKET_IS_OPTIONAL;
+ (*udp)[i].fib = -1;
copyaddrinfo(&(*udp)[i].addr, addrs[0]);
+ figure_socket_servers(&(*udp)[i], NULL);
(*tcp)[i].flags |= NSD_SOCKET_IS_OPTIONAL;
+ (*tcp)[i].fib = -1;
copyaddrinfo(&(*tcp)[i].addr, addrs[1]);
+ figure_socket_servers(&(*tcp)[i], NULL);
i++;
} else {
log_msg(LOG_WARNING, "No IPv6, fallback to IPv4. getaddrinfo: %s",
@@ -245,7 +306,63 @@ figure_default_sockets(
*ifs = i + 1;
setup_socket(&(*udp)[i], NULL, udp_port, &ai[0]);
+ figure_socket_servers(&(*udp)[i], NULL);
setup_socket(&(*tcp)[i], NULL, tcp_port, &ai[1]);
+ figure_socket_servers(&(*tcp)[i], NULL);
+}
+
+static int
+find_device(
+ struct nsd_socket *sock,
+ const struct ifaddrs *ifa)
+{
+ for(; ifa != NULL; ifa = ifa->ifa_next) {
+ if((ifa->ifa_addr == NULL) ||
+ (ifa->ifa_addr->sa_family != sock->addr.ai_family) ||
+ ((ifa->ifa_flags & IFF_UP) == 0 ||
+ (ifa->ifa_flags & IFF_LOOPBACK) != 0 ||
+ (ifa->ifa_flags & IFF_RUNNING) == 0))
+ {
+ continue;
+ }
+
+#ifdef INET6
+ if(ifa->ifa_addr->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sa1, *sa2;
+ size_t sz = sizeof(struct in6_addr);
+ sa1 = (struct sockaddr_in6 *)ifa->ifa_addr;
+ sa2 = (struct sockaddr_in6 *)&sock->addr.ai_addr;
+ if(memcmp(&sa1->sin6_addr, &sa2->sin6_addr, sz) == 0) {
+ break;
+ }
+ } else
+#endif
+ if(ifa->ifa_addr->sa_family == AF_INET) {
+ struct sockaddr_in *sa1, *sa2;
+ sa1 = (struct sockaddr_in *)ifa->ifa_addr;
+ sa2 = (struct sockaddr_in *)&sock->addr.ai_addr;
+ if(sa1->sin_addr.s_addr == sa2->sin_addr.s_addr) {
+ break;
+ }
+ }
+ }
+
+ if(ifa != NULL) {
+ char *colon;
+ size_t len;
+
+ if((colon = strchr(ifa->ifa_name, ':')) != NULL) {
+ len = (size_t)((uintptr_t)colon - (uintptr_t)ifa->ifa_name);
+ } else {
+ len = strlen(ifa->ifa_name);
+ }
+ if (len < sizeof(sock->device)) {
+ strlcpy(sock->device, ifa->ifa_name, len);
+ return 1;
+ }
+ }
+
+ return 0;
}
static void
@@ -258,15 +375,23 @@ figure_sockets(
size_t i = 0;
struct addrinfo ai = *hints;
struct ip_address_option *ip;
+ struct ifaddrs *ifa = NULL;
+ int bind_device = 0;
if(!ips) {
- figure_default_sockets(udp, tcp, ifs, udp_port, tcp_port, hints);
+ figure_default_sockets(
+ udp, tcp, ifs, udp_port, tcp_port, hints);
return;
}
*ifs = 0;
for(ip = ips; ip; ip = ip->next) {
(*ifs)++;
+ bind_device |= (ip->dev != 0);
+ }
+
+ if(bind_device && getifaddrs(&ifa) == -1) {
+ error("getifaddrs failed: %s", strerror(errno));
}
*udp = xalloc_zero((*ifs + 1) * sizeof(struct nsd_socket));
@@ -278,12 +403,152 @@ figure_sockets(
for(ip = ips, i = 0; ip; ip = ip->next, i++) {
ai.ai_socktype = SOCK_DGRAM;
setup_socket(&(*udp)[i], ip->address, udp_port, &ai);
+ figure_socket_servers(&(*udp)[i], ip);
ai.ai_socktype = SOCK_STREAM;
setup_socket(&(*tcp)[i], ip->address, tcp_port, &ai);
+ figure_socket_servers(&(*tcp)[i], ip);
+ if(ip->fib != -1) {
+ (*udp)[i].fib = ip->fib;
+ (*tcp)[i].fib = ip->fib;
+ }
+ if(ip->dev != 0) {
+ (*udp)[i].flags |= NSD_BIND_DEVICE;
+ (*tcp)[i].flags |= NSD_BIND_DEVICE;
+ if(ifa != NULL && (find_device(&(*udp)[i], ifa) == 0 ||
+ find_device(&(*tcp)[i], ifa) == 0))
+ {
+ error("cannot find device for ip-address %s",
+ ip->address);
+ }
+ }
}
assert(i == *ifs);
+
+ if(ifa != NULL) {
+ freeifaddrs(ifa);
+ }
+}
+
+/* print server affinity for given socket. "*" if socket has no affinity with
+ any specific server, "x-y" if socket has affinity with more than two
+ consecutively numbered servers, "x" if socket has affinity with a specific
+ server number, which is not necessarily just one server. e.g. "1 3" is
+ printed if socket has affinity with servers number one and three, but not
+ server number two. */
+static ssize_t
+print_socket_servers(struct nsd_socket *sock, char *buf, size_t bufsz)
+{
+ int i, x, y, z, n = (int)(sock->servers->size);
+ char *sep = "";
+ size_t off, tot;
+ ssize_t cnt = 0;
+
+ assert(bufsz != 0);
+
+ off = tot = 0;
+ x = y = z = -1;
+ for (i = 0; i <= n; i++) {
+ if (i == n || !nsd_bitset_isset(sock->servers, i)) {
+ cnt = 0;
+ if (i == n && x == -1) {
+ assert(y == -1);
+ assert(z == -1);
+ cnt = snprintf(buf, bufsz, "-");
+ } else if (y > z) {
+ assert(x > z);
+ if (x == 0 && y == (n - 1)) {
+ assert(z == -1);
+ cnt = snprintf(buf+off, bufsz-off,
+ "*");
+ } else if (x == y) {
+ cnt = snprintf(buf+off, bufsz-off,
+ "%s%d", sep, x+1);
+ } else if (x == (y - 1)) {
+ cnt = snprintf(buf+off, bufsz-off,
+ "%s%d %d", sep, x+1, y+1);
+ } else {
+ assert(y > (x + 1));
+ cnt = snprintf(buf+off, bufsz-off,
+ "%s%d-%d", sep, x+1, y+1);
+ }
+ }
+ z = i;
+ if (cnt > 0) {
+ tot += (size_t)cnt;
+ off = (tot < bufsz) ? tot : bufsz - 1;
+ sep = " ";
+ } else if (cnt < 0) {
+ return -1;
+ }
+ } else if (x <= z) {
+ x = y = i;
+ } else {
+ assert(x > z);
+ y = i;
+ }
+ }
+
+ return tot;
+}
+
+static void
+print_sockets(
+ struct nsd_socket *udp, struct nsd_socket *tcp, size_t ifs)
+{
+ char sockbuf[INET6_ADDRSTRLEN + 6 + 1];
+ char *serverbuf;
+ size_t i, serverbufsz, servercnt;
+ const char *fmt = "listen on ip-address %s (%s) with server(s): %s";
+ struct nsd_bitset *servers;
+
+ if(ifs == 0) {
+ return;
+ }
+
+ assert(udp != NULL);
+ assert(tcp != NULL);
+
+ servercnt = udp[0].servers->size;
+ serverbufsz = (((servercnt / 10) * servercnt) + servercnt) + 1;
+ serverbuf = xalloc(serverbufsz);
+
+ /* warn user of unused servers */
+ servers = xalloc(nsd_bitset_size(servercnt));
+ nsd_bitset_init(servers, (size_t)servercnt);
+
+ for(i = 0; i < ifs; i++) {
+ assert(udp[i].servers->size == servercnt);
+ addrport2str(&udp[i].addr.ai_addr, sockbuf, sizeof(sockbuf));
+ print_socket_servers(&udp[i], serverbuf, serverbufsz);
+ nsd_bitset_or(servers, servers, udp[i].servers);
+ log_msg(LOG_NOTICE, fmt, sockbuf, "udp", serverbuf);
+ assert(tcp[i].servers->size == servercnt);
+ addrport2str(&tcp[i].addr.ai_addr, sockbuf, sizeof(sockbuf));
+ print_socket_servers(&tcp[i], serverbuf, serverbufsz);
+ nsd_bitset_or(servers, servers, tcp[i].servers);
+ log_msg(LOG_NOTICE, fmt, sockbuf, "tcp", serverbuf);
+ }
+
+
+ /* warn user of unused servers */
+ for(i = 0; i < servercnt; i++) {
+ if(!nsd_bitset_isset(servers, i)) {
+ log_msg(LOG_WARNING, "server %zu will not listen on "
+ "any specified ip-address", i+1);
+ }
+ }
+ free(serverbuf);
+ free(servers);
+}
+
+#ifdef HAVE_CPUSET_T
+static void free_cpuset(void *ptr)
+{
+ cpuset_t *set = (cpuset_t *)ptr;
+ cpuset_destroy(set);
}
+#endif
/*
* Fetch the nsd parent process id from the nsd pidfile
@@ -764,6 +1029,7 @@ main(int argc, char *argv[])
if(nsd.child_count == 0) {
nsd.child_count = nsd.options->server_count;
}
+
#ifdef SO_REUSEPORT
if(nsd.options->reuseport && nsd.child_count > 1) {
nsd.reuseport = nsd.child_count;
@@ -845,6 +1111,54 @@ main(int argc, char *argv[])
edns_init_nsid(&nsd.edns_ipv6, nsd.nsid_len);
#endif /* defined(INET6) */
+#ifdef HAVE_CPUSET_T
+ nsd.use_cpu_affinity = (nsd.options->cpu_affinity != NULL);
+ if(nsd.use_cpu_affinity) {
+ int ncpus;
+ struct cpu_option* opt = nsd.options->cpu_affinity;
+
+ if((ncpus = number_of_cpus()) == -1) {
+ error("cannot retrieve number of cpus: %s",
+ strerror(errno));
+ }
+ nsd.cpuset = cpuset_create();
+ region_add_cleanup(nsd.region, free_cpuset, nsd.cpuset);
+ for(; opt; opt = opt->next) {
+ assert(opt->cpu >= 0);
+ if(opt->cpu >= ncpus) {
+ error("invalid cpu %d specified in "
+ "cpu-affinity", opt->cpu);
+ }
+ cpuset_set((cpuid_t)opt->cpu, nsd.cpuset);
+ }
+ }
+ if(nsd.use_cpu_affinity) {
+ int cpu;
+ struct cpu_map_option *opt
+ = nsd.options->service_cpu_affinity;
+
+ cpu = -1;
+ for(; opt && cpu == -1; opt = opt->next) {
+ if(opt->service == -1) {
+ cpu = opt->cpu;
+ assert(cpu >= 0);
+ }
+ }
+ nsd.xfrd_cpuset = cpuset_create();
+ region_add_cleanup(nsd.region, free_cpuset, nsd.xfrd_cpuset);
+ if(cpu == -1) {
+ cpuset_or(nsd.xfrd_cpuset,
+ nsd.cpuset);
+ } else {
+ if(!cpuset_isset(cpu, nsd.cpuset)) {
+ error("cpu %d specified in xfrd-cpu-affinity "
+ "is not specified in cpu-affinity", cpu);
+ }
+ cpuset_set((cpuid_t)cpu, nsd.xfrd_cpuset);
+ }
+ }
+#endif /* HAVE_CPUSET_T */
+
/* Number of child servers to fork. */
nsd.children = (struct nsd_child *) region_alloc_array(
nsd.region, nsd.child_count, sizeof(struct nsd_child));
@@ -858,9 +1172,43 @@ main(int argc, char *argv[])
nsd.children[i].need_to_send_QUIT = 0;
nsd.children[i].need_to_exit = 0;
nsd.children[i].has_exited = 0;
-#ifdef BIND8_STATS
+#ifdef BIND8_STATS
nsd.children[i].query_count = 0;
#endif
+
+#ifdef HAVE_CPUSET_T
+ if(nsd.use_cpu_affinity) {
+ int cpu, server;
+ struct cpu_map_option *opt
+ = nsd.options->service_cpu_affinity;
+
+ cpu = -1;
+ server = i+1;
+ for(; opt && cpu == -1; opt = opt->next) {
+ if(opt->service == server) {
+ cpu = opt->cpu;
+ assert(cpu >= 0);
+ }
+ }
+ nsd.children[i].cpuset = cpuset_create();
+ region_add_cleanup(nsd.region,
+ free_cpuset,
+ nsd.children[i].cpuset);
+ if(cpu == -1) {
+ cpuset_or(nsd.children[i].cpuset,
+ nsd.cpuset);
+ } else {
+ if(!cpuset_isset((cpuid_t)cpu, nsd.cpuset)) {
+ error("cpu %d specified in "
+ "server-%d-cpu-affinity is not "
+ "specified in cpu-affinity",
+ cpu, server);
+ }
+ cpuset_set(
+ (cpuid_t)cpu, nsd.children[i].cpuset);
+ }
+ }
+#endif /* HAVE_CPUSET_T */
}
nsd.this_child = NULL;
@@ -968,6 +1316,17 @@ main(int argc, char *argv[])
}
}
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("main");
+#endif
+#ifdef HAVE_CPUSET_T
+ if(nsd.use_cpu_affinity) {
+ set_cpu_affinity(nsd.cpuset);
+ }
+#endif
+
+ print_sockets(nsd.udp, nsd.tcp, nsd.ifs);
+
/* Setup the signal handling... */
action.sa_handler = sig_handler;
sigfillset(&action.sa_mask);
diff --git a/usr.sbin/nsd/nsd.conf.5.in b/usr.sbin/nsd/nsd.conf.5.in
index addcddeb8cc..dadafa12c11 100644
--- a/usr.sbin/nsd/nsd.conf.5.in
+++ b/usr.sbin/nsd/nsd.conf.5.in
@@ -1,4 +1,4 @@
-.TH "nsd.conf" "5" "Dec 10, 2019" "NLnet Labs" "nsd 4.2.4"
+.TH "nsd.conf" "5" "Apr 16, 2020" "NLnet Labs" "nsd 4.3.1"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
@@ -138,11 +138,16 @@ clause. There may only be one
.B server:
clause.
.TP
-.B ip\-address:\fR <ip4 or ip6>[@port]
+.B ip\-address:\fR <ip4 or ip6>[@port] [servers]
NSD will bind to the listed ip\-address. Can be given multiple times
to bind multiple ip\-addresses. Optionally, a port number can be given.
-If none are given NSD listens to the wildcard interface. Same as commandline option
+If none are given NSD listens to the wildcard interface. Same as commandline option
.BR \-a.
+To limit which NSD server(s) listen on the given interface, specify one or
+more servers separated by whitespace after <ip>[@port]. Ranges can be used as
+a shorthand to specify multiple consecutive servers. By default every server
+will listen.
+.BR
For servers with multiple IP addresses that can be used to send traffic
to the internet, list them one by one, or the source address of replies
could be wrong. This is because if the udp socket associates a source
@@ -151,7 +156,7 @@ send to the internet, and it picks the wrong one. Typically needed for
anycast instances. Use ip-transparent to be able to list addresses that
turn on later (typical for certain load-balancing).
.TP
-.B interface:\fR <ip4 or ip6>[@port]
+.B interface:\fR <ip4 or ip6>[@port] [servers] [setfib]
Same as ip\-address (for easy of compatibility with unbound.conf).
.TP
.B ip\-transparent:\fR <yes or no>
@@ -171,6 +176,11 @@ than 1 (such as, equal to the number of cpus). The default is no.
It works on Linux, but does not work on FreeBSD, and likely does not
work on other systems.
.TP
+.B bindtodevice:\fR <yes or no>
+Use the SO_BINDTODEVICE socket option to bind the socket to the device to
+ensure responses go out the same interface the corresponding query came in on
+and skip interface selection by the kernel.
+.TP
.B send\-buffer\-size:\fR <number>
Set the send buffer size for query-servicing sockets. Set to 0 to use the default settings.
.TP
@@ -236,6 +246,22 @@ Start this many NSD servers. Default is 1. Same as commandline
option
.BR \-N .
.TP
+.B cpu\-affinity:\fR <number> <number> ...
+Overall CPU affinity for NSD server(s). Default is no affinity.
+.BR \-n .
+.TP
+.B server\-N\-cpu\-affinity:\fR <number>
+Bind NSD server specified by N to a specific core. Default is to have affinity
+set to every core specified in cpu\-affinity. This setting only takes effect
+if cpu\-affinity is enabled.
+.BR \-n
+.TP
+.B xfrd\-cpu\-affinity:\fR <number>
+Bind xfrd to a specific core. Default is to have affinity set to every core
+specified in cpu\-affinity. This setting only takes effect if cpu\-affinity is
+enabled.
+.BR \-n
+.TP
.B tcp\-count:\fR <number>
The maximum number of concurrent, active TCP connections by each server.
Default is 100. Same as commandline option
@@ -366,6 +392,13 @@ queries. Default is no.
Prevent NSD from replying with the identity string on CHAOS class
queries. Default is no.
.TP
+.B drop\-updates:\fR <yes or no>
+If set to yes, drop received packets with the UPDATE opcode.
+.TP
+.B use\-systemd:\fR <yes or no>
+This option is deprecated and ignored. If compiled with libsystemd,
+NSD signals readiness to systemd and use of the option is not necessary.
+.TP
.B log\-time\-ascii:\fR <yes or no>
Log time in ascii, if "no" then in seconds epoch. Default is yes.
This chooses the format when logging to file. The printout via syslog
diff --git a/usr.sbin/nsd/nsd.conf.sample.in b/usr.sbin/nsd/nsd.conf.sample.in
index e6886fd8f1e..3ea1782e6ee 100644
--- a/usr.sbin/nsd/nsd.conf.sample.in
+++ b/usr.sbin/nsd/nsd.conf.sample.in
@@ -15,22 +15,61 @@ server:
# Number of NSD servers to fork. Put the number of CPUs to use here.
# server-count: 1
- # uncomment to specify specific interfaces to bind (default are the
- # wildcard interfaces 0.0.0.0 and ::0).
+ # Set overall CPU affinity for NSD processes on Linux and FreeBSD.
+ # Any server/xfrd CPU affinity value will be masked by this value.
+ # cpu-affinity: 0 1 2 3
+
+ # Bind NSD server(s), configured by server-count (1-based), to a
+ # dedicated core. Single core affinity improves L1/L2 cache hits and
+ # reduces pipeline stalls/flushes.
+ #
+ # server-1-cpu-affinity: 0
+ # server-2-cpu-affinity: 1
+ # ...
+ # server-<N>-cpu-affinity: 2
+
+ # Bind xfrd to a dedicated core.
+ # xfrd-cpu-affinity: 3
+
+ # Specify specific interfaces to bind (default are the wildcard
+ # interfaces 0.0.0.0 and ::0).
# For servers with multiple IP addresses, list them one by one,
# or the source address of replies could be wrong.
# Use ip-transparent to be able to list addresses that turn on later.
# ip-address: 1.2.3.4
# ip-address: 1.2.3.4@5678
# ip-address: 12fe::8ef0
+ #
+ # IP addresses can be configured per-server to avoid waking up more
+ # than one server when a packet comes in (thundering herd problem) or
+ # to partition sockets across servers to improve select/poll
+ # performance.
+ #
+ # ip-address: 1.2.3.4 servers="1-2 3"
+ # ip-address: 1.2.3.4@5678 servers="4-5 6"
+ #
+ # When several interfaces are configured to listen on the same subnet,
+ # care must be taken to ensure responses go out the same interface the
+ # corresponding query came in on to avoid problems with load balancers
+ # and VLAN tagged interfaces. Linux offers the SO_BINDTODEVICE socket
+ # option to bind a socket to a specified device. For FreeBSD, to
+ # achieve the same result, specify the routing table to use after the
+ # IP address to use SO_SETFIB.
+ #
+ # Complement with socket partitioning and CPU affinity for attack
+ # mitigation benefits. i.e. only a single core is maxed out if a
+ # specific IP address is under attack.
+ #
+ # ip-address: 1.2.3.4 setfib=0 bindtodevice=yes
+ # ip-address: 1.2.3.5@6789 setfib=1 bindtodevice=yes
# Allow binding to non local addresses. Default no.
# ip-transparent: no
- # Allow binding to addresses that are down. Default no.
+ # Allow binding to addresses that are down. Default no.
# ip-freebind: no
- # use the reuseport socket option for performance. Default no.
+ # Use SO_REUSEPORT socket option for performance. Default no.
# reuseport: no
# override maximum socket send buffer size. Default of 0 results in
@@ -83,7 +122,7 @@ server:
# pidfile: "@pidfile@"
# The file where secondary zone refresh and expire timeouts are kept.
- # If you delete this file, all secondary zones are forced to be
+ # If you delete this file, all secondary zones are forced to be
# 'refreshing' (as if nsd got a notify). Set to "" to disable.
# xfrdfile: "@xfrdfile@"
@@ -96,6 +135,9 @@ server:
# don't answer HOSTNAME.BIND and ID.SERVER CHAOS class queries
# hide-identity: no
+ # Drop UPDATE queries
+ # drop-updates: no
+
# version string the server responds with for chaos queries.
# default is 'NSD x.y.z' with the server's version number.
# version: "NSD"
@@ -141,7 +183,7 @@ server:
# Number of seconds between reloads triggered by xfrd.
# xfrd-reload-timeout: 1
-
+
# log timestamp in ascii (y-m-d h:m:s.msec), yes is default.
# log-time-ascii: yes
@@ -161,7 +203,7 @@ server:
# check mtime of all zone files on start and sighup
# zonefiles-check: yes
-
+
# write changed zonefiles to disk, every N seconds.
# default is 0(disabled) or 3600(if database is "").
# zonefiles-write: 3600
@@ -186,11 +228,11 @@ server:
# rrl-slip: 2
# Response Rate Limiting, IPv4 prefix length. Addresses are
- # grouped by netblock.
+ # grouped by netblock.
# rrl-ipv4-prefix-length: 24
# Response Rate Limiting, IPv6 prefix length. Addresses are
- # grouped by netblock.
+ # grouped by netblock.
# rrl-ipv6-prefix-length: 64
# Response Rate Limiting, maximum QPS allowed (from one query source)
@@ -262,7 +304,7 @@ remote-control:
# Patterns have zone configuration and they are shared by one or more zones.
-#
+#
# pattern:
# name by which the pattern is referred to
#name: "myzones"
@@ -274,7 +316,7 @@ remote-control:
# if label or character does not exist you get a dot '.'.
# for example "%s.zone" or "zones/%1/%2/%3/%s" or "secondary/%z/%s"
#zonefile: "%s.zone"
-
+
# If no master and slave access control elements are provided,
# this zone will not be served to/from other servers.
@@ -299,7 +341,7 @@ remote-control:
# If you want to make use of IXFR/UDP use: UDP addr tsigkey
# for a master that only speaks AXFR (like NSD) use AXFR addr tsigkey
#request-xfr: 192.0.2.2 the_tsig_key_name
- # Attention: You cannot use UDP and AXFR together. AXFR is always over
+ # Attention: You cannot use UDP and AXFR together. AXFR is always over
# TCP. If you use UDP, we higly recommend you to deploy TSIG.
# Allow AXFR fallback if the master does not support IXFR. Default
# is yes.
@@ -312,6 +354,7 @@ remote-control:
#min-refresh-time: 0
#max-retry-time: 1209600
#min-retry-time: 0
+
# Slave server tries zone transfer to all masters and picks highest
# zone version available, for when masters have different versions.
#multi-master-check: no
@@ -325,7 +368,7 @@ remote-control:
# zonestats: "%s"
# if you give another pattern name here, at this point the settings
- # from that pattern are inserted into this one (as if it were a
+ # from that pattern are inserted into this one (as if it were a
# macro). The statement can be given in between other statements,
# because the order of access control elements can make a difference
# (which master to request from first, which slave to notify first).
@@ -336,13 +379,13 @@ remote-control:
# Zones that are dynamically added and deleted are put in the zonelist file.
#
# zone:
- # name: "example.com"
- # you can give a pattern here, all the settings from that pattern
- # are then inserted at this point
- # include-pattern: "master"
- # You can also specify (additional) options directly for this zone.
- # zonefile: "example.com.zone"
- # request-xfr: 192.0.2.1 example.com.key
+ # name: "example.com"
+ # you can give a pattern here, all the settings from that pattern
+ # are then inserted at this point
+ # include-pattern: "master"
+ # You can also specify (additional) options directly for this zone.
+ # zonefile: "example.com.zone"
+ # request-xfr: 192.0.2.1 example.com.key
# RRLconfig
# Response Rate Limiting, whitelist types
diff --git a/usr.sbin/nsd/nsd.h b/usr.sbin/nsd/nsd.h
index 0cee8c87fc6..9f460494207 100644
--- a/usr.sbin/nsd/nsd.h
+++ b/usr.sbin/nsd/nsd.h
@@ -11,12 +11,21 @@
#define _NSD_H_
#include <signal.h>
+#include <net/if.h>
+#ifndef IFNAMSIZ
+# ifdef IF_NAMESIZE
+# define IFNAMSIZ IF_NAMESIZE
+# else
+# define IFNAMSIZ 16
+# endif
+#endif
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#endif
#include "dns.h"
#include "edns.h"
+#include "bitset.h"
struct netio_handler;
struct nsd_options;
struct udb_base;
@@ -111,6 +120,7 @@ typedef unsigned long stc_type;
#endif /* USE_ZONE_STATS */
#define NSD_SOCKET_IS_OPTIONAL (1<<0)
+#define NSD_BIND_DEVICE (1<<1)
struct nsd_addrinfo
{
@@ -123,14 +133,22 @@ struct nsd_addrinfo
struct nsd_socket
{
- struct nsd_addrinfo addr;
- int s;
- int flags;
+ struct nsd_addrinfo addr;
+ int s;
+ int flags;
+ struct nsd_bitset *servers;
+ char device[IFNAMSIZ];
+ int fib;
};
struct nsd_child
{
- /* The type of child process (UDP or TCP handler). */
+#ifdef HAVE_CPUSET_T
+ /* Processor(s) that child process must run on (if applicable). */
+ cpuset_t *cpuset;
+#endif
+
+ /* The type of child process (UDP or TCP handler). */
int kind;
/* The child's process id. */
@@ -223,6 +241,12 @@ struct nsd
unsigned char *nsid;
uint8_t file_rotation_ok;
+#ifdef HAVE_CPUSET_T
+ int use_cpu_affinity;
+ cpuset_t* cpuset;
+ cpuset_t* xfrd_cpuset;
+#endif
+
/* number of interfaces */
size_t ifs;
/* non0 if so_reuseport is in use, if so, tcp, udp array increased */
diff --git a/usr.sbin/nsd/nsec3.c b/usr.sbin/nsd/nsec3.c
index f323b693107..566b69ca225 100644
--- a/usr.sbin/nsd/nsec3.c
+++ b/usr.sbin/nsd/nsec3.c
@@ -119,6 +119,7 @@ nsec3_hash_and_store(zone_type* zone, const dname_type* dname, uint8_t* store)
detect_nsec3_params(zone->nsec3_param, &nsec3_salt,
&nsec3_saltlength, &nsec3_iterations);
+ assert(nsec3_iterations >= 0 && nsec3_iterations <= 65536);
iterated_hash((unsigned char*)store, nsec3_salt, nsec3_saltlength,
dname_name(dname), dname->name_size, nsec3_iterations);
}
diff --git a/usr.sbin/nsd/options.c b/usr.sbin/nsd/options.c
index 5064eca94f8..3fb67ffdd34 100644
--- a/usr.sbin/nsd/options.c
+++ b/usr.sbin/nsd/options.c
@@ -15,6 +15,7 @@
#include "tsig.h"
#include "difffile.h"
#include "rrl.h"
+#include "bitset.h"
#include "configyyrename.h"
#include "configparser.h"
@@ -57,6 +58,7 @@ nsd_options_create(region_type* region)
opt->verbosity = 0;
opt->hide_version = 0;
opt->hide_identity = 0;
+ opt->drop_updates = 0;
opt->do_ip4 = 1;
opt->do_ip6 = 1;
opt->database = DBFILE;
@@ -70,6 +72,8 @@ nsd_options_create(region_type* region)
opt->confine_to_zone = 0;
opt->refuse_any = 1;
opt->server_count = 1;
+ opt->cpu_affinity = NULL;
+ opt->service_cpu_affinity = NULL;
opt->tcp_count = 100;
opt->tcp_reject_overflow = 0;
opt->tcp_query_count = 0;
@@ -346,6 +350,7 @@ parse_zone_list_file(struct nsd_options* opt)
add foo.bar.nl slave
add rutabaga.uk config
*/
+ char hdr[64];
char buf[1024];
/* create empty data structures */
@@ -364,15 +369,16 @@ parse_zone_list_file(struct nsd_options* opt)
return 0;
}
/* read header */
- buf[strlen(ZONELIST_HEADER)] = 0;
- if(fread(buf, 1, strlen(ZONELIST_HEADER), opt->zonelist) !=
- strlen(ZONELIST_HEADER) || strncmp(buf, ZONELIST_HEADER,
+ hdr[strlen(ZONELIST_HEADER)] = 0;
+ if(fread(hdr, 1, strlen(ZONELIST_HEADER), opt->zonelist) !=
+ strlen(ZONELIST_HEADER) || strncmp(hdr, ZONELIST_HEADER,
strlen(ZONELIST_HEADER)) != 0) {
log_msg(LOG_ERR, "zone list %s contains bad header\n", opt->zonelistfile);
fclose(opt->zonelist);
opt->zonelist = NULL;
return 0;
}
+ buf[sizeof(buf)-1]=0;
/* read entries in file */
while(fgets(buf, sizeof(buf), opt->zonelist)) {
@@ -1414,7 +1420,7 @@ acl_addr_matches_ipv6host(struct acl_options* acl, struct sockaddr_storage* addr
return 0;
break;
case acl_range_minmax:
- if(!acl_addr_match_range((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr,
+ if(!acl_addr_match_range_v6((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr,
(uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr)))
return 0;
break;
@@ -1442,7 +1448,7 @@ acl_addr_matches_ipv4host(struct acl_options* acl, struct sockaddr_in* addr, uns
return 0;
break;
case acl_range_minmax:
- if(!acl_addr_match_range((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr,
+ if(!acl_addr_match_range_v4((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr,
(uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr)))
return 0;
break;
@@ -1522,7 +1528,23 @@ acl_addr_match_mask(uint32_t* a, uint32_t* b, uint32_t* mask, size_t sz)
}
int
-acl_addr_match_range(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz)
+acl_addr_match_range_v4(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz)
+{
+ assert(sz == 4); (void)sz;
+ /* check treats x as one huge number */
+
+ /* if outside bounds, we are done */
+ if(*minval > *x)
+ return 0;
+ if(*maxval < *x)
+ return 0;
+
+ return 1;
+}
+
+#ifdef INET6
+int
+acl_addr_match_range_v6(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz)
{
size_t i;
uint8_t checkmin = 1, checkmax = 1;
@@ -1550,6 +1572,7 @@ acl_addr_match_range(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz)
}
return 1;
}
+#endif /* INET6 */
int
acl_key_matches(struct acl_options* acl, struct query* q)
diff --git a/usr.sbin/nsd/options.h b/usr.sbin/nsd/options.h
index beb07741c3b..52605a02009 100644
--- a/usr.sbin/nsd/options.h
+++ b/usr.sbin/nsd/options.h
@@ -23,10 +23,14 @@ struct nsd;
typedef struct nsd_options nsd_options_type;
typedef struct pattern_options pattern_options_type;
typedef struct zone_options zone_options_type;
+typedef struct range_option range_option_type;
typedef struct ip_address_option ip_address_option_type;
+typedef struct cpu_option cpu_option_type;
+typedef struct cpu_map_option cpu_map_option_type;
typedef struct acl_options acl_options_type;
typedef struct key_options key_options_type;
typedef struct config_parser_state config_parser_state_type;
+
/*
* Options global for nsd.
*/
@@ -67,6 +71,7 @@ struct nsd_options {
int verbosity;
int hide_version;
int hide_identity;
+ int drop_updates;
int do_ip4;
int do_ip6;
const char* database;
@@ -74,6 +79,8 @@ struct nsd_options {
const char* version;
const char* logfile;
int server_count;
+ struct cpu_option* cpu_affinity;
+ struct cpu_map_option* service_cpu_affinity;
int tcp_count;
int tcp_reject_overflow;
int confine_to_zone;
@@ -159,9 +166,29 @@ struct nsd_options {
region_type* region;
};
+struct range_option {
+ struct range_option* next;
+ int first;
+ int last;
+};
+
struct ip_address_option {
struct ip_address_option* next;
char* address;
+ struct range_option* servers;
+ int dev;
+ int fib;
+};
+
+struct cpu_option {
+ struct cpu_option* next;
+ int cpu;
+};
+
+struct cpu_map_option {
+ struct cpu_map_option* next;
+ int service;
+ int cpu;
};
/*
@@ -300,12 +327,10 @@ struct config_parser_state {
int line;
int errors;
struct nsd_options* opt;
- /* pointer to memory where options for the configuration block that is
- currently parsed must be stored. memory is dynamically allocated,
- the block is promoted once it is closed. */
struct pattern_options *pattern;
struct zone_options *zone;
struct key_options *key;
+ struct ip_address_option *ip;
void (*err)(void*,const char*);
void* err_arg;
};
@@ -387,7 +412,8 @@ int acl_addr_matches_host(struct acl_options* acl, struct acl_options* host);
int acl_addr_matches(struct acl_options* acl, struct query* q);
int acl_key_matches(struct acl_options* acl, struct query* q);
int acl_addr_match_mask(uint32_t* a, uint32_t* b, uint32_t* mask, size_t sz);
-int acl_addr_match_range(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz);
+int acl_addr_match_range_v6(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz);
+int acl_addr_match_range_v4(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz);
/* returns true if acls are both from the same host */
int acl_same_host(struct acl_options* a, struct acl_options* b);
diff --git a/usr.sbin/nsd/packet.c b/usr.sbin/nsd/packet.c
index 0643202ae94..701453d8fdc 100644
--- a/usr.sbin/nsd/packet.c
+++ b/usr.sbin/nsd/packet.c
@@ -348,12 +348,19 @@ int packet_find_notify_serial(buffer_type *packet, uint32_t* serial)
{
size_t saved_position = buffer_position(packet);
/* count of further RRs after question section */
- size_t rrcount = ANCOUNT(packet) + NSCOUNT(packet) + ARCOUNT(packet);
+ size_t rrcount = (size_t)ANCOUNT(packet) + (size_t)NSCOUNT(packet) + (size_t)ARCOUNT(packet);
+ size_t qcount = (size_t)QDCOUNT(packet);
size_t i;
buffer_set_position(packet, QHEADERSZ);
+ if(qcount > 64 || rrcount > 65530) {
+ /* query count 0 or 1 only, rr number limited by 64k packet,
+ * and should not be impossibly high, parse error */
+ buffer_set_position(packet, saved_position);
+ return 0;
+ }
/* skip all question RRs */
- for (i = 0; i < QDCOUNT(packet); ++i) {
+ for (i = 0; i < qcount; ++i) {
if (!packet_skip_rr(packet, 1)) {
buffer_set_position(packet, saved_position);
return 0;
diff --git a/usr.sbin/nsd/popen3.c b/usr.sbin/nsd/popen3.c
new file mode 100644
index 00000000000..d457ef308ba
--- /dev/null
+++ b/usr.sbin/nsd/popen3.c
@@ -0,0 +1,176 @@
+#include "config.h"
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#include "popen3.h"
+
+static void close_pipe(int fds[2])
+{
+ if(fds[0] != -1) {
+ close(fds[0]);
+ fds[0] = -1;
+ }
+ if(fds[1] != -1) {
+ close(fds[1]);
+ fds[1] = -1;
+ }
+}
+
+pid_t popen3(char *const *command,
+ FILE **finptr,
+ FILE **foutptr,
+ FILE **ferrptr)
+{
+ int err = 0;
+ int fdin[] = { -1, -1 };
+ int fdout[] = { -1, -1 };
+ int fderr[] = { -1, -1 };
+ int fdsig[] = { -1, -1 };
+ FILE *fin, *fout, *ferr;
+ pid_t pid;
+ ssize_t discard;
+
+ if(command == NULL || *command == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ fin = fout = ferr = NULL;
+
+ if(finptr != NULL && (pipe(fdin) == -1 ||
+ (fin = fdopen(fdin[1], "w")) == NULL))
+ {
+ goto error;
+ }
+ if(foutptr != NULL && (pipe(fdout) == -1 ||
+ (fout = fdopen(fdout[0], "r")) == NULL))
+ {
+ goto error;
+ }
+ if(ferrptr != NULL && (pipe(fderr) == -1 ||
+ (ferr = fdopen(fderr[0], "r")) == NULL))
+ {
+ goto error;
+ }
+ if(pipe(fdsig) == -1 ||
+ fcntl(fdsig[0], F_SETFD, FD_CLOEXEC) == -1 ||
+ fcntl(fdsig[1], F_SETFD, FD_CLOEXEC) == -1)
+ {
+ goto error;
+ }
+
+ pid = fork();
+ switch(pid) {
+ case -1: /* error */
+ goto error;
+ case 0: /* child */
+ if(ferrptr != NULL) {
+ if(dup2(fderr[1], 2) == -1) {
+ goto error_dup2;
+ }
+ close_pipe(fderr);
+ } else {
+ close(2);
+ }
+ if(foutptr != NULL) {
+ if(dup2(fdout[1], 1) == -1) {
+ goto error_dup2;
+ }
+ close_pipe(fdout);
+ } else {
+ close(1);
+ }
+ if(finptr != NULL) {
+ if(dup2(fdin[0], 0) == -1) {
+ goto error_dup2;
+ }
+ close_pipe(fdin);
+ } else {
+ close(0);
+ }
+
+ execvp(*command, command);
+error_dup2:
+ err = errno;
+ close(fdsig[0]);
+ discard = write(fdsig[1], &err, sizeof(err));
+ (void)discard;
+ close(fdsig[1]);
+ exit(-1);
+ default: /* parent */
+ {
+ /* wait for signal pipe to close */
+ int ret;
+ fd_set rfds;
+
+ close(fdsig[1]);
+ fdsig[1] = -1;
+ do {
+ FD_ZERO(&rfds);
+ FD_SET(fdsig[0], &rfds);
+ ret = select(fdsig[0] + 1, &rfds, NULL, NULL, NULL);
+ } while(ret == -1 && errno == EINTR);
+
+ if(ret == -1) {
+ goto error;
+ }
+
+ if((ret = read(fdsig[0], &err, sizeof(err))) != 0) {
+ if(ret != -1) {
+ assert(ret == sizeof(err));
+ errno = err;
+ }
+ goto error;
+ }
+ close(fdsig[0]);
+ fdsig[0] = -1;
+ }
+ break;
+ }
+
+ if(finptr != NULL) {
+ close(fdin[0]);
+ *finptr = fin;
+ }
+ if(foutptr != NULL) {
+ close(fdout[1]);
+ *foutptr = fout;
+ }
+ if(ferrptr != NULL) {
+ close(fderr[1]);
+ *ferrptr = ferr;
+ }
+
+ return pid;
+
+error:
+ err = errno;
+
+ if(fin != NULL) {
+ fclose(fin);
+ fdin[1] = -1;
+ }
+ if(fout != NULL) {
+ fclose(fout);
+ fdout[0] = -1;
+ }
+ if(ferr != NULL) {
+ fclose(ferr);
+ fderr[0] = -1;
+ }
+
+ close_pipe(fdin);
+ close_pipe(fdout);
+ close_pipe(fderr);
+ close_pipe(fdsig);
+
+ errno = err;
+
+ return -1;
+}
diff --git a/usr.sbin/nsd/popen3.h b/usr.sbin/nsd/popen3.h
new file mode 100644
index 00000000000..7c09c42e2ab
--- /dev/null
+++ b/usr.sbin/nsd/popen3.h
@@ -0,0 +1,27 @@
+/*
+ * popen3.h -- execute a command and connect stdin, stdout and stderr
+ *
+ * Copyright (c) 2019, NLnet Labs. All rights reserved.
+ *
+ * See LICENSE for the license.
+ *
+ */
+#ifndef _POPEN3_H_
+#define _POPEN3_H_
+
+#include <stdio.h>
+#include <sys/types.h>
+
+/*
+ * Execute a command and connect stdin, stdout and stderr of the process to
+ * respectively finptr, foutptr and ferrptr if non-NULL. The process
+ * identifier of the new process is returned on success and the pointers to
+ * the FILE handles will have been set. On failure, -1 is returned and none
+ * of the pointers will have been set.
+ */
+pid_t popen3(char *const *command,
+ FILE **finptr,
+ FILE **foutptr,
+ FILE **ferrptr);
+
+#endif /* _POPEN3_H_ */
diff --git a/usr.sbin/nsd/query.c b/usr.sbin/nsd/query.c
index 927d348cab5..e0e5cf493b3 100644
--- a/usr.sbin/nsd/query.c
+++ b/usr.sbin/nsd/query.c
@@ -957,7 +957,16 @@ answer_domain(struct nsd* nsd, struct query *q, answer_type *answer,
rrset_type *rrset;
if (q->qtype == TYPE_ANY) {
- int added = 0;
+ rrset_type *preferred_rrset = NULL;
+ rrset_type *normal_rrset = NULL;
+ rrset_type *non_preferred_rrset = NULL;
+
+ /*
+ * Minimize response size for ANY, with one RRset
+ * according to RFC 8482(4.1).
+ * Prefers popular and not large rtypes (A,AAAA,...)
+ * lowering large ones (DNSKEY,RRSIG,...).
+ */
for (rrset = domain_find_any_rrset(domain, q->zone); rrset; rrset = rrset->next) {
if (rrset->zone == q->zone
#ifdef NSEC3
@@ -972,16 +981,32 @@ answer_domain(struct nsd* nsd, struct query *q, answer_type *answer,
&& zone_is_secure(q->zone)
&& rrset_rrtype(rrset) == TYPE_RRSIG))
{
- add_rrset(q, answer, ANSWER_SECTION, domain, rrset);
- ++added;
-#ifdef NOTYET
- /* minimize response size with one RR,
- * according to RFC 8482(4.1). */
- break;
-#endif
+ switch(rrset_rrtype(rrset)) {
+ case TYPE_A:
+ case TYPE_AAAA:
+ case TYPE_SOA:
+ case TYPE_MX:
+ case TYPE_PTR:
+ preferred_rrset = rrset;
+ break;
+ case TYPE_DNSKEY:
+ case TYPE_RRSIG:
+ case TYPE_NSEC:
+ non_preferred_rrset = rrset;
+ break;
+ default:
+ normal_rrset = rrset;
+ }
+ if (preferred_rrset) break;
}
}
- if (added == 0) {
+ if (preferred_rrset) {
+ add_rrset(q, answer, ANSWER_SECTION, domain, preferred_rrset);
+ } else if (normal_rrset) {
+ add_rrset(q, answer, ANSWER_SECTION, domain, normal_rrset);
+ } else if (non_preferred_rrset) {
+ add_rrset(q, answer, ANSWER_SECTION, domain, non_preferred_rrset);
+ } else {
answer_nodata(q, answer, original);
return;
}
@@ -1399,6 +1424,8 @@ query_process(query_type *q, nsd_type *nsd)
if(q->opcode != OPCODE_QUERY && q->opcode != OPCODE_NOTIFY) {
if(query_ratelimit_err(nsd))
return QUERY_DISCARDED;
+ if(nsd->options->drop_updates && q->opcode == OPCODE_UPDATE)
+ return QUERY_DISCARDED;
return query_error(q, NSD_RC_IMPL);
}
@@ -1435,8 +1462,15 @@ query_process(query_type *q, nsd_type *nsd)
return query_formerr(q, nsd);
}
if(q->qtype==TYPE_IXFR && NSCOUNT(q->packet) > 0) {
- int i; /* skip ixfr soa information data here */
- for(i=0; i< NSCOUNT(q->packet); i++)
+ unsigned int i; /* skip ixfr soa information data here */
+ unsigned int nscount = (unsigned)NSCOUNT(q->packet);
+ /* define a bound on the number of extraneous records allowed,
+ * we expect 1, a SOA serial record, and no more.
+ * perhaps RRSIGs (but not needed), otherwise we do not
+ * understand what this means. We do not want too many
+ * because the high iteration counts slow down. */
+ if(nscount > 64) return query_formerr(q, nsd);
+ for(i=0; i< nscount; i++)
if(!packet_skip_rr(q->packet, 0))
return query_formerr(q, nsd);
}
diff --git a/usr.sbin/nsd/radtree.c b/usr.sbin/nsd/radtree.c
index 873f0f8eba5..4bd12a4e6e9 100644
--- a/usr.sbin/nsd/radtree.c
+++ b/usr.sbin/nsd/radtree.c
@@ -174,6 +174,8 @@ static int radix_find_prefix_node(struct radtree* rt, uint8_t* k,
*respos = pos;
*result = n;
}
+ /* cannot reach because of returns when !n above */
+ /* ENOREACH */
return 1;
}
diff --git a/usr.sbin/nsd/region-allocator.c b/usr.sbin/nsd/region-allocator.c
index 638c861bdb3..f53841ad13d 100644
--- a/usr.sbin/nsd/region-allocator.c
+++ b/usr.sbin/nsd/region-allocator.c
@@ -272,7 +272,7 @@ region_alloc(region_type *region, size_t size)
region->total_allocated += size;
++region->large_objects;
- return result + sizeof(struct large_elem);
+ return (char *)result + sizeof(struct large_elem);
}
if (region->recycle_bin && region->recycle_bin[aligned_size]) {
@@ -469,7 +469,7 @@ region_recycle(region_type *region, void *block, size_t size)
region->total_allocated -= size;
--region->large_objects;
- l = (struct large_elem*)(block-sizeof(struct large_elem));
+ l = (struct large_elem*)((char*)block-sizeof(struct large_elem));
if(l->prev)
l->prev->next = l->next;
else region->large_list = l->next;
diff --git a/usr.sbin/nsd/remote.c b/usr.sbin/nsd/remote.c
index 80e50053822..f677d9495e3 100644
--- a/usr.sbin/nsd/remote.c
+++ b/usr.sbin/nsd/remote.c
@@ -375,6 +375,7 @@ create_tcp_accept_sock(struct addrinfo* addr, int* noproto)
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
{
log_msg(LOG_ERR, "setsockopt(..., IPV6_V6ONLY, ...) failed: %s", strerror(errno));
+ close(s);
return -1;
}
#endif
@@ -387,11 +388,13 @@ create_tcp_accept_sock(struct addrinfo* addr, int* noproto)
/* Bind it... */
if (bind(s, (struct sockaddr *)addr->ai_addr, addr->ai_addrlen) != 0) {
log_msg(LOG_ERR, "can't bind tcp socket: %s", strerror(errno));
+ close(s);
return -1;
}
/* Listen to it... */
if (listen(s, TCP_BACKLOG_REMOTE) == -1) {
log_msg(LOG_ERR, "can't listen: %s", strerror(errno));
+ close(s);
return -1;
}
return s;
@@ -437,7 +440,9 @@ add_open(struct daemon_remote* rc, struct nsd_options* cfg, const char* ip,
(unsigned)nsd.uid, (unsigned)nsd.gid,
ip, strerror(errno)));
}
- chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
+ if(chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == -1) {
+ VERBOSITY(3, (LOG_INFO, "cannot chmod control socket %s: %s", ip, strerror(errno)));
+ }
#else
(void)cfg;
#endif
@@ -445,9 +450,11 @@ add_open(struct daemon_remote* rc, struct nsd_options* cfg, const char* ip,
} else {
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+ /* if we had no interface ip name, "default" is what we
+ * would do getaddrinfo for. */
if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
log_msg(LOG_ERR, "control interface %s:%s getaddrinfo: %s %s",
- ip?ip:"default", port, gai_strerror(r),
+ ip, port, gai_strerror(r),
#ifdef EAI_SYSTEM
r==EAI_SYSTEM?(char*)strerror(errno):""
#else
@@ -771,6 +778,8 @@ ssl_read_line(RES* res, char* buf, size_t max)
if(!res)
return 0;
while(len < max) {
+ buf[len] = 0; /* terminate for safety and please checkers */
+ /* this byte is written if we read a byte from the input */
if(res->ssl) {
ERR_clear_error();
if((r=SSL_read(res->ssl, buf+len, 1)) <= 0) {
@@ -840,14 +849,14 @@ get_zone_arg(RES* ssl, xfrd_state_type* xfrd, char* arg,
}
dname = dname_parse(xfrd->region, arg);
if(!dname) {
- ssl_printf(ssl, "error cannot parse zone name '%s'\n", arg);
+ (void)ssl_printf(ssl, "error cannot parse zone name '%s'\n", arg);
*zo = NULL;
return 0;
}
*zo = zone_options_find(xfrd->nsd->options, dname);
region_recycle(xfrd->region, (void*)dname, dname_total_size(dname));
if(!*zo) {
- ssl_printf(ssl, "error zone %s not configured\n", arg);
+ (void)ssl_printf(ssl, "error zone %s not configured\n", arg);
return 0;
}
return 1;
@@ -914,7 +923,7 @@ do_notify(RES* ssl, xfrd_state_type* xfrd, char* arg)
xfrd_notify_start(n, xfrd);
send_ok(ssl);
} else {
- ssl_printf(ssl, "error zone does not have notify\n");
+ (void)ssl_printf(ssl, "error zone does not have notify\n");
}
} else {
struct notify_zone* n;
@@ -940,13 +949,13 @@ do_transfer(RES* ssl, xfrd_state_type* xfrd, char* arg)
xfrd_handle_notify_and_start_xfr(zone, NULL);
send_ok(ssl);
} else {
- ssl_printf(ssl, "error zone not slave\n");
+ (void)ssl_printf(ssl, "error zone not slave\n");
}
} else {
RBTREE_FOR(zone, xfrd_zone_type*, xfrd->zones) {
xfrd_handle_notify_and_start_xfr(zone, NULL);
}
- ssl_printf(ssl, "ok, %lu zones\n", (unsigned long)xfrd->zones->count);
+ (void)ssl_printf(ssl, "ok, %lu zones\n", (unsigned long)xfrd->zones->count);
}
}
@@ -981,13 +990,13 @@ do_force_transfer(RES* ssl, xfrd_state_type* xfrd, char* arg)
force_transfer_zone(zone);
send_ok(ssl);
} else {
- ssl_printf(ssl, "error zone not slave\n");
+ (void)ssl_printf(ssl, "error zone not slave\n");
}
} else {
RBTREE_FOR(zone, xfrd_zone_type*, xfrd->zones) {
force_transfer_zone(zone);
}
- ssl_printf(ssl, "ok, %lu zones\n", (unsigned long)xfrd->zones->count);
+ (void)ssl_printf(ssl, "ok, %lu zones\n", (unsigned long)xfrd->zones->count);
}
}
@@ -1109,11 +1118,11 @@ do_verbosity(RES* ssl, char* str)
{
int val = atoi(str);
if(strcmp(str, "") == 0) {
- ssl_printf(ssl, "verbosity %d\n", verbosity);
+ (void)ssl_printf(ssl, "verbosity %d\n", verbosity);
return;
}
if(val == 0 && strcmp(str, "0") != 0) {
- ssl_printf(ssl, "error in verbosity number syntax: %s\n", str);
+ (void)ssl_printf(ssl, "error in verbosity number syntax: %s\n", str);
return;
}
verbosity = val;
@@ -1137,7 +1146,7 @@ find_arg2(RES* ssl, char* arg, char** arg2)
return 1;
}
*arg2 = NULL;
- ssl_printf(ssl, "error could not find next argument "
+ (void)ssl_printf(ssl, "error could not find next argument "
"after %s\n", arg);
return 0;
}
@@ -1336,7 +1345,7 @@ perform_addzone(RES* ssl, xfrd_state_type* xfrd, char* arg)
}
/* see if zone is a duplicate */
- if( (zopt=zone_options_find(xfrd->nsd->options, dname)) ) {
+ if( zone_options_find(xfrd->nsd->options, dname) ) {
region_recycle(xfrd->region, (void*)dname,
dname_total_size(dname));
(void)ssl_printf(ssl, "zone %s already exists\n", arg);
@@ -1386,8 +1395,7 @@ perform_delzone(RES* ssl, xfrd_state_type* xfrd, char* arg)
region_recycle(xfrd->region, (void*)dname,
dname_total_size(dname));
/* nothing to do */
- if(!ssl_printf(ssl, "warning zone %s not present\n", arg))
- return 0;
+ (void)ssl_printf(ssl, "warning zone %s not present\n", arg);
return 0;
}
@@ -1866,7 +1874,7 @@ do_repattern(RES* ssl, xfrd_state_type* xfrd)
while(l>0 && xfrd->nsd->chrootdir[l-1] == '/')
--l;
if(strncmp(xfrd->nsd->chrootdir, cfgfile, l) != 0) {
- ssl_printf(ssl, "error %s is not relative to %s: "
+ (void)ssl_printf(ssl, "error %s is not relative to %s: "
"chroot prevents reread of config\n",
cfgfile, xfrd->nsd->chrootdir);
region_destroy(region);
@@ -1875,7 +1883,7 @@ do_repattern(RES* ssl, xfrd_state_type* xfrd)
cfgfile += l;
}
- ssl_printf(ssl, "reconfig start, read %s\n", cfgfile);
+ (void)ssl_printf(ssl, "reconfig start, read %s\n", cfgfile);
opt = nsd_options_create(region);
if(!parse_options_file(opt, cfgfile, &print_ssl_cfg_err, &ssl)) {
/* error already printed */
@@ -1913,12 +1921,10 @@ do_print_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
} else {
struct key_options* key_opts = key_options_find(xfrd->nsd->options, arg);
if(!key_opts) {
- if(!ssl_printf(ssl, "error: no such key with name: %s\n", arg))
- return;
+ (void)ssl_printf(ssl, "error: no such key with name: %s\n", arg);
return;
} else {
- if(!ssl_printf(ssl, "key: name: \"%s\" secret: \"%s\" algorithm: %s\n", arg, key_opts->secret, key_opts->algorithm))
- return;
+ (void)ssl_printf(ssl, "key: name: \"%s\" secret: \"%s\" algorithm: %s\n", arg, key_opts->secret, key_opts->algorithm);
}
}
}
@@ -1933,25 +1939,21 @@ do_update_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
struct key_options* key_opt;
if(*arg == '\0') {
- if(!ssl_printf(ssl, "error: missing argument (keyname)\n"))
- return;
+ (void)ssl_printf(ssl, "error: missing argument (keyname)\n");
return;
}
if(!find_arg2(ssl, arg, &arg2)) {
- if(!ssl_printf(ssl, "error: missing argument (secret)\n"))
- return;
+ (void)ssl_printf(ssl, "error: missing argument (secret)\n");
return;
}
key_opt = key_options_find(xfrd->nsd->options, arg);
if(!key_opt) {
- if(!ssl_printf(ssl, "error: no such key with name: %s\n", arg))
- return;
+ (void)ssl_printf(ssl, "error: no such key with name: %s\n", arg);
memset(arg2, 0xdd, strlen(arg2));
return;
}
if(__b64_pton(arg2, data, sizeof(data)) == -1) {
- if(!ssl_printf(ssl, "error: the secret: %s is not in b64 format\n", arg2))
- return;
+ (void)ssl_printf(ssl, "error: the secret: %s is not in b64 format\n", arg2);
memset(data, 0xdd, sizeof(data)); /* wipe secret */
memset(arg2, 0xdd, strlen(arg2));
return;
@@ -1991,8 +1993,7 @@ do_add_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
struct key_options* new_key_opt;
if(*arg == '\0') {
- if(!ssl_printf(ssl, "error: missing argument (keyname)\n"))
- return;
+ (void)ssl_printf(ssl, "error: missing argument (keyname)\n");
return;
}
if(!find_arg3(ssl, arg, &arg2, &arg3)) {
@@ -2001,33 +2002,28 @@ do_add_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
strlcpy(algo, arg3, sizeof(algo));
}
if(!arg2) {
- if(!ssl_printf(ssl, "error: missing argument (secret)\n"))
- return;
+ (void)ssl_printf(ssl, "error: missing argument (secret)\n");
return;
}
if(key_options_find(xfrd->nsd->options, arg)) {
- if(!ssl_printf(ssl, "error: key %s already exists\n", arg))
- return;
+ (void)ssl_printf(ssl, "error: key %s already exists\n", arg);
memset(arg2, 0xdd, strlen(arg2));
return;
}
if(__b64_pton(arg2, data, sizeof(data)) == -1) {
- if(!ssl_printf(ssl, "error: the secret: %s is not in b64 format\n", arg2))
- return;
+ (void)ssl_printf(ssl, "error: the secret: %s is not in b64 format\n", arg2);
memset(data, 0xdd, sizeof(data)); /* wipe secret */
memset(arg2, 0xdd, strlen(arg2));
return;
}
memset(data, 0xdd, sizeof(data)); /* wipe secret from temp buffer */
if(!dname_parse_wire(dname, arg)) {
- if(!ssl_printf(ssl, "error: could not parse key name: %s\n", arg))
- return;
+ (void)ssl_printf(ssl, "error: could not parse key name: %s\n", arg);
memset(arg2, 0xdd, strlen(arg2));
return;
}
if(tsig_get_algorithm_by_name(algo) == NULL) {
- if(!ssl_printf(ssl, "error: unknown algorithm: %s\n", algo))
- return;
+ (void)ssl_printf(ssl, "error: unknown algorithm: %s\n", algo);
memset(arg2, 0xdd, strlen(arg2));
return;
}
@@ -2073,27 +2069,23 @@ do_assoc_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
struct key_options* key_opt;
if(*arg == '\0') {
- if(!ssl_printf(ssl, "error: missing argument (zonename)\n"))
- return;
+ (void)ssl_printf(ssl, "error: missing argument (zonename)\n");
return;
}
if(!find_arg2(ssl, arg, &arg2)) {
- if(!ssl_printf(ssl, "error: missing argument (keyname)\n"))
- return;
+ (void)ssl_printf(ssl, "error: missing argument (keyname)\n");
return;
}
if(!get_zone_arg(ssl, xfrd, arg, &zone))
return;
if(!zone) {
- if(!ssl_printf(ssl, "error: missing argument (zone)\n"))
- return;
+ (void)ssl_printf(ssl, "error: missing argument (zone)\n");
return;
}
key_opt = key_options_find(xfrd->nsd->options, arg2);
if(!key_opt) {
- if(!ssl_printf(ssl, "error: key: %s does not exist\n", arg2))
- return;
+ (void)ssl_printf(ssl, "error: key: %s does not exist\n", arg2);
return;
}
@@ -2132,14 +2124,12 @@ do_del_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg) {
struct key_options* key_opt;
if(*arg == '\0') {
- if(!ssl_printf(ssl, "error: missing argument (keyname)\n"))
- return;
+ (void)ssl_printf(ssl, "error: missing argument (keyname)\n");
return;
}
key_opt = key_options_find(xfrd->nsd->options, arg);
if(!key_opt) {
- if(!ssl_printf(ssl, "key %s does not exist, nothing to be deleted\n", arg))
- return;
+ (void)ssl_printf(ssl, "key %s does not exist, nothing to be deleted\n", arg);
return;
}
RBTREE_FOR(zone, struct zone_options*, xfrd->nsd->options->zone_options)
@@ -2157,8 +2147,7 @@ do_del_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg) {
}
if(used_key) {
- if(!ssl_printf(ssl, "error: key: %s is in use and cannot be deleted\n", arg))
- return;
+ (void)ssl_printf(ssl, "error: key: %s is in use and cannot be deleted\n", arg);
return;
} else {
remove_key(xfrd, arg);
@@ -2286,7 +2275,7 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res)
if(strcmp(magic, pre) != 0) {
VERBOSITY(2, (LOG_INFO, "control connection had bad "
"version %s, cmd: %s", magic, buf));
- ssl_printf(res, "error version mismatch\n");
+ (void)ssl_printf(res, "error version mismatch\n");
return;
}
VERBOSITY(2, (LOG_INFO, "control cmd: %s", buf));
diff --git a/usr.sbin/nsd/server.c b/usr.sbin/nsd/server.c
index 6f5e2b0b189..2db997a667e 100644
--- a/usr.sbin/nsd/server.c
+++ b/usr.sbin/nsd/server.c
@@ -35,6 +35,9 @@
#include <signal.h>
#include <netdb.h>
#include <poll.h>
+#ifdef HAVE_SYS_RANDOM_H
+#include <sys/random.h>
+#endif
#ifndef SHUT_WR
#define SHUT_WR 1
#endif
@@ -672,6 +675,22 @@ initialize_dname_compression_tables(struct nsd *nsd)
}
static int
+set_cloexec(struct nsd_socket *sock)
+{
+ assert(sock != NULL);
+
+ if(fcntl(sock->s, F_SETFD, FD_CLOEXEC) == -1) {
+ const char *socktype =
+ sock->addr.ai_family == SOCK_DGRAM ? "udp" : "tcp";
+ log_msg(LOG_ERR, "fcntl(..., O_CLOEXEC) failed for %s: %s",
+ socktype, strerror(errno));
+ return -1;
+ }
+
+ return 1;
+}
+
+static int
set_reuseport(struct nsd_socket *sock)
{
#ifdef SO_REUSEPORT
@@ -944,34 +963,64 @@ set_ip_freebind(struct nsd_socket *sock)
static int
set_ip_transparent(struct nsd_socket *sock)
{
-#if defined(IP_TRANSPARENT)
- int on = 1;
- const char *socktype =
- sock->addr.ai_socktype == SOCK_DGRAM ? "udp" : "tcp";
- if(0 == setsockopt(
- sock->s, IPPROTO_IP, IP_TRANSPARENT, &on, sizeof(on)))
- {
- return 1;
- }
+ /*
+ The scandalous preprocessor blob here calls for some explanation :)
+ POSIX does not specify an option to bind non-local IPs, so
+ platforms developed several implementation-specific options,
+ all set in the same way, but with different names.
+ For additional complexity, some platform manage this setting
+ differently for different address families (IPv4 vs IPv6).
+ This scandalous preprocessor blob below abstracts such variability
+ in the way which leaves the C code as lean and clear as possible.
+ */
- log_msg(LOG_ERR, "setsockopt(..., %s, ...) failed for %s: %s",
- "IP_TRANSPARENT", socktype, strerror(errno));
- return -1;
+#if defined(IP_TRANSPARENT)
+# define NSD_SOCKET_OPTION_TRANSPARENT IP_TRANSPARENT
+# define NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL IPPROTO_IP
+# define NSD_SOCKET_OPTION_TRANSPARENT_NAME "IP_TRANSPARENT"
+// as of 2020-01, Linux does not support this on IPv6 programmatically
#elif defined(SO_BINDANY)
+# define NSD_SOCKET_OPTION_TRANSPARENT SO_BINDANY
+# define NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL SOL_SOCKET
+# define NSD_SOCKET_OPTION_TRANSPARENT_NAME "SO_BINDANY"
+#elif defined(IP_BINDANY)
+# define NSD_SOCKET_OPTION_TRANSPARENT IP_BINDANY
+# define NSD_SOCKET_OPTION_TRANSPARENT6 IPV6_BINDANY
+# define NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL IPPROTO_IP
+# define NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL6 IPPROTO_IPV6
+# define NSD_SOCKET_OPTION_TRANSPARENT_NAME "IP_BINDANY"
+#endif
+
+#ifndef NSD_SOCKET_OPTION_TRANSPARENT
+ (void)sock;
+#else
+# ifndef NSD_SOCKET_OPTION_TRANSPARENT6
+# define NSD_SOCKET_OPTION_TRANSPARENT6 NSD_SOCKET_OPTION_TRANSPARENT
+# endif
+# ifndef NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL6
+# define NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL6 NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL
+# endif
+# ifndef NSD_SOCKET_OPTION_TRANSPARENT_NAME6
+# define NSD_SOCKET_OPTION_TRANSPARENT_NAME6 NSD_SOCKET_OPTION_TRANSPARENT_NAME
+# endif
+
int on = 1;
const char *socktype =
sock->addr.ai_socktype == SOCK_DGRAM ? "udp" : "tcp";
+ const int is_ip6 = (sock->addr.ai_family == AF_INET6);
+
if(0 == setsockopt(
- sock->s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on)))
+ sock->s,
+ is_ip6 ? NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL6 : NSD_SOCKET_OPTION_TRANSPARENT_OPTLEVEL,
+ is_ip6 ? NSD_SOCKET_OPTION_TRANSPARENT6 : NSD_SOCKET_OPTION_TRANSPARENT,
+ &on, sizeof(on)))
{
return 1;
}
log_msg(LOG_ERR, "setsockopt(..., %s, ...) failed for %s: %s",
- "SO_BINDANY", socktype, strerror(errno));
+ is_ip6 ? NSD_SOCKET_OPTION_TRANSPARENT_NAME6 : NSD_SOCKET_OPTION_TRANSPARENT_NAME, socktype, strerror(errno));
return -1;
-#else
- (void)sock;
#endif
return 0;
@@ -1038,6 +1087,44 @@ set_tcp_fastopen(struct nsd_socket *sock)
#endif /* USE_TCP_FASTOPEN */
static int
+set_bindtodevice(struct nsd_socket *sock)
+{
+#if defined(SO_BINDTODEVICE)
+ if(setsockopt(sock->s, SOL_SOCKET, SO_BINDTODEVICE,
+ sock->device, strlen(sock->device)) == -1)
+ {
+ log_msg(LOG_ERR, "setsockopt(..., %s, %s, ...) failed: %s",
+ "SO_BINDTODEVICE", sock->device, strerror(errno));
+ return -1;
+ }
+
+ return 1;
+#else
+ (void)sock;
+ return 0;
+#endif
+}
+
+static int
+set_setfib(struct nsd_socket *sock)
+{
+#if defined(SO_SETFIB)
+ if(setsockopt(sock->s, SOL_SOCKET, SO_SETFIB,
+ (const void *)&sock->fib, sizeof(sock->fib)) == -1)
+ {
+ log_msg(LOG_ERR, "setsockopt(..., %s, %d, ...) failed: %s",
+ "SO_SETFIB", sock->fib, strerror(errno));
+ return -1;
+ }
+
+ return 1;
+#else
+ (void)sock;
+ return 0;
+#endif
+}
+
+static int
open_udp_socket(struct nsd *nsd, struct nsd_socket *sock, int *reuseport_works)
{
int rcv = 1*1024*1024, snd = 1*1024*1024;
@@ -1059,6 +1146,8 @@ open_udp_socket(struct nsd *nsd, struct nsd_socket *sock, int *reuseport_works)
return -1;
}
+ set_cloexec(sock);
+
if(nsd->reuseport && reuseport_works && *reuseport_works)
*reuseport_works = (set_reuseport(sock) == 1);
@@ -1093,6 +1182,10 @@ open_udp_socket(struct nsd *nsd, struct nsd_socket *sock, int *reuseport_works)
(void)set_ip_freebind(sock);
if(nsd->options->ip_transparent)
(void)set_ip_transparent(sock);
+ if((sock->flags & NSD_BIND_DEVICE) && set_bindtodevice(sock) == -1)
+ return -1;
+ if(sock->fib != -1 && set_setfib(sock) == -1)
+ return -1;
if(bind(sock->s, (struct sockaddr *)&sock->addr.ai_addr, sock->addr.ai_addrlen) == -1) {
char buf[256];
@@ -1131,6 +1224,8 @@ open_tcp_socket(struct nsd *nsd, struct nsd_socket *sock, int *reuseport_works)
return -1;
}
+ set_cloexec(sock);
+
if(nsd->reuseport && reuseport_works && *reuseport_works)
*reuseport_works = (set_reuseport(sock) == 1);
@@ -1153,6 +1248,10 @@ open_tcp_socket(struct nsd *nsd, struct nsd_socket *sock, int *reuseport_works)
(void)set_ip_freebind(sock);
if(nsd->options->ip_transparent)
(void)set_ip_transparent(sock);
+ if((sock->flags & NSD_BIND_DEVICE) && set_bindtodevice(sock) == -1)
+ return -1;
+ if(sock->fib != -1 && set_setfib(sock) == -1)
+ return -1;
if(bind(sock->s, (struct sockaddr *)&sock->addr.ai_addr, sock->addr.ai_addrlen) == -1) {
char buf[256];
@@ -1200,6 +1299,7 @@ server_init(struct nsd *nsd)
* instance */
region_remove_cleanup(nsd->region, free, nsd->udp);
region_remove_cleanup(nsd->region, free, nsd->tcp);
+
nsd->udp = xrealloc(nsd->udp, ifs * sizeof(*nsd->udp));
nsd->tcp = xrealloc(nsd->tcp, ifs * sizeof(*nsd->tcp));
region_add_cleanup(nsd->region, free, nsd->udp);
@@ -1207,11 +1307,15 @@ server_init(struct nsd *nsd)
for(i = nsd->ifs; i < ifs; i++) {
nsd->udp[i].addr = nsd->udp[i%nsd->ifs].addr;
+ nsd->udp[i].servers = nsd->udp[i%nsd->ifs].servers;
if(open_udp_socket(nsd, &nsd->udp[i], &reuseport) == -1) {
return -1;
}
/* Turn off REUSEPORT for TCP by copying the socket
* file descriptor.
+ * This means we should not close TCP used by
+ * other servers in reuseport enabled mode, in
+ * server_child().
*/
nsd->tcp[i] = nsd->tcp[i%nsd->ifs];
}
@@ -1233,7 +1337,14 @@ server_prepare(struct nsd *nsd)
{
#ifdef RATELIMIT
/* set secret modifier for hashing (udb ptr buckets and rate limits) */
-#ifdef HAVE_ARC4RANDOM
+#ifdef HAVE_GETRANDOM
+ uint32_t v;
+ if(getrandom(&v, sizeof(v), 0) == -1) {
+ log_msg(LOG_ERR, "getrandom failed: %s", strerror(errno));
+ exit(1);
+ }
+ hash_set_raninit(v);
+#elif defined(HAVE_ARC4RANDOM)
hash_set_raninit(arc4random());
#else
uint32_t v = getpid() ^ time(NULL);
@@ -1303,6 +1414,15 @@ server_start_children(struct nsd *nsd, region_type* region, netio_type* netio,
return restart_child_servers(nsd, region, netio, xfrd_sock_p);
}
+static void
+server_close_socket(struct nsd_socket *sock)
+{
+ if(sock->s != -1) {
+ close(sock->s);
+ sock->s = -1;
+ }
+}
+
void
server_close_all_sockets(struct nsd_socket sockets[], size_t n)
{
@@ -1310,10 +1430,7 @@ server_close_all_sockets(struct nsd_socket sockets[], size_t n)
/* Close all the sockets... */
for (i = 0; i < n; ++i) {
- if (sockets[i].s != -1) {
- close(sockets[i].s);
- sockets[i].s = -1;
- }
+ server_close_socket(&sockets[i]);
}
}
@@ -1455,6 +1572,16 @@ server_start_xfrd(struct nsd *nsd, int del_db, int reload_active)
/* use other task than I am using, since if xfrd died and is
* restarted, the reload is using nsd->mytask */
nsd->mytask = 1 - nsd->mytask;
+
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("xfrd");
+#endif
+#ifdef HAVE_CPUSET_T
+ if(nsd->use_cpu_affinity) {
+ set_cpu_affinity(nsd->xfrd_cpuset);
+ }
+#endif
+
xfrd_init(sockets[1], nsd, del_db, reload_active, pid);
/* ENOTREACH */
break;
@@ -1771,11 +1898,13 @@ server_tls_ctx_setup(char* key, char* pem, char* verifypem)
return NULL;
}
/* no SSLv2, SSLv3 because has defects */
+#if SSL_OP_NO_SSLv2 != 0
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2) != SSL_OP_NO_SSLv2){
log_crypto_err("could not set SSL_OP_NO_SSLv2");
SSL_CTX_free(ctx);
return NULL;
}
+#endif
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
!= SSL_OP_NO_SSLv3){
log_crypto_err("could not set SSL_OP_NO_SSLv3");
@@ -2074,6 +2203,15 @@ server_reload(struct nsd *nsd, region_type* server_region, netio_type* netio,
ign_sigchld.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &ign_sigchld, &old_sigchld);
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("main");
+#endif
+#ifdef HAVE_CPUSET_T
+ if(nsd->use_cpu_affinity) {
+ set_cpu_affinity(nsd->cpuset);
+ }
+#endif
+
/* see what tasks we got from xfrd */
task_remap(nsd->task[nsd->mytask]);
udb_ptr_init(&last_task, nsd->task[nsd->mytask]);
@@ -2679,6 +2817,15 @@ server_child(struct nsd *nsd)
assert(nsd->server_kind != NSD_SERVER_MAIN);
DEBUG(DEBUG_IPC, 2, (LOG_INFO, "child process started"));
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("server %d", nsd->this_child->child_num + 1);
+#endif
+#ifdef HAVE_CPUSET_T
+ if(nsd->use_cpu_affinity) {
+ set_cpu_affinity(nsd->this_child->cpuset);
+ }
+#endif
+
if (!(nsd->server_kind & NSD_SERVER_TCP)) {
server_close_all_sockets(nsd->tcp, nsd->ifs);
}
@@ -2718,6 +2865,7 @@ server_child(struct nsd *nsd)
}
if (nsd->server_kind & NSD_SERVER_UDP) {
+ int child = nsd->this_child->child_num;
memset(msgs, 0, sizeof(msgs));
for (i = 0; i < NUM_RECV_PER_SELECT; i++) {
queries[i] = query_create(server_region,
@@ -2725,17 +2873,27 @@ server_child(struct nsd *nsd)
compression_table_size, compressed_dnames);
query_reset(queries[i], UDP_MAX_MESSAGE_LEN, 0);
iovecs[i].iov_base = buffer_begin(queries[i]->packet);
- iovecs[i].iov_len = buffer_remaining(queries[i]->packet);;
+ iovecs[i].iov_len = buffer_remaining(queries[i]->packet);
msgs[i].msg_hdr.msg_iov = &iovecs[i];
msgs[i].msg_hdr.msg_iovlen = 1;
msgs[i].msg_hdr.msg_name = &queries[i]->addr;
msgs[i].msg_hdr.msg_namelen = queries[i]->addrlen;
}
- for (i = from; i < from+numifs; ++i) {
- struct udp_handler_data *data = region_alloc_zero(
- nsd->server_region, sizeof(*data));
- add_udp_handler(nsd, &nsd->udp[i], data);
+ for (i = 0; i < nsd->ifs; i++) {
+ int listen;
+ struct udp_handler_data *data;
+
+ listen = nsd_bitset_isset(nsd->udp[i].servers, child);
+
+ if(i >= from && i < (from + numifs) && listen) {
+ data = region_alloc_zero(
+ nsd->server_region, sizeof(*data));
+ add_udp_handler(nsd, &nsd->udp[i], data);
+ } else {
+ /* close sockets intended for other servers */
+ server_close_socket(&nsd->udp[i]);
+ }
}
}
@@ -2745,15 +2903,33 @@ server_child(struct nsd *nsd)
* connections.
*/
if (nsd->server_kind & NSD_SERVER_TCP) {
+ int child = nsd->this_child->child_num;
tcp_accept_handler_count = numifs;
tcp_accept_handlers = region_alloc_array(server_region,
numifs, sizeof(*tcp_accept_handlers));
- for (i = from; i < numifs; i++) {
- struct tcp_accept_handler_data *data =
- &tcp_accept_handlers[i-from];
- memset(data, 0, sizeof(*data));
- add_tcp_handler(nsd, &nsd->tcp[i], data);
+ for (i = 0; i < nsd->ifs; i++) {
+ int listen;
+ struct tcp_accept_handler_data *data;
+
+ listen = nsd_bitset_isset(nsd->tcp[i].servers, child);
+
+ if(i >= from && i < (from + numifs) && listen) {
+ data = &tcp_accept_handlers[i-from];
+ memset(data, 0, sizeof(*data));
+ add_tcp_handler(nsd, &nsd->tcp[i], data);
+ } else {
+ /* close sockets intended for other servers */
+ /*
+ * uncomment this once tcp servers are no
+ * longer copied in the tcp fd copy line
+ * in server_init().
+ server_close_socket(&nsd->tcp[i]);
+ */
+ /* close sockets not meant for this server*/
+ if(!listen)
+ server_close_socket(&nsd->tcp[i]);
+ }
}
} else {
tcp_accept_handler_count = 0;
diff --git a/usr.sbin/nsd/tsig.c b/usr.sbin/nsd/tsig.c
index 91ca99b93b5..8b24fd1bf07 100644
--- a/usr.sbin/nsd/tsig.c
+++ b/usr.sbin/nsd/tsig.c
@@ -546,10 +546,10 @@ int
tsig_find_rr(tsig_record_type *tsig, buffer_type *packet)
{
size_t saved_position = buffer_position(packet);
- size_t rrcount = (QDCOUNT(packet)
- + ANCOUNT(packet)
- + NSCOUNT(packet)
- + ARCOUNT(packet));
+ size_t rrcount = ((size_t)QDCOUNT(packet)
+ + (size_t)ANCOUNT(packet)
+ + (size_t)NSCOUNT(packet)
+ + (size_t)ARCOUNT(packet));
size_t i;
int result;
@@ -557,6 +557,11 @@ tsig_find_rr(tsig_record_type *tsig, buffer_type *packet)
tsig->status = TSIG_NOT_PRESENT;
return 1;
}
+ if(rrcount > 65530) {
+ /* impossibly high number of records in 64k, reject packet */
+ buffer_set_position(packet, saved_position);
+ return 0;
+ }
buffer_set_position(packet, QHEADERSZ);
@@ -635,6 +640,12 @@ tsig_parse_rr(tsig_record_type *tsig, buffer_type *packet)
tsig->mac_size = 0;
return 0;
}
+ if(tsig->mac_size > 16384) {
+ /* the hash should not be too big, really 512/8=64 bytes */
+ buffer_set_position(packet, tsig->position);
+ tsig->mac_size = 0;
+ return 0;
+ }
tsig->mac_data = (uint8_t *) region_alloc_init(
tsig->rr_region, buffer_current(packet), tsig->mac_size);
buffer_skip(packet, tsig->mac_size);
diff --git a/usr.sbin/nsd/udb.c b/usr.sbin/nsd/udb.c
index 1b41ab91156..fb129b82100 100644
--- a/usr.sbin/nsd/udb.c
+++ b/usr.sbin/nsd/udb.c
@@ -192,13 +192,13 @@ udb_base_create_fd(const char* fname, int fd, udb_walk_relptr_func walkfunc,
}
/* init completion */
- udb->glob_data = (udb_glob_d*)(udb->base+sizeof(uint64_t));
+ udb->glob_data = (udb_glob_d*)((char*)udb->base+sizeof(uint64_t));
r = 0;
/* cannot be dirty because that is goto fail above */
if(udb->glob_data->dirty_alloc != udb_dirty_clean)
r = 1;
udb->alloc = udb_alloc_create(udb, (udb_alloc_d*)(
- (void*)udb->glob_data+sizeof(*udb->glob_data)));
+ (char*)udb->glob_data+sizeof(*udb->glob_data)));
if(!udb->alloc) {
log_msg(LOG_ERR, "out of memory");
udb_base_free(udb);
@@ -555,10 +555,10 @@ udb_base_remap(udb_base* udb, udb_alloc* alloc, uint64_t nsize)
/* fix up realpointers in udb and alloc */
/* but mremap may have been nice and not move the base */
udb->base = nb;
- udb->glob_data = (udb_glob_d*)(nb+sizeof(uint64_t));
+ udb->glob_data = (udb_glob_d*)((char*)nb+sizeof(uint64_t));
/* use passed alloc pointer because the udb->alloc may not
* be initialized yet */
- alloc->disk = (udb_alloc_d*)((void*)udb->glob_data
+ alloc->disk = (udb_alloc_d*)((char*)udb->glob_data
+sizeof(*udb->glob_data));
}
udb->base_size = nsize;
@@ -630,7 +630,7 @@ int udb_exp_size(uint64_t a)
}
assert( x>=0 && x<=63);
assert( ((uint64_t)1<<x) >= a);
- assert( x==0 || ((uint64_t)1<<(x-1)) < a);
+ assert( x==0 || /* <<x-1 without negative number analyzer complaints: */ (((uint64_t)1<<x)>>1) < a);
return x;
}
@@ -798,7 +798,7 @@ regen_ptrlist(void* base, udb_base* udb, udb_alloc* alloc,
if(exp == UDB_EXP_XL) {
assert(at != rb_old); /* should have been freed */
regen_its_ptrs(base, udb, atp,
- ((void*)atp)+sizeof(udb_xl_chunk_d),
+ ((char*)atp)+sizeof(udb_xl_chunk_d),
sz-sizeof(udb_xl_chunk_d) - sizeof(uint64_t)*2,
rb_old, rb_new);
at += sz;
@@ -807,7 +807,7 @@ regen_ptrlist(void* base, udb_base* udb, udb_alloc* alloc,
} else { /* data chunk */
assert(at != rb_old); /* should have been freed */
regen_its_ptrs(base, udb, atp,
- ((void*)atp)+sizeof(udb_chunk_d),
+ ((char*)atp)+sizeof(udb_chunk_d),
sz-sizeof(udb_chunk_d)-1, rb_old, rb_new);
at += sz;
}
diff --git a/usr.sbin/nsd/udb.h b/usr.sbin/nsd/udb.h
index 8d7ee137ad1..3ee98648b15 100644
--- a/usr.sbin/nsd/udb.h
+++ b/usr.sbin/nsd/udb.h
@@ -52,9 +52,9 @@ typedef struct udb_alloc udb_alloc;
typedef uint64_t udb_void;
/** convert relptr to usable pointer */
-#define UDB_REL(base, relptr) ((base) + (relptr))
+#define UDB_REL(base, relptr) ((void*)((char*)(base) + (relptr)))
/** from system pointer to relative pointer */
-#define UDB_SYSTOREL(base, ptr) ((udb_void)((void*)(ptr) - (base)))
+#define UDB_SYSTOREL(base, ptr) ((udb_void)((char*)(ptr) - (char*)(base)))
/** MAX 2**x exponent of alloced chunks, for 1Mbytes. The smallest
* chunk is 16bytes (8preamble+8data), so 0-3 is unused. */
diff --git a/usr.sbin/nsd/udbradtree.c b/usr.sbin/nsd/udbradtree.c
index 4452b6ddde1..5de16c7bb42 100644
--- a/usr.sbin/nsd/udbradtree.c
+++ b/usr.sbin/nsd/udbradtree.c
@@ -266,7 +266,7 @@ static int udb_radnode_array_grow(udb_base* udb, udb_ptr* n, size_t want)
RADARRAY(&a)->array[i].len = lookup_len(n, i);
}
memmove(&RADARRAY(&a)->array[ns], lookup_string(n, 0),
- lookup(n)->len * lookup(n)->str_cap);
+ ((size_t)lookup(n)->len) * ((size_t)lookup(n)->str_cap));
udb_radarray_zero_ptrs(udb, n);
udb_rel_ptr_free_space(&RADNODE(n)->lookup, udb, size_of_lookup(n));
udb_rptr_set_ptr(&RADNODE(n)->lookup, udb, &a);
@@ -361,7 +361,7 @@ static int udb_radnode_array_space(udb_base* udb, udb_ptr* n, uint8_t byte,
lookup_node(n, i+need)->pidx = i+need;
}
memmove(lookup_string(n, need), lookup_string(n, 0),
- lookup(n)->len*lookup(n)->str_cap);
+ ((size_t)lookup(n)->len)*((size_t)lookup(n)->str_cap));
/* zero the first */
for(i = 0; i < (int)need; i++) {
udb_rptr_zero(&lookup(n)->array[i].node, udb);
@@ -1257,7 +1257,7 @@ int udb_radix_find_less_equal(udb_base* udb, udb_ptr* rt, uint8_t* k,
/* must match additional string */
if(pos+lookup_len(&n, byte) > len) {
/* the additional string is longer than key*/
- if( (r=memcmp(&k[pos], lookup_string(&n, byte),
+ if( (memcmp(&k[pos], lookup_string(&n, byte),
len-pos)) <= 0) {
/* and the key is before this node */
udb_ptr_set_rptr(result, udb,
diff --git a/usr.sbin/nsd/util.c b/usr.sbin/nsd/util.c
index bef11f179c1..d7bfac69eb1 100644
--- a/usr.sbin/nsd/util.c
+++ b/usr.sbin/nsd/util.c
@@ -16,10 +16,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#ifdef HAVE_SCHED_H
+#include <sched.h>
+#endif /* HAVE_SCHED_H */
+#ifdef HAVE_SYS_CPUSET_H
+#include <sys/cpuset.h>
+#endif /* HAVE_SYS_CPUSET_H */
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif /* HAVE_SYSLOG_H */
#include <unistd.h>
+#ifdef HAVE_SYS_RANDOM_H
+#include <sys/random.h>
+#endif
#include "util.h"
#include "region-allocator.h"
@@ -260,9 +269,9 @@ xalloc(size_t size)
void *
xmallocarray(size_t num, size_t size)
-{
+{
void *result = reallocarray(NULL, num, size);
-
+
if (!result) {
log_msg(LOG_ERR, "reallocarray failed: %s", strerror(errno));
exit(1);
@@ -831,7 +840,7 @@ mktime_from_utc(const struct tm *tm)
http://www.tsfr.org/~orc/Code/bsd/bsd-current/cksum/crc.c.
or http://gobsd.com/code/freebsd/usr.bin/cksum/crc.c
The polynomial is 0x04c11db7L. */
-static u_long crctab[] = {
+static uint32_t crctab[] = {
0x0,
0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
@@ -923,8 +932,15 @@ compare_serial(uint32_t a, uint32_t b)
uint16_t
qid_generate(void)
{
+#ifdef HAVE_GETRANDOM
+ uint16_t r;
+ if(getrandom(&r, sizeof(r), 0) == -1) {
+ log_msg(LOG_ERR, "getrandom failed: %s", strerror(errno));
+ exit(1);
+ }
+ return r;
+#elif defined(HAVE_ARC4RANDOM)
/* arc4random_uniform not needed because range is a power of 2 */
-#ifdef HAVE_ARC4RANDOM
return (uint16_t) arc4random();
#else
return (uint16_t) random();
@@ -934,9 +950,16 @@ qid_generate(void)
int
random_generate(int max)
{
-#ifdef HAVE_ARC4RANDOM_UNIFORM
+#ifdef HAVE_GETRANDOM
+ int r;
+ if(getrandom(&r, sizeof(r), 0) == -1) {
+ log_msg(LOG_ERR, "getrandom failed: %s", strerror(errno));
+ exit(1);
+ }
+ return (int)(((unsigned)r)%max);
+#elif defined(HAVE_ARC4RANDOM_UNIFORM)
return (int) arc4random_uniform(max);
-#elif HAVE_ARC4RANDOM
+#elif defined(HAVE_ARC4RANDOM)
return (int) (arc4random() % max);
#else
return (int) ((unsigned)random() % max);
@@ -1149,3 +1172,41 @@ error(const char *format, ...)
exit(1);
}
+#ifdef HAVE_CPUSET_T
+#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
+/* exists on Linux and FreeBSD */
+int number_of_cpus(void)
+{
+ return (int)sysconf(_SC_NPROCESSORS_CONF);
+}
+#else
+int number_of_cpus(void)
+{
+ return -1;
+}
+#endif
+#ifdef __gnu_hurd__
+/* HURD has no sched_setaffinity implementation, but links an always fail,
+ * with a linker error, we print an error when it is used */
+int set_cpu_affinity(cpuset_t *ATTR_UNUSED(set))
+{
+ log_err("sched_setaffinity: not available on this system");
+ return -1;
+}
+#elif defined(HAVE_SCHED_SETAFFINITY)
+/* Linux */
+int set_cpu_affinity(cpuset_t *set)
+{
+ assert(set != NULL);
+ return sched_setaffinity(getpid(), sizeof(*set), set);
+}
+#else
+/* FreeBSD */
+int set_cpu_affinity(cpuset_t *set)
+{
+ assert(set != NULL);
+ return cpuset_setaffinity(
+ CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(*set), set);
+}
+#endif
+#endif /* HAVE_CPUSET_T */
diff --git a/usr.sbin/nsd/util.h b/usr.sbin/nsd/util.h
index 63c2d771b6d..89d4963a846 100644
--- a/usr.sbin/nsd/util.h
+++ b/usr.sbin/nsd/util.h
@@ -429,4 +429,9 @@ int file_inside_chroot(const char* fname, const char* chr);
/** Something went wrong, give error messages and exit. */
void error(const char *format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
+#if HAVE_CPUSET_T
+int number_of_cpus(void);
+int set_cpu_affinity(cpuset_t *set);
+#endif
+
#endif /* _UTIL_H_ */
diff --git a/usr.sbin/nsd/xfrd-tcp.c b/usr.sbin/nsd/xfrd-tcp.c
index 1ae5311c538..d00c13b756a 100644
--- a/usr.sbin/nsd/xfrd-tcp.c
+++ b/usr.sbin/nsd/xfrd-tcp.c
@@ -215,8 +215,8 @@ pipeline_find(struct xfrd_tcp_set* set, xfrd_zone_type* zone)
/* smaller buf than a full pipeline with 64kb ID array, only need
* the front part with the key info, this front part contains the
* members that the compare function uses. */
- const size_t keysize = sizeof(struct xfrd_tcp_pipeline) -
- ID_PIPE_NUM*(sizeof(struct xfrd_zone*) + sizeof(uint16_t));
+ enum { keysize = sizeof(struct xfrd_tcp_pipeline) -
+ ID_PIPE_NUM*(sizeof(struct xfrd_zone*) + sizeof(uint16_t)) };
/* void* type for alignment of the struct,
* divide the keysize by ptr-size and then add one to round up */
void* buf[ (keysize / sizeof(void*)) + 1 ];
diff --git a/usr.sbin/nsd/xfrd.c b/usr.sbin/nsd/xfrd.c
index bd07d797676..21a37448dff 100644
--- a/usr.sbin/nsd/xfrd.c
+++ b/usr.sbin/nsd/xfrd.c
@@ -200,7 +200,7 @@ xfrd_init(int socket, struct nsd* nsd, int shortsoa, int reload_active,
xfrd->tcp_set = xfrd_tcp_set_create(xfrd->region);
xfrd->tcp_set->tcp_timeout = nsd->tcp_timeout;
-#ifndef HAVE_ARC4RANDOM
+#if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_GETRANDOM)
srandom((unsigned long) getpid() * (unsigned long) time(NULL));
#endif
@@ -784,6 +784,8 @@ xfrd_set_timer_refresh(xfrd_zone_type* zone)
if(set < xfrd_time())
set = 0;
else set -= xfrd_time();
+ if(set > XFRD_TRANSFER_TIMEOUT_MAX)
+ set = XFRD_TRANSFER_TIMEOUT_MAX;
xfrd_set_timer(zone, set);
}
@@ -809,22 +811,16 @@ xfrd_set_timer_retry(xfrd_zone_type* zone)
/* set timer for next retry or expire timeout if earlier. */
if(zone->soa_disk_acquired == 0) {
/* if no information, use reasonable timeout */
-#ifdef HAVE_ARC4RANDOM_UNIFORM
xfrd_set_timer(zone, zone->fresh_xfr_timeout
- + arc4random_uniform(zone->fresh_xfr_timeout));
-#elif HAVE_ARC4RANDOM
- xfrd_set_timer(zone, zone->fresh_xfr_timeout
- + arc4random() % zone->fresh_xfr_timeout);
-#else
- xfrd_set_timer(zone, zone->fresh_xfr_timeout
- + random()%zone->fresh_xfr_timeout);
-#endif
+ + random_generate(zone->fresh_xfr_timeout));
} else if(zone->state == xfrd_zone_expired ||
xfrd_time() + (time_t)ntohl(zone->soa_disk.retry)*mult <
zone->soa_disk_acquired + (time_t)ntohl(zone->soa_disk.expire))
{
set_retry = ntohl(zone->soa_disk.retry);
set_retry *= mult;
+ if(set_retry > XFRD_TRANSFER_TIMEOUT_MAX)
+ set_retry = XFRD_TRANSFER_TIMEOUT_MAX;
if(set_retry > (time_t)zone->zone_options->pattern->max_retry_time)
set_retry = zone->zone_options->pattern->max_retry_time;
else if(set_retry < (time_t)zone->zone_options->pattern->min_retry_time)
@@ -834,6 +830,8 @@ xfrd_set_timer_retry(xfrd_zone_type* zone)
xfrd_set_timer(zone, set_retry);
} else {
set_retry = ntohl(zone->soa_disk.expire);
+ if(set_retry > XFRD_TRANSFER_TIMEOUT_MAX)
+ set_retry = XFRD_TRANSFER_TIMEOUT_MAX;
if(set_retry < XFRD_LOWERBOUND_RETRY)
xfrd_set_timer(zone, XFRD_LOWERBOUND_RETRY);
else {
@@ -1159,13 +1157,7 @@ xfrd_set_timer(xfrd_zone_type* zone, time_t t)
/* only for times far in the future */
if(t > 10) {
time_t base = t*9/10;
-#ifdef HAVE_ARC4RANDOM_UNIFORM
- t = base + arc4random_uniform(t-base);
-#elif HAVE_ARC4RANDOM
- t = base + arc4random() % (t-base);
-#else
- t = base + random()%(t-base);
-#endif
+ t = base + random_generate(t-base);
}
/* keep existing flags and fd, but re-add with timeout */
@@ -1890,6 +1882,12 @@ xfrd_parse_received_xfr_packet(xfrd_zone_type* zone, buffer_type* packet,
}
buffer_skip(packet, QHEADERSZ);
+ if(qdcount > 64 || ancount > 65530 || nscount > 65530) {
+ /* 0 or 1 question section rr, and 64k limits other counts */
+ DEBUG(DEBUG_XFRD,1, (LOG_ERR, "dropping xfr reply, impossibly "
+ "high record count"));
+ return xfrd_packet_bad;
+ }
/* skip question section */
for(rr_count = 0; rr_count < qdcount; ++rr_count) {
@@ -2466,7 +2464,7 @@ static void
xfrd_process_stat_info_task(xfrd_state_type* xfrd, struct task_list_d* task)
{
size_t i;
- stc_type* p = (void*)task->zname + sizeof(struct nsdst);
+ stc_type* p = (void*)((char*)task->zname + sizeof(struct nsdst));
stats_add(&xfrd->nsd->st, (struct nsdst*)task->zname);
for(i=0; i<xfrd->nsd->child_count; i++) {
xfrd->nsd->children[i].query_count += *p++;