nsd 4.1.27

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

nsd 4.1.27

Florian Obser-2
Nothing to extravagant, if you want this in 6.5
now would be a good time to test and report back :)

From the release announcement:

4.1.27
================
FEATURES:
- Deny ANY with only one RR in response, by default.  Patch from
  Daisuke Higashi.  The deny-any statement in nsd.conf sets ANY
  queries over UDP to be further moved to TCP as well.
  Also no additional section processig for type ANY, reducing
  the response size.
- Fix #4215: on-the-fly change of TSIG keys with patch from Igor, adds
  nsd-control print_tsig, update_tsig, add_tsig, assoc_tsig
  and del_tsig.  These changes are gone after reload, edit the
  config file (or a file included from it) to make changes that
  last after restart.
BUG FIXES:
- Fix #4213: disable-ipv6 and dnstap compile error.
- Fix to reduce region_log_stats if condition, this removes a
  debug statement.
- Fix for FreeBSD port with dnstap enabled.
- Fix to remove unused code.
- Fix #6: nsd-control-setup: Change validity time to a shorter
  period (<2038).
- Fix unused definition in header remote.h.
- Fix #4236: IPV4_MINIMAL_RESPONSE_SIZE=1480 is slightly too big.
- Fix #4235: IP_PMTUDISC_OMIT on IPv4/UDP sockets.
- Fixed radtree_insert memory leak.
- Fixed access recycled variable.

diff --git Makefile.in Makefile.in
index fbfc44be33b..0fba1027b88 100644
--- Makefile.in
+++ 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 config.h.in config.h.in
index 67296ca99b7..75c96b60b81 100644
--- config.h.in
+++ 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 configure configure
index 47736231022..88a1f1d8af5 100644
--- configure
+++ 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 <[hidden email]>.
 #
@@ -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='[hidden email]'
 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 configure.ac configure.ac
index 22e3e21e2ae..f2e384c8443 100644
--- configure.ac
+++ configure.ac
@@ -5,7 +5,7 @@ dnl
 sinclude(acx_nlnetlabs.m4)
 sinclude(dnstap/dnstap.m4)
 
-AC_INIT(NSD,4.1.26,[hidden email])
+AC_INIT(NSD,4.1.27,[hidden email])
 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 difffile.c difffile.c
index 4182db6bcff..b3aee0b4530 100644
--- difffile.c
+++ 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 dnstap/dnstap.c dnstap/dnstap.c
index fb724a8fc7c..8286441c2d8 100644
--- dnstap/dnstap.c
+++ 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 namedb.c namedb.c
index 4528b6e4f15..9ca5ffcbebb 100644
--- namedb.c
+++ 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 nsd-checkconf.8.in nsd-checkconf.8.in
index dccf95d690d..18d669750e5 100644
--- nsd-checkconf.8.in
+++ 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 nsd-checkzone.8.in nsd-checkzone.8.in
index afadb4c9215..b6e2499b1a6 100644
--- nsd-checkzone.8.in
+++ 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 nsd-control-setup.sh.in nsd-control-setup.sh.in
index b39c11ce722..705caefbe84 100644
--- nsd-control-setup.sh.in
+++ nsd-control-setup.sh.in
@@ -43,7 +43,7 @@ SERVERNAME=nsd
 CLIENTNAME=nsd-control
 
 # validity period for certificates
-DAYS=7200
+DAYS=3650
 
 # size of keys in bits
 BITS=3072
diff --git nsd-control.8.in nsd-control.8.in
index 40ca171c2c4..b6fe680b89b 100644
--- nsd-control.8.in
+++ 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 nsd-control.c nsd-control.c
index b83fc0c2fe3..efac9ac530d 100644
--- nsd-control.c
+++ 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 nsd.8.in nsd.8.in
index afb19cbfe66..1d58c5ad877 100644
--- nsd.8.in
+++ 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 nsd.c nsd.c
index 57bae3232d7..c773fc99d34 100644
--- nsd.c
+++ 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 nsd.conf.5.in nsd.conf.5.in
index 348fcda8fe3..a9c10213149 100644
--- nsd.conf.5.in
+++ 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 options.h options.h
index a83eb383e47..1d30156bbbe 100644
--- options.h
+++ 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 packet.h packet.h
index 8540dcfdf6a..097e9660f31 100644
--- packet.h
+++ 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 query.c query.c
index 48261d87404..e2a56e9aea0 100644
--- query.c
+++ 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 radtree.c radtree.c
index c3ac8661a73..873f0f8eba5 100644
--- radtree.c
+++ 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 region-allocator.c region-allocator.c
index 8b5d2c77989..638c861bdb3 100644
--- region-allocator.c
+++ 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 remote.c remote.c
index 5cc36489d37..147535f1a23 100644
--- remote.c
+++ 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 remote.h remote.h
index 0a8738ab4a9..fb8fd699a0f 100644
--- remote.h
+++ 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 server.c server.c
index edde352117b..ff2f62fff82 100644
--- server.c
+++ 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 udb.h udb.h
index 4cbe4031880..8d7ee137ad1 100644
--- udb.h
+++ 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;


--
I'm not entirely sure you are real.