summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/nsd/Makefile.in13
-rw-r--r--usr.sbin/nsd/config.h.in3
-rw-r--r--usr.sbin/nsd/configure85
-rw-r--r--usr.sbin/nsd/configure.ac3
-rw-r--r--usr.sbin/nsd/difffile.c1
-rw-r--r--usr.sbin/nsd/dnstap/dnstap.c2
-rw-r--r--usr.sbin/nsd/namedb.c5
-rw-r--r--usr.sbin/nsd/nsd-checkconf.8.in2
-rw-r--r--usr.sbin/nsd/nsd-checkzone.8.in2
-rw-r--r--usr.sbin/nsd/nsd-control-setup.sh.in24
-rw-r--r--usr.sbin/nsd/nsd-control.8.in27
-rw-r--r--usr.sbin/nsd/nsd-control.c5
-rw-r--r--usr.sbin/nsd/nsd.8.in4
-rw-r--r--usr.sbin/nsd/nsd.c4
-rw-r--r--usr.sbin/nsd/nsd.conf.5.in2
-rw-r--r--usr.sbin/nsd/options.h2
-rw-r--r--usr.sbin/nsd/packet.h2
-rw-r--r--usr.sbin/nsd/query.c12
-rw-r--r--usr.sbin/nsd/radtree.c5
-rw-r--r--usr.sbin/nsd/region-allocator.c4
-rw-r--r--usr.sbin/nsd/remote.c323
-rw-r--r--usr.sbin/nsd/remote.h1
-rw-r--r--usr.sbin/nsd/server.c56
-rw-r--r--usr.sbin/nsd/udb.h4
24 files changed, 535 insertions, 56 deletions
diff --git a/usr.sbin/nsd/Makefile.in b/usr.sbin/nsd/Makefile.in
index fbfc44be33b..0fba1027b88 100644
--- a/usr.sbin/nsd/Makefile.in
+++ b/usr.sbin/nsd/Makefile.in
@@ -310,7 +310,7 @@ configparser.c configparser.h: $(srcdir)/configparser.y
$(YACC) -d -o configparser.c $(srcdir)/configparser.y
# dnstap
-dnstap.o: $(srcdir)/dnstap/dnstap.c config.h \
+dnstap.o: $(srcdir)/dnstap/dnstap.c config.h dnstap/dnstap_config.h \
dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h $(srcdir)/dnstap/dnstap.h \
$(srcdir)/util.h $(srcdir)/options.h $(srcdir)/rbtree.h \
$(srcdir)/region-allocator.h
@@ -347,6 +347,9 @@ depend:
-e 's?$$(srcdir)/configlexer.c?configlexer.c?g' \
-e 's?$$(srcdir)/configparser.c?configparser.c?g' \
-e 's?$$(srcdir)/configparser.h?configparser.h?g' \
+ -e 's?$$(srcdir)/dnstap/dnstap_config.h??g' \
+ -e 's?$$(srcdir)/dnstap/dnstap.pb-c.c?dnstap/dnstap.pb-c.c?g' \
+ -e 's?$$(srcdir)/dnstap/dnstap.pb-c.h?dnstap/dnstap.pb-c.h?g' \
-e 's?$$(srcdir)/zlexer.c?zlexer.c?g' \
-e 's?$$(srcdir)/zparser.c?zparser.c?g' \
-e 's?$$(srcdir)/zparser.h?zparser.h?g' \
@@ -403,7 +406,8 @@ namedb.o: $(srcdir)/namedb.c config.h $(srcdir)/namedb.h $(srcdir)/dname.h $(src
$(srcdir)/util.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/rbtree.h $(srcdir)/nsec3.h
netio.o: $(srcdir)/netio.c config.h $(srcdir)/netio.h $(srcdir)/region-allocator.h $(srcdir)/util.h
nsd.o: $(srcdir)/nsd.c config.h $(srcdir)/nsd.h $(srcdir)/dns.h $(srcdir)/edns.h $(srcdir)/buffer.h $(srcdir)/region-allocator.h \
- $(srcdir)/util.h $(srcdir)/options.h $(srcdir)/rbtree.h $(srcdir)/tsig.h $(srcdir)/dname.h $(srcdir)/remote.h $(srcdir)/xfrd-disk.h
+ $(srcdir)/util.h $(srcdir)/options.h $(srcdir)/rbtree.h $(srcdir)/tsig.h $(srcdir)/dname.h $(srcdir)/remote.h $(srcdir)/xfrd-disk.h \
+ $(srcdir)/dnstap/dnstap_collector.h
nsd-checkconf.o: $(srcdir)/nsd-checkconf.c config.h $(srcdir)/tsig.h $(srcdir)/buffer.h \
$(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/dname.h $(srcdir)/options.h $(srcdir)/rbtree.h $(srcdir)/rrl.h $(srcdir)/query.h \
$(srcdir)/namedb.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/nsd.h $(srcdir)/edns.h $(srcdir)/packet.h
@@ -442,7 +446,8 @@ rrl.o: $(srcdir)/rrl.c config.h $(srcdir)/rrl.h $(srcdir)/query.h $(srcdir)/name
server.o: $(srcdir)/server.c config.h $(srcdir)/axfr.h $(srcdir)/nsd.h $(srcdir)/dns.h $(srcdir)/edns.h $(srcdir)/buffer.h \
$(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/query.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/radtree.h $(srcdir)/rbtree.h \
$(srcdir)/packet.h $(srcdir)/tsig.h $(srcdir)/netio.h $(srcdir)/xfrd.h $(srcdir)/options.h $(srcdir)/xfrd-tcp.h $(srcdir)/xfrd-disk.h \
- $(srcdir)/difffile.h $(srcdir)/udb.h $(srcdir)/nsec3.h $(srcdir)/ipc.h $(srcdir)/remote.h $(srcdir)/lookup3.h $(srcdir)/rrl.h
+ $(srcdir)/difffile.h $(srcdir)/udb.h $(srcdir)/nsec3.h $(srcdir)/ipc.h $(srcdir)/remote.h $(srcdir)/lookup3.h $(srcdir)/rrl.h \
+ $(srcdir)/dnstap/dnstap_collector.h
tsig.o: $(srcdir)/tsig.c config.h $(srcdir)/tsig.h $(srcdir)/buffer.h $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/dname.h \
$(srcdir)/tsig-openssl.h $(srcdir)/dns.h $(srcdir)/packet.h $(srcdir)/namedb.h $(srcdir)/radtree.h $(srcdir)/rbtree.h $(srcdir)/query.h $(srcdir)/nsd.h \
$(srcdir)/edns.h
@@ -458,7 +463,7 @@ util.o: $(srcdir)/util.c config.h $(srcdir)/util.h $(srcdir)/region-allocator.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 \
- $(srcdir)/difffile.h $(srcdir)/udb.h $(srcdir)/ipc.h $(srcdir)/remote.h $(srcdir)/rrl.h $(srcdir)/query.h
+ $(srcdir)/difffile.h $(srcdir)/udb.h $(srcdir)/ipc.h $(srcdir)/remote.h $(srcdir)/rrl.h $(srcdir)/query.h $(srcdir)/dnstap/dnstap_collector.h
xfrd-disk.o: $(srcdir)/xfrd-disk.c config.h $(srcdir)/xfrd-disk.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)/nsd.h $(srcdir)/edns.h
diff --git a/usr.sbin/nsd/config.h.in b/usr.sbin/nsd/config.h.in
index 67296ca99b7..75c96b60b81 100644
--- a/usr.sbin/nsd/config.h.in
+++ b/usr.sbin/nsd/config.h.in
@@ -178,6 +178,9 @@
/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
+/* Define to 1 if you have the <login_cap.h> header file. */
+#undef HAVE_LOGIN_CAP_H
+
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
diff --git a/usr.sbin/nsd/configure b/usr.sbin/nsd/configure
index 47736231022..88a1f1d8af5 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.1.26.
+# Generated by GNU Autoconf 2.69 for NSD 4.1.27.
#
# 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.1.26'
-PACKAGE_STRING='NSD 4.1.26'
+PACKAGE_VERSION='4.1.27'
+PACKAGE_STRING='NSD 4.1.27'
PACKAGE_BUGREPORT='nsd-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@@ -1296,7 +1296,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.1.26 to adapt to many kinds of systems.
+\`configure' configures NSD 4.1.27 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1357,7 +1357,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of NSD 4.1.26:";;
+ short | recursive ) echo "Configuration of NSD 4.1.27:";;
esac
cat <<\_ACEOF
@@ -1512,7 +1512,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-NSD configure 4.1.26
+NSD configure 4.1.27
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2221,7 +2221,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.1.26, which was
+It was created by NSD $as_me 4.1.27, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -8025,6 +8025,73 @@ _ACEOF
fi
done
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setusercontext" >&5
+$as_echo_n "checking for library containing setusercontext... " >&6; }
+if ${ac_cv_search_setusercontext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setusercontext ();
+int
+main ()
+{
+return setusercontext ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' util; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_setusercontext=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_setusercontext+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_setusercontext+:} false; then :
+
+else
+ ac_cv_search_setusercontext=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setusercontext" >&5
+$as_echo "$ac_cv_search_setusercontext" >&6; }
+ac_res=$ac_cv_search_setusercontext
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ for ac_header in login_cap.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "login_cap.h" "ac_cv_header_login_cap_h" "$ac_includes_default"
+if test "x$ac_cv_header_login_cap_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LOGIN_CAP_H 1
+_ACEOF
+
+fi
+
+done
+
+fi
+
for ac_func in 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
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
@@ -10127,7 +10194,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.1.26, which was
+This file was extended by NSD $as_me 4.1.27, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -10189,7 +10256,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.1.26
+NSD config.status 4.1.27
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 22e3e21e2ae..f2e384c8443 100644
--- a/usr.sbin/nsd/configure.ac
+++ b/usr.sbin/nsd/configure.ac
@@ -5,7 +5,7 @@ dnl
sinclude(acx_nlnetlabs.m4)
sinclude(dnstap/dnstap.m4)
-AC_INIT(NSD,4.1.26,nsd-bugs@nlnetlabs.nl)
+AC_INIT(NSD,4.1.27,nsd-bugs@nlnetlabs.nl)
AC_CONFIG_HEADER([config.h])
CFLAGS="$CFLAGS"
@@ -627,6 +627,7 @@ AC_SYS_LARGEFILE
AC_CHECK_SIZEOF(void*)
AC_CHECK_SIZEOF(off_t)
AC_CHECK_FUNCS([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])
AC_ARG_ENABLE(recvmmsg, AC_HELP_STRING([--enable-recvmmsg], [Enable recvmmsg and sendmmsg compilation, faster but some kernel versions may have implementation problems for IPv6]))
diff --git a/usr.sbin/nsd/difffile.c b/usr.sbin/nsd/difffile.c
index 4182db6bcff..b3aee0b4530 100644
--- a/usr.sbin/nsd/difffile.c
+++ b/usr.sbin/nsd/difffile.c
@@ -1381,6 +1381,7 @@ apply_ixfr_for_zone(nsd_type* nsd, zone_type* zonedb, FILE* in,
#endif /* NSEC3 */
zonedb->is_changed = 1;
if(nsd->db->udb) {
+ assert(z.base);
ZONE(&z)->is_changed = 1;
ZONE(&z)->mtime = time_end_0;
ZONE(&z)->mtime_nsec = time_end_1*1000;
diff --git a/usr.sbin/nsd/dnstap/dnstap.c b/usr.sbin/nsd/dnstap/dnstap.c
index fb724a8fc7c..8286441c2d8 100644
--- a/usr.sbin/nsd/dnstap/dnstap.c
+++ b/usr.sbin/nsd/dnstap/dnstap.c
@@ -319,7 +319,7 @@ dt_msg_fill_net(struct dt_msg *dm,
*has_port = 1;
} else if (ss->ss_family == AF_INET) {
#else
- if (ss->ss_family == AF_INET) {
+ if (ss->sin_family == AF_INET) {
#endif /* INET6 */
struct sockaddr_in *s = (struct sockaddr_in *) ss;
diff --git a/usr.sbin/nsd/namedb.c b/usr.sbin/nsd/namedb.c
index 4528b6e4f15..9ca5ffcbebb 100644
--- a/usr.sbin/nsd/namedb.c
+++ b/usr.sbin/nsd/namedb.c
@@ -278,11 +278,14 @@ do_deldomain(namedb_type* db, domain_type* domain)
void
domain_table_deldomain(namedb_type* db, domain_type* domain)
{
+ domain_type* parent;
+
while(domain_can_be_deleted(domain)) {
+ parent = domain->parent;
/* delete it */
do_deldomain(db, domain);
/* test parent */
- domain = domain->parent;
+ domain = parent;
}
}
diff --git a/usr.sbin/nsd/nsd-checkconf.8.in b/usr.sbin/nsd/nsd-checkconf.8.in
index dccf95d690d..18d669750e5 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 4, 2018" "NLnet Labs" "nsd 4.1.26"
+.TH "nsd\-checkconf" "8" "Mar 25, 2019" "NLnet Labs" "nsd 4.1.27"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
diff --git a/usr.sbin/nsd/nsd-checkzone.8.in b/usr.sbin/nsd/nsd-checkzone.8.in
index afadb4c9215..b6e2499b1a6 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 4, 2018" "NLnet Labs" "nsd 4.1.26"
+.TH "nsd\-checkzone" "8" "Mar 25, 2019" "NLnet Labs" "nsd 4.1.27"
.\" 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 394afb40c41..705caefbe84 100644
--- a/usr.sbin/nsd/nsd-control-setup.sh.in
+++ b/usr.sbin/nsd/nsd-control-setup.sh.in
@@ -22,16 +22,16 @@
# 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 A PARTICULAR
-# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# settings:
@@ -43,10 +43,10 @@ SERVERNAME=nsd
CLIENTNAME=nsd-control
# validity period for certificates
-DAYS=7200
+DAYS=3650
# size of keys in bits
-BITS=1536
+BITS=3072
# hash algorithm
HASH=sha256
diff --git a/usr.sbin/nsd/nsd-control.8.in b/usr.sbin/nsd/nsd-control.8.in
index 40ca171c2c4..b6fe680b89b 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 4, 2018" "NLnet Labs" "nsd 4.1.26"
+.TH "nsd\-control" "8" "Mar 25, 2019" "NLnet Labs" "nsd 4.1.27"
.\" Copyright (c) 2011, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
@@ -152,6 +152,31 @@ is also stable.
.TP
.B verbosity <number>
Change logging verbosity.
+.TP
+.B print_tsig [<key_name>]
+print the secret and algorithm for the TSIG key with that name.
+Or list all the tsig keys with their name, secret and algorithm.
+.TP
+.B update_tsig <name> <secret>
+Change existing TSIG key with name to the new secret. The secret is
+a base64 encoded string. The changes are only in-memory and are gone next
+restart, for lasting changes edit the nsd.conf file or a file included from it.
+.TP
+.B add_tsig <name> <secret> [algo]
+Add a new TSIG key with the given name, secret and algorithm. Without
+algorithm a default (hmac-sha256) algorithm is used. The secret is a
+base64 encoded string. The changes are only in-memory and are gone next
+restart, for lasting changes edit the nsd.conf file or a file included from it.
+.TP
+.B assoc_tsig <zone> <key_name>
+Associate the zone with the given tsig. The access control lists for
+notify, allow-notify, provide-xfr and request-xfr are adjusted to use the
+given key.
+.TP
+.B del_tsig <key_name>
+Delete the TSIG key with the given name. Prints error if the key is still
+in use by some zone. The changes are only in-memory and are gone next
+restart, for lasting changes edit the nsd.conf file or a file included from it.
.SH "EXIT CODE"
The nsd\-control program exits with status code 1 on error, 0 on success.
.SH "SET UP"
diff --git a/usr.sbin/nsd/nsd-control.c b/usr.sbin/nsd/nsd-control.c
index b83fc0c2fe3..efac9ac530d 100644
--- a/usr.sbin/nsd/nsd-control.c
+++ b/usr.sbin/nsd/nsd-control.c
@@ -101,6 +101,11 @@ usage()
printf(" zonestatus [<zone>] print state, serial, activity\n");
printf(" serverpid get pid of server process\n");
printf(" verbosity <number> change logging detail\n");
+ printf(" print_tsig [<key_name>] print tsig with <name> the secret and algo\n");
+ printf(" update_tsig <name> <secret> change existing tsig with <name> to a new <secret>\n");
+ printf(" add_tsig <name> <secret> [algo] add new key with the given parameters\n");
+ printf(" assoc_tsig <zone> <key_name> associate <zone> with given tsig <key_name> name\n");
+ printf(" del_tsig <key_name> delete tsig <key_name> from configuration\n");
exit(1);
}
diff --git a/usr.sbin/nsd/nsd.8.in b/usr.sbin/nsd/nsd.8.in
index afb19cbfe66..1d58c5ad877 100644
--- a/usr.sbin/nsd/nsd.8.in
+++ b/usr.sbin/nsd/nsd.8.in
@@ -1,9 +1,9 @@
-.TH "NSD" "8" "Dec 4, 2018" "NLnet Labs" "NSD 4.1.26"
+.TH "NSD" "8" "Mar 25, 2019" "NLnet Labs" "NSD 4.1.27"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
.B nsd
-\- Name Server Daemon (NSD) version 4.1.26.
+\- Name Server Daemon (NSD) version 4.1.27.
.SH "SYNOPSIS"
.B nsd
.RB [ \-4 ]
diff --git a/usr.sbin/nsd/nsd.c b/usr.sbin/nsd/nsd.c
index 57bae3232d7..c773fc99d34 100644
--- a/usr.sbin/nsd/nsd.c
+++ b/usr.sbin/nsd/nsd.c
@@ -21,7 +21,9 @@
#include <grp.h>
#endif /* HAVE_GRP_H */
#ifdef HAVE_SETUSERCONTEXT
+#ifdef HAVE_LOGIN_CAP_H
#include <login_cap.h>
+#endif /* HAVE_LOGIN_CAP_H */
#endif /* HAVE_SETUSERCONTEXT */
#include <assert.h>
@@ -952,7 +954,7 @@ main(int argc, char *argv[])
int fd;
/* Take off... */
- switch ((nsd.pid = fork())) {
+ switch (fork()) {
case 0:
/* Child */
break;
diff --git a/usr.sbin/nsd/nsd.conf.5.in b/usr.sbin/nsd/nsd.conf.5.in
index 348fcda8fe3..a9c10213149 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 4, 2018" "NLnet Labs" "nsd 4.1.26"
+.TH "nsd.conf" "5" "Mar 25, 2019" "NLnet Labs" "nsd 4.1.27"
.\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
.\" See LICENSE for the license.
.SH "NAME"
diff --git a/usr.sbin/nsd/options.h b/usr.sbin/nsd/options.h
index a83eb383e47..1d30156bbbe 100644
--- a/usr.sbin/nsd/options.h
+++ b/usr.sbin/nsd/options.h
@@ -337,6 +337,8 @@ struct key_options* key_options_find(struct nsd_options* opt, const char* name);
void key_options_remove(struct nsd_options* opt, const char* name);
int key_options_equal(struct key_options* p, struct key_options* q);
void key_options_add_modify(struct nsd_options* opt, struct key_options* key);
+void key_options_setup(region_type* region, struct key_options* key);
+void key_options_desetup(region_type* region, struct key_options* key);
/* read in zone list file. Returns false on failure */
int parse_zone_list_file(struct nsd_options* opt);
/* create zone entry and add to the zonelist file */
diff --git a/usr.sbin/nsd/packet.h b/usr.sbin/nsd/packet.h
index 8540dcfdf6a..097e9660f31 100644
--- a/usr.sbin/nsd/packet.h
+++ b/usr.sbin/nsd/packet.h
@@ -140,7 +140,7 @@ struct query;
#define MAXRRSPP 10240 /* Maximum number of rr's per packet */
#define MAX_COMPRESSED_DNAMES MAXRRSPP /* Maximum number of compressed domains. */
#define MAX_COMPRESSION_OFFSET 16383 /* Compression pointers are 14 bit. */
-#define IPV4_MINIMAL_RESPONSE_SIZE 1480 /* Recommended minimal edns size for IPv4 */
+#define IPV4_MINIMAL_RESPONSE_SIZE 1460 /* Recommended minimal edns size for IPv4 */
#define IPV6_MINIMAL_RESPONSE_SIZE 1220 /* Recommended minimal edns size for IPv6 */
/* use round robin rotation */
diff --git a/usr.sbin/nsd/query.c b/usr.sbin/nsd/query.c
index 48261d87404..e2a56e9aea0 100644
--- a/usr.sbin/nsd/query.c
+++ b/usr.sbin/nsd/query.c
@@ -693,7 +693,8 @@ answer_needs_ns(struct query* query)
assert(query);
/* Currently, only troublesome for DNSKEY and DS,
* cuz their RRSETs are quite large. */
- return (query->qtype != TYPE_DNSKEY && query->qtype != TYPE_DS);
+ return (query->qtype != TYPE_DNSKEY && query->qtype != TYPE_DS
+ && query->qtype != TYPE_ANY);
}
static int
@@ -969,6 +970,9 @@ answer_domain(struct nsd* nsd, struct query *q, answer_type *answer,
{
add_rrset(q, answer, ANSWER_SECTION, domain, rrset);
++added;
+ /* minimize response size with one RR,
+ * according to RFC 8482(4.1). */
+ break;
}
}
if (added == 0) {
@@ -1182,8 +1186,10 @@ answer_authoritative(struct nsd *nsd,
* No match and no wildcard. Include NSEC
* proving there is no wildcard.
*/
- nsec_domain = find_covering_nsec(closest_encloser->wildcard_child_closest_match, q->zone, &nsec_rrset);
- if (nsec_domain) {
+ if(closest_encloser && (nsec_domain =
+ find_covering_nsec(closest_encloser->
+ wildcard_child_closest_match, q->zone,
+ &nsec_rrset)) != NULL) {
add_rrset(q, answer, AUTHORITY_SECTION, nsec_domain, nsec_rrset);
}
}
diff --git a/usr.sbin/nsd/radtree.c b/usr.sbin/nsd/radtree.c
index c3ac8661a73..873f0f8eba5 100644
--- a/usr.sbin/nsd/radtree.c
+++ b/usr.sbin/nsd/radtree.c
@@ -510,7 +510,10 @@ struct radnode* radix_insert(struct radtree* rt, uint8_t* k,
/* add a root to point to new node */
n = (struct radnode*)region_alloc_zero(rt->region,
sizeof(*n));
- if(!n) return NULL;
+ if(!n) {
+ region_recycle(rt->region, add, sizeof(*add));
+ return NULL;
+ }
if(!radnode_array_space(rt->region, n, k[0])) {
region_recycle(rt->region, n->array,
n->capacity*sizeof(struct radsel));
diff --git a/usr.sbin/nsd/region-allocator.c b/usr.sbin/nsd/region-allocator.c
index 8b5d2c77989..638c861bdb3 100644
--- a/usr.sbin/nsd/region-allocator.c
+++ b/usr.sbin/nsd/region-allocator.c
@@ -491,7 +491,7 @@ region_dump_stats(region_type *region, FILE *out)
(unsigned long) region->chunk_count,
(unsigned long) region->cleanup_count,
(unsigned long) region->recycle_size);
- if(1 && region->recycle_bin) {
+ if(region->recycle_bin) {
/* print details of the recycle bin */
size_t i;
for(i=0; i<region->large_object_size; i++) {
@@ -541,7 +541,7 @@ region_log_stats(region_type *region)
len = strlen(str);
str+=len;
strl-=len;
- if(1 && region->recycle_bin) {
+ if(region->recycle_bin) {
/* print details of the recycle bin */
size_t i;
for(i=0; i<region->large_object_size; i++) {
diff --git a/usr.sbin/nsd/remote.c b/usr.sbin/nsd/remote.c
index 5cc36489d37..147535f1a23 100644
--- a/usr.sbin/nsd/remote.c
+++ b/usr.sbin/nsd/remote.c
@@ -743,12 +743,22 @@ state_list_remove_elem(struct rc_state** list, struct rc_state* todel)
static void
stats_list_remove_elem(struct rc_state** list, struct rc_state* todel)
{
- while(*list) {
- if( (*list) == todel) {
- *list = (*list)->stats_next;
- return;
+ struct rc_state* prev = NULL;
+ struct rc_state* n = *list;
+ while(n) {
+ /* delete this one? */
+ if(n == todel) {
+ if(prev) prev->next = n->next;
+ else (*list) = n->next;
+ /* go on and delete further elements */
+ /* prev = prev; */
+ n = n->next;
+ continue;
}
- list = &(*list)->stats_next;
+
+ /* go to the next element */
+ prev = n;
+ n = n->next;
}
}
@@ -1191,11 +1201,35 @@ find_arg2(RES* ssl, char* arg, char** arg2)
as[0]=0;
return 1;
}
+ *arg2 = NULL;
ssl_printf(ssl, "error could not find next argument "
"after %s\n", arg);
return 0;
}
+/** find second and third arguments, modifies string,
+ * does not print error for missing arg3 so that if it does not find an
+ * arg3, the caller can use two arguments. */
+static int
+find_arg3(RES* ssl, char* arg, char** arg2, char** arg3)
+{
+ if(find_arg2(ssl, arg, arg2)) {
+ char* as;
+ *arg3 = *arg2;
+ as = strrchr(arg, ' ');
+ if(as) {
+ as[0]=0;
+ *arg2 = as+1;
+ while(isspace((unsigned char)*as) && as > arg)
+ as--;
+ as[0]=0;
+ return 1;
+ }
+ }
+ *arg3 = NULL;
+ return 0;
+}
+
/** do the status command */
static void
do_status(RES* ssl, xfrd_state_type* xfrd)
@@ -1930,6 +1964,275 @@ do_serverpid(RES* ssl, xfrd_state_type* xfrd)
(void)ssl_printf(ssl, "%u\n", (unsigned)xfrd->reload_pid);
}
+/** do the print_tsig command: printout tsig info */
+static void
+do_print_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
+{
+ if(*arg == '\0') {
+ struct key_options* key;
+ RBTREE_FOR(key, struct key_options*, xfrd->nsd->options->keys) {
+ if(!ssl_printf(ssl, "key: name: \"%s\" secret: \"%s\" algorithm: %s\n", key->name, key->secret, key->algorithm))
+ return;
+ }
+ return;
+ } 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;
+ return;
+ } else {
+ if(!ssl_printf(ssl, "key: name: \"%s\" secret: \"%s\" algorithm: %s\n", arg, key_opts->secret, key_opts->algorithm))
+ return;
+ }
+ }
+}
+
+/** do the update_tsig command: change existing tsig to new secret */
+static void
+do_update_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
+{
+ struct region* region = xfrd->nsd->options->region;
+ char* arg2 = NULL;
+ uint8_t data[65536]; /* 64K */
+ struct key_options* key_opt;
+
+ if(*arg == '\0') {
+ if(!ssl_printf(ssl, "error: missing argument (keyname)\n"))
+ return;
+ return;
+ }
+ if(!find_arg2(ssl, arg, &arg2)) {
+ if(!ssl_printf(ssl, "error: missing argument (secret)\n"))
+ return;
+ 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;
+ 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;
+ memset(data, 0xdd, sizeof(data)); /* wipe secret */
+ memset(arg2, 0xdd, strlen(arg2));
+ return;
+ }
+ log_msg(LOG_INFO, "changing secret provided with the key: %s with old secret %s and algo: %s\n", arg, key_opt->secret, key_opt->algorithm);
+ if(key_opt->secret) {
+ /* wipe old secret */
+ memset(key_opt->secret, 0xdd, strlen(key_opt->secret));
+ region_recycle(region, key_opt->secret,
+ strlen(key_opt->secret)+1);
+ }
+ key_opt->secret = region_strdup(region, arg2);
+ log_msg(LOG_INFO, "the key: %s has new secret %s and algorithm: %s\n", arg, key_opt->secret, key_opt->algorithm);
+ /* wipe secret from temp parse buffer */
+ memset(arg2, 0xdd, strlen(arg2));
+ memset(data, 0xdd, sizeof(data));
+
+ key_options_desetup(region, key_opt);
+ key_options_setup(region, key_opt);
+ task_new_add_key(xfrd->nsd->task[xfrd->nsd->mytask], xfrd->last_task,
+ key_opt);
+ xfrd_set_reload_now(xfrd);
+
+ send_ok(ssl);
+}
+
+/** do the add tsig command, add new key with name, secret and algo given */
+static void
+do_add_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
+{
+ char* arg2 = NULL;
+ char* arg3 = NULL;
+ uint8_t data[65536]; /* 64KB */
+ uint8_t dname[MAXDOMAINLEN+1];
+ char algo[256];
+ region_type* region = xfrd->nsd->options->region;
+ struct key_options* new_key_opt;
+
+ if(*arg == '\0') {
+ if(!ssl_printf(ssl, "error: missing argument (keyname)\n"))
+ return;
+ return;
+ }
+ if(!find_arg3(ssl, arg, &arg2, &arg3)) {
+ strlcpy(algo, "hmac-sha256", sizeof(algo));
+ } else {
+ strlcpy(algo, arg3, sizeof(algo));
+ }
+ if(!arg2) {
+ if(!ssl_printf(ssl, "error: missing argument (secret)\n"))
+ return;
+ return;
+ }
+ if(key_options_find(xfrd->nsd->options, arg)) {
+ if(!ssl_printf(ssl, "error: key %s already exists\n", arg))
+ return;
+ 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;
+ 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;
+ 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;
+ memset(arg2, 0xdd, strlen(arg2));
+ return;
+ }
+ log_msg(LOG_INFO, "adding key with name: %s and secret: %s with algo: %s\n", arg, arg2, algo);
+ new_key_opt = key_options_create(region);
+ new_key_opt->name = region_strdup(region, arg);
+ new_key_opt->secret = region_strdup(region, arg2);
+ new_key_opt->algorithm = region_strdup(region, algo);
+ add_key(xfrd, new_key_opt);
+
+ /* wipe secret from temp buffer */
+ memset(arg2, 0xdd, strlen(arg2));
+ send_ok(ssl);
+}
+
+/** set acl entries to use the given TSIG key */
+static void
+zopt_set_acl_to_tsig(struct acl_options* acl, struct region* region,
+ const char* key_name, struct key_options* key_opt)
+{
+ while(acl) {
+ if(acl->blocked) {
+ acl = acl->next;
+ continue;
+ }
+ acl->nokey = 0;
+ if(acl->key_name)
+ region_recycle(region, (void*)acl->key_name,
+ strlen(acl->key_name)+1);
+ acl->key_name = region_strdup(region, key_name);
+ acl->key_options = key_opt;
+ acl = acl->next;
+ }
+}
+
+/** do the assoc_tsig command: associate the zone to use the tsig name */
+static void
+do_assoc_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg)
+{
+ region_type* region = xfrd->nsd->options->region;
+ char* arg2 = NULL;
+ struct zone_options* zone;
+ struct key_options* key_opt;
+
+ if(*arg == '\0') {
+ if(!ssl_printf(ssl, "error: missing argument (zonename)\n"))
+ return;
+ return;
+ }
+ if(!find_arg2(ssl, arg, &arg2)) {
+ if(!ssl_printf(ssl, "error: missing argument (keyname)\n"))
+ return;
+ return;
+ }
+
+ if(!get_zone_arg(ssl, xfrd, arg, &zone))
+ return;
+ if(!zone) {
+ if(!ssl_printf(ssl, "error: missing argument (zone)\n"))
+ return;
+ 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;
+ return;
+ }
+
+ zopt_set_acl_to_tsig(zone->pattern->allow_notify, region, arg2,
+ key_opt);
+ zopt_set_acl_to_tsig(zone->pattern->notify, region, arg2, key_opt);
+ zopt_set_acl_to_tsig(zone->pattern->request_xfr, region, arg2,
+ key_opt);
+ zopt_set_acl_to_tsig(zone->pattern->provide_xfr, region, arg2,
+ key_opt);
+
+ task_new_add_pattern(xfrd->nsd->task[xfrd->nsd->mytask],
+ xfrd->last_task, zone->pattern);
+ xfrd_set_reload_now(xfrd);
+
+ send_ok(ssl);
+}
+
+/** see if TSIG key is used in the acl */
+static int
+acl_contains_tsig_key(struct acl_options* acl, const char* name)
+{
+ while(acl) {
+ if(acl->key_name && strcmp(acl->key_name, name) == 0)
+ return 1;
+ acl = acl->next;
+ }
+ return 0;
+}
+
+/** do the del_tsig command, remove an (unused) tsig */
+static void
+do_del_tsig(RES* ssl, xfrd_state_type* xfrd, char* arg) {
+ int used_key = 0;
+ struct zone_options* zone;
+ struct key_options* key_opt;
+
+ if(*arg == '\0') {
+ if(!ssl_printf(ssl, "error: missing argument (keyname)\n"))
+ return;
+ 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;
+ return;
+ }
+ RBTREE_FOR(zone, struct zone_options*, xfrd->nsd->options->zone_options)
+ {
+ if(acl_contains_tsig_key(zone->pattern->allow_notify, arg) ||
+ acl_contains_tsig_key(zone->pattern->notify, arg) ||
+ acl_contains_tsig_key(zone->pattern->request_xfr, arg) ||
+ acl_contains_tsig_key(zone->pattern->provide_xfr, arg)) {
+ if(!ssl_printf(ssl, "zone %s uses key %s\n",
+ zone->name, arg))
+ return;
+ used_key = 1;
+ break;
+ }
+ }
+
+ if(used_key) {
+ if(!ssl_printf(ssl, "error: key: %s is in use and cannot be deleted\n", arg))
+ return;
+ return;
+ } else {
+ remove_key(xfrd, arg);
+ log_msg(LOG_INFO, "key: %s is successfully deleted\n", arg);
+ }
+
+ send_ok(ssl);
+}
+
/** check for name with end-of-string, space or tab after it */
static int
cmdcmp(char* p, const char* cmd, size_t len)
@@ -1983,6 +2286,16 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd, struct rc_state* rs)
do_repattern(ssl, rc->xfrd);
} else if(cmdcmp(p, "serverpid", 9)) {
do_serverpid(ssl, rc->xfrd);
+ } else if(cmdcmp(p, "print_tsig", 10)) {
+ do_print_tsig(ssl, rc->xfrd, skipwhite(p+10));
+ } else if(cmdcmp(p, "update_tsig", 11)) {
+ do_update_tsig(ssl, rc->xfrd, skipwhite(p+11));
+ } else if(cmdcmp(p, "add_tsig", 8)) {
+ do_add_tsig(ssl, rc->xfrd, skipwhite(p+8));
+ } else if(cmdcmp(p, "assoc_tsig", 10)) {
+ do_assoc_tsig(ssl, rc->xfrd, skipwhite(p+10));
+ } else if(cmdcmp(p, "del_tsig", 8)) {
+ do_del_tsig(ssl, rc->xfrd, skipwhite(p+8));
} else {
(void)ssl_printf(ssl, "error unknown command '%s'\n", p);
}
diff --git a/usr.sbin/nsd/remote.h b/usr.sbin/nsd/remote.h
index 0a8738ab4a9..fb8fd699a0f 100644
--- a/usr.sbin/nsd/remote.h
+++ b/usr.sbin/nsd/remote.h
@@ -50,7 +50,6 @@ struct nsd_options;
/* private, defined in remote.c to keep ssl.h out of this header */
struct daemon_remote;
-struct rc_state;
/* the remote control needs less backlog than the tcp53 service */
#define TCP_BACKLOG_REMOTE 16 /* listen() tcp backlog */
diff --git a/usr.sbin/nsd/server.c b/usr.sbin/nsd/server.c
index edde352117b..ff2f62fff82 100644
--- a/usr.sbin/nsd/server.c
+++ b/usr.sbin/nsd/server.c
@@ -740,13 +740,55 @@ server_init_ifs(struct nsd *nsd, size_t from, size_t to, int* reuseport_works)
#endif
#if defined(AF_INET)
if (addr->ai_family == AF_INET) {
-# if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
- int action = IP_PMTUDISC_DONT;
- if (setsockopt(nsd->udp[i].s, IPPROTO_IP,
- IP_MTU_DISCOVER, &action, sizeof(action)) < 0)
- {
- log_msg(LOG_ERR, "setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_DONT...) failed: %s",
- strerror(errno));
+# if defined(IP_MTU_DISCOVER)
+ int mtudisc_disabled = 0;
+# if defined(IP_PMTUDISC_OMIT)
+ /* Try IP_PMTUDISC_OMIT first */
+
+ /*
+ * Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets
+ * ignore PMTU information and send packets with DF=0.
+ * Fragmentation is allowed if and only if the packet
+ * size exceeds the outgoing interface MTU or the packet
+ * encounters smaller MTU link in network.
+ * This mitigates DNS fragmentation attacks by preventing
+ * forged PMTU information.
+ * FreeBSD already has same semantics without setting
+ * the option.
+ */
+ int action_omit = IP_PMTUDISC_OMIT;
+ if (!mtudisc_disabled) {
+ if(setsockopt(nsd->udp[i].s, IPPROTO_IP,
+ IP_MTU_DISCOVER, &action_omit,
+ sizeof(action_omit)) < 0)
+ {
+ log_msg(LOG_ERR, "setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_OMIT...) failed: %s",
+ strerror(errno));
+ } else {
+ mtudisc_disabled = 1;
+ }
+ }
+# endif /* IP_PMTUDISC_OMIT */
+# if defined(IP_PMTUDISC_DONT)
+ /*
+ * Use IP_PMTUDISC_DONT
+ * if IP_PMTUDISC_OMIT failed / undefined
+ */
+ if (!mtudisc_disabled) {
+ int action_dont = IP_PMTUDISC_DONT;
+ if (setsockopt(nsd->udp[i].s, IPPROTO_IP,
+ IP_MTU_DISCOVER, &action_dont,
+ sizeof(action_dont)) < 0)
+ {
+ log_msg(LOG_ERR, "setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_DONT...) failed: %s",
+ strerror(errno));
+ } else {
+ mtudisc_disabled = 1;
+ }
+ }
+# endif /* IP_PMTUDISC_DONT */
+ /* exit if all methods to disable PMTUD failed */
+ if(!mtudisc_disabled) {
return -1;
}
# elif defined(IP_DONTFRAG)
diff --git a/usr.sbin/nsd/udb.h b/usr.sbin/nsd/udb.h
index 4cbe4031880..8d7ee137ad1 100644
--- a/usr.sbin/nsd/udb.h
+++ b/usr.sbin/nsd/udb.h
@@ -165,7 +165,9 @@ struct udb_glob_d {
volatile uint64_t rb_size;
/** segment of move rollback, for an XL chunk that overlaps. */
volatile uint64_t rb_seg;
- /** linked list for content-listing, 0 if empty */
+ /** linked list for content-listing, 0 if empty;
+ * this pointer is unused; and could be removed if the database
+ * format is modified or updated. */
udb_rel_ptr content_list;
/** user global data pointer */
udb_rel_ptr user_global;