Lightly tested, I will test AXFR with tsig tomorrow.

tests / OKs?

diff --git Makefile.in Makefile.in
index 9103291..3fbd01b 100644
--- Makefile.in
+++ Makefile.in
@@ -439,9 +439,9 @@ xfrd-disk.o: $(srcdir)/xfrd-disk.c config.h 
$(srcdir)/xfrd-disk.h $(srcdir)/xfrd
 xfrd-notify.o: $(srcdir)/xfrd-notify.c config.h $(srcdir)/xfrd-notify.h 
$(srcdir)/tsig.h $(srcdir)/buffer.h \
  $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/dname.h 
$(srcdir)/rbtree.h $(srcdir)/xfrd.h $(srcdir)/namedb.h $(srcdir)/dns.h \
  $(srcdir)/radtree.h $(srcdir)/options.h $(srcdir)/xfrd-tcp.h 
$(srcdir)/packet.h
-xfrd-tcp.o: $(srcdir)/xfrd-tcp.c config.h $(srcdir)/xfrd-tcp.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)/packet.h $(srcdir)/xfrd-disk.h
+xfrd-tcp.o: $(srcdir)/xfrd-tcp.c config.h $(srcdir)/nsd.h $(srcdir)/dns.h 
$(srcdir)/edns.h $(srcdir)/buffer.h \
+ $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/xfrd-tcp.h 
$(srcdir)/xfrd.h $(srcdir)/rbtree.h $(srcdir)/namedb.h $(srcdir)/dname.h \
+ $(srcdir)/radtree.h $(srcdir)/options.h $(srcdir)/tsig.h $(srcdir)/packet.h 
$(srcdir)/xfrd-disk.h
 zlexer.o: zlexer.c config.h $(srcdir)/zonec.h $(srcdir)/namedb.h 
$(srcdir)/dname.h $(srcdir)/buffer.h \
  $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/dns.h 
$(srcdir)/radtree.h $(srcdir)/rbtree.h zparser.h
 zonec.o: $(srcdir)/zonec.c config.h $(srcdir)/zonec.h $(srcdir)/namedb.h 
$(srcdir)/dname.h $(srcdir)/buffer.h \
diff --git acx_nlnetlabs.m4 acx_nlnetlabs.m4
index 26513e4..a6c174f 100644
--- acx_nlnetlabs.m4
+++ acx_nlnetlabs.m4
@@ -2,7 +2,11 @@
 # Copyright 2009, Wouter Wijngaards, NLnet Labs.   
 # BSD licensed.
 #
-# Version 30
+# Version 34
+# 2016-03-21 Check -ldl -pthread for libcrypto for ldns and openssl 1.1.0.
+# 2016-03-21 Use HMAC_Update instead of HMAC_CTX_Init (for openssl-1.1.0).
+# 2016-01-04 -D_DEFAULT_SOURCE defined with -D_BSD_SOURCE for Linux glibc 2.20
+# 2015-12-11 FLTO check for new OSX, clang.
 # 2015-11-18 spelling check fix.
 # 2015-11-05 ACX_SSL_CHECKS no longer adds -ldl needlessly.
 # 2015-08-28 ACX_CHECK_PIE and ACX_CHECK_RELRO_NOW added.
@@ -241,7 +245,7 @@ ACX_CHECK_COMPILER_FLAG(xc99, [C99FLAG="-xc99"])
 
 AC_CHECK_HEADERS([getopt.h time.h],,, [AC_INCLUDES_DEFAULT])
 
-ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE 
-D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 
-D_ALL_SOURCE,
+ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE 
-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 
-D_XOPEN_SOURCE_EXTENDED=1 -D_ALL_SOURCE,
 [
 #include "confdefs.h"
 #include <stdlib.h>
@@ -276,9 +280,9 @@ int test() {
                a = 0;
        return a;
 }
-], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE 
-D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 
-D_ALL_SOURCE"])
+], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAULT_SOURCE 
-D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 
-D_ALL_SOURCE"])
 
-ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE 
-D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE,
+ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE 
-D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE,
 [
 #include "confdefs.h"
 #include <stdlib.h>
@@ -313,7 +317,7 @@ int test() {
                a = 0;
        return a;
 }
-], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE 
-D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"])
+], [CFLAGS="$CFLAGS $C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAULT_SOURCE 
-D_POSIX_C_SOURCE=200112 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE"])
 
 ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG,
 [
@@ -325,7 +329,7 @@ int test() {
 }
 ], [CFLAGS="$CFLAGS $C99FLAG"])
 
-ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE,
+ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE -D_DEFAULT_SOURCE,
 [
 #include <ctype.h>
 
@@ -334,7 +338,7 @@ int test() {
         a = isascii(32);
         return a;
 }
-], [CFLAGS="$CFLAGS -D_BSD_SOURCE"])
+], [CFLAGS="$CFLAGS -D_BSD_SOURCE -D_DEFAULT_SOURCE"])
 
 ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE,
 [
@@ -423,7 +427,7 @@ AC_DEFUN([ACX_CHECK_FLTO], [
         BAKCFLAGS="$CFLAGS"
         CFLAGS="$CFLAGS -flto"
         AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [
-            if $CC $CFLAGS -o conftest conftest.c 2>&1 | grep "warning: no 
debug symbols in executable" >/dev/null; then
+            if $CC $CFLAGS -o conftest conftest.c 2>&1 | $GREP -e "warning: no 
debug symbols in executable" -e "warning: object" >/dev/null; then
                 CFLAGS="$BAKCFLAGS"
                 AC_MSG_RESULT(no)
             else
@@ -669,16 +673,16 @@ AC_DEFUN([ACX_SSL_CHECKS], [
                 ACX_RUNTIME_PATH_ADD([$ssldir/lib])
             fi
         
-            AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
+            AC_MSG_CHECKING([for HMAC_Update in -lcrypto])
             LIBS="$LIBS -lcrypto"
             LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
             AC_TRY_LINK(, [
-                int HMAC_CTX_init(void);
-                (void)HMAC_CTX_init();
+                int HMAC_Update(void);
+                (void)HMAC_Update();
               ], [
                 AC_MSG_RESULT(yes)
-                AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, 
-                          [If you have HMAC_CTX_init])
+                AC_DEFINE([HAVE_HMAC_UPDATE], 1, 
+                          [If you have HMAC_Update])
               ], [
                 AC_MSG_RESULT(no)
                 # check if -lwsock32 or -lgdi32 are needed.    
@@ -688,11 +692,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [
                 LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
                 AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
                 AC_TRY_LINK([], [
-                    int HMAC_CTX_init(void);
-                    (void)HMAC_CTX_init();
+                    int HMAC_Update(void);
+                    (void)HMAC_Update();
                   ],[
-                    AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, 
-                        [If you have HMAC_CTX_init])
+                    AC_DEFINE([HAVE_HMAC_UPDATE], 1, 
+                        [If you have HMAC_Update])
                     AC_MSG_RESULT(yes) 
                   ],[
                     AC_MSG_RESULT(no)
@@ -702,15 +706,30 @@ AC_DEFUN([ACX_SSL_CHECKS], [
                     LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
                     AC_MSG_CHECKING([if -lcrypto needs -ldl])
                     AC_TRY_LINK([], [
-                        int HMAC_CTX_init(void);
-                        (void)HMAC_CTX_init();
+                        int HMAC_Update(void);
+                        (void)HMAC_Update();
                       ],[
-                        AC_DEFINE([HAVE_HMAC_CTX_INIT], 1, 
-                            [If you have HMAC_CTX_init])
+                        AC_DEFINE([HAVE_HMAC_UPDATE], 1, 
+                            [If you have HMAC_Update])
                         AC_MSG_RESULT(yes) 
                       ],[
                         AC_MSG_RESULT(no)
-                    AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 
or higher is required])
+                        LIBS="$BAKLIBS"
+                        LIBSSL_LIBS="$BAKSSLLIBS"
+                        LIBS="$LIBS -ldl -pthread"
+                        LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
+                        AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
+                        AC_TRY_LINK([], [
+                            int HMAC_Update(void);
+                            (void)HMAC_Update();
+                          ],[
+                            AC_DEFINE([HAVE_HMAC_UPDATE], 1, 
+                                [If you have HMAC_Update])
+                            AC_MSG_RESULT(yes) 
+                          ],[
+                            AC_MSG_RESULT(no)
+                            AC_MSG_ERROR([OpenSSL found in $ssldir, but 
version 0.9.7 or higher is required])
+                       ])
                     ])
                 ])
             ])
@@ -1284,6 +1303,7 @@ AC_DEFUN([ACX_STRIP_EXT_FLAGS],
   AC_MSG_NOTICE([Stripping extension flags...])
   ACX_CFLAGS_STRIP(-D_GNU_SOURCE)
   ACX_CFLAGS_STRIP(-D_BSD_SOURCE)
+  ACX_CFLAGS_STRIP(-D_DEFAULT_SOURCE)
   ACX_CFLAGS_STRIP(-D__EXTENSIONS__)
   ACX_CFLAGS_STRIP(-D_POSIX_C_SOURCE=200112)
   ACX_CFLAGS_STRIP(-D_XOPEN_SOURCE=600)
@@ -1311,6 +1331,7 @@ dnl config.h part to define omitted cflags, use with 
ACX_STRIP_EXT_FLAGS.
 AC_DEFUN([AHX_CONFIG_EXT_FLAGS],
 [AHX_CONFIG_FLAG_EXT(-D_GNU_SOURCE)
 AHX_CONFIG_FLAG_EXT(-D_BSD_SOURCE)
+AHX_CONFIG_FLAG_EXT(-D_DEFAULT_SOURCE)
 AHX_CONFIG_FLAG_EXT(-D__EXTENSIONS__)
 AHX_CONFIG_FLAG_EXT(-D_POSIX_C_SOURCE=200112)
 AHX_CONFIG_FLAG_EXT(-D_XOPEN_SOURCE=600)
diff --git answer.c answer.c
index be43c4c..c7b86fb 100644
--- answer.c
+++ answer.c
@@ -95,6 +95,11 @@ encode_answer(query_type *q, const answer_type *answer)
                 * sections.
                 */
                if (done) {
+                       /* delegations should have a usable address in it */
+                       if(section == ADDITIONAL_A_SECTION &&
+                               counts[ADDITIONAL_A_SECTION] == 0 &&
+                               q->delegation_domain)
+                               TC_SET(q->packet);
                        break;
                }
 #endif
diff --git axfr.c axfr.c
index f7e0caa..09eb082 100644
--- axfr.c
+++ axfr.c
@@ -95,9 +95,10 @@ query_axfr(struct nsd *nsd, struct query *query)
        }
 
        /* Add zone RRs until answer is full.  */
-       assert(query->axfr_current_domain);
-
-       do {
+       while (query->axfr_current_domain != NULL &&
+                       domain_is_subdomain(query->axfr_current_domain,
+                                           query->axfr_zone->apex))
+       {
                if (!query->axfr_current_rrset) {
                        query->axfr_current_rrset = domain_find_any_rrset(
                                query->axfr_current_domain,
@@ -128,9 +129,6 @@ query_axfr(struct nsd *nsd, struct query *query)
                query->axfr_current_domain
                        = domain_next(query->axfr_current_domain);
        }
-       while (query->axfr_current_domain != NULL &&
-                       domain_is_subdomain(query->axfr_current_domain,
-                                           query->axfr_zone->apex));
 
        /* Add terminating SOA RR.  */
        assert(query->axfr_zone->soa_rrset->rr_count == 1);
diff --git config.h.in config.h.in
index 2a2e5b6..8a3f47f 100644
--- config.h.in
+++ config.h.in
@@ -58,6 +58,9 @@
 /* Define to 1 if you have the `chroot' function. */
 #undef HAVE_CHROOT
 
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
 /* if time.h provides ctime_r prototype */
 #undef HAVE_CTIME_R_PROTO
 
@@ -127,6 +130,12 @@
 /* Define to 1 if you have the <grp.h> header file. */
 #undef HAVE_GRP_H
 
+/* Define to 1 if you have the `HMAC_CTX_new' function. */
+#undef HAVE_HMAC_CTX_NEW
+
+/* Define to 1 if you have the `HMAC_CTX_reset' function. */
+#undef HAVE_HMAC_CTX_RESET
+
 /* Define to 1 if you have the `inet_aton' function. */
 #undef HAVE_INET_ATON
 
@@ -179,6 +188,9 @@
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #undef HAVE_NETINET_IN_H
 
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
 /* Define to 1 if you have the <openssl/err.h> header file. */
 #undef HAVE_OPENSSL_ERR_H
 
@@ -290,6 +302,12 @@
 /* Define to 1 if you have the `strtol' function. */
 #undef HAVE_STRTOL
 
+/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
+
+/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+
 /* If time.h has a struct timespec (for pselect). */
 #undef HAVE_STRUCT_TIMESPEC
 
@@ -625,6 +643,9 @@
 #  ifndef _BSD_SOURCE
 #    define _BSD_SOURCE 1
 #  endif
+#  ifndef _DEFAULT_SOURCE
+#    define _DEFAULT_SOURCE 1
+#  endif
 #  ifndef __EXTENSIONS__
 #    define __EXTENSIONS__ 1
 #  endif 
@@ -669,6 +690,10 @@
 #include <netinet/in.h>
 #endif
 
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
diff --git configlexer.lex configlexer.lex
index 20304b7..113fa22 100644
--- configlexer.lex
+++ configlexer.lex
@@ -199,6 +199,7 @@ name{COLON}         { LEXOUT(("v(%s) ", yytext)); return 
VAR_NAME;}
 ip-address{COLON}      { LEXOUT(("v(%s) ", yytext)); return VAR_IP_ADDRESS;}
 interface{COLON}       { LEXOUT(("v(%s) ", yytext)); return VAR_IP_ADDRESS;}
 ip-transparent{COLON}  { LEXOUT(("v(%s) ", yytext)); return 
VAR_IP_TRANSPARENT;}
+ip-freebind{COLON}     { LEXOUT(("v(%s) ", yytext)); return VAR_IP_FREEBIND;}
 debug-mode{COLON}      { LEXOUT(("v(%s) ", yytext)); return VAR_DEBUG_MODE;}
 hide-version{COLON}    { LEXOUT(("v(%s) ", yytext)); return VAR_HIDE_VERSION;}
 ip4-only{COLON}                { LEXOUT(("v(%s) ", yytext)); return 
VAR_IP4_ONLY;}
@@ -214,6 +215,8 @@ server-count{COLON} { LEXOUT(("v(%s) ", yytext)); return 
VAR_SERVER_COUNT;}
 tcp-count{COLON}       { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_COUNT;}
 tcp-query-count{COLON} { LEXOUT(("v(%s) ", yytext)); return 
VAR_TCP_QUERY_COUNT;}
 tcp-timeout{COLON}     { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_TIMEOUT;}
+tcp-mss{COLON}         { LEXOUT(("v(%s) ", yytext)); return VAR_TCP_MSS;}
+outgoing-tcp-mss{COLON}        { LEXOUT(("v(%s) ", yytext)); return 
VAR_OUTGOING_TCP_MSS;}
 ipv4-edns-size{COLON}  { LEXOUT(("v(%s) ", yytext)); return 
VAR_IPV4_EDNS_SIZE;}
 ipv6-edns-size{COLON}  { LEXOUT(("v(%s) ", yytext)); return 
VAR_IPV6_EDNS_SIZE;}
 pidfile{COLON}         { LEXOUT(("v(%s) ", yytext)); return VAR_PIDFILE;}
diff --git configparser.y configparser.y
index 36a3ddd..1d824d1 100644
--- configparser.y
+++ configparser.y
@@ -51,6 +51,7 @@ extern config_parser_state_t* cfg_parser;
 %token VAR_CHROOT VAR_USERNAME VAR_ZONESDIR VAR_XFRDFILE VAR_DIFFFILE
 %token VAR_XFRD_RELOAD_TIMEOUT VAR_TCP_QUERY_COUNT VAR_TCP_TIMEOUT
 %token VAR_IPV4_EDNS_SIZE VAR_IPV6_EDNS_SIZE VAR_DO_IP4 VAR_DO_IP6
+%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_IP_FREEBIND
 %token VAR_ZONEFILE 
 %token VAR_ZONE
 %token VAR_ALLOW_NOTIFY VAR_REQUEST_XFR VAR_NOTIFY VAR_PROVIDE_XFR 
@@ -93,11 +94,12 @@ content_server: server_ip_address | server_ip_transparent | 
server_debug_mode |
        server_tcp_query_count | server_tcp_timeout | server_ipv4_edns_size |
        server_ipv6_edns_size | server_verbosity | server_hide_version |
        server_zonelistfile | server_xfrdir |
+       server_tcp_mss | server_outgoing_tcp_mss |
        server_rrl_size | server_rrl_ratelimit | server_rrl_slip | 
        server_rrl_ipv4_prefix_length | server_rrl_ipv6_prefix_length | 
server_rrl_whitelist_ratelimit |
        server_zonefiles_check | server_do_ip4 | server_do_ip6 |
        server_zonefiles_write | server_log_time_ascii | server_round_robin |
-       server_reuseport | server_version;
+       server_reuseport | server_version | server_ip_freebind;
 server_ip_address: VAR_IP_ADDRESS STRING 
        { 
                OUTYY(("P(server_ip_address:%s)\n", $2)); 
@@ -128,6 +130,14 @@ server_ip_transparent: VAR_IP_TRANSPARENT STRING
                else cfg_parser->opt->ip_transparent = (strcmp($2, "yes")==0);
        }
        ;
+server_ip_freebind: VAR_IP_FREEBIND STRING 
+       { 
+               OUTYY(("P(server_ip_freebind:%s)\n", $2)); 
+               if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+                       yyerror("expected yes or no.");
+               else cfg_parser->opt->ip_freebind = (strcmp($2, "yes")==0);
+       }
+       ;
 server_debug_mode: VAR_DEBUG_MODE STRING 
        { 
                OUTYY(("P(server_debug_mode:%s)\n", $2)); 
@@ -381,6 +391,22 @@ server_tcp_timeout: VAR_TCP_TIMEOUT STRING
                cfg_parser->opt->tcp_timeout = atoi($2);
        }
        ;
+server_tcp_mss: VAR_TCP_MSS STRING
+       {
+               OUTYY(("P(server_tcp_mss:%s)\n", $2));
+               if(atoi($2) == 0 && strcmp($2, "0") != 0)
+                       yyerror("number expected");
+               cfg_parser->opt->tcp_mss = atoi($2);
+       }
+       ;
+server_outgoing_tcp_mss: VAR_OUTGOING_TCP_MSS STRING
+       {
+               OUTYY(("P(server_outgoing_tcp_mss:%s)\n", $2));
+               if(atoi($2) == 0 && strcmp($2, "0") != 0)
+                       yyerror("number expected");
+               cfg_parser->opt->outgoing_tcp_mss = atoi($2);
+       }
+       ;
 server_ipv4_edns_size: VAR_IPV4_EDNS_SIZE STRING
        { 
                OUTYY(("P(server_ipv4_edns_size:%s)\n", $2)); 
diff --git configure configure
index 68bdc87..a525e08 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.7.
+# Generated by GNU Autoconf 2.69 for NSD 4.1.10.
 #
 # Report bugs to <[email protected]>.
 #
@@ -580,8 +580,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='NSD'
 PACKAGE_TARNAME='nsd'
-PACKAGE_VERSION='4.1.7'
-PACKAGE_STRING='NSD 4.1.7'
+PACKAGE_VERSION='4.1.10'
+PACKAGE_STRING='NSD 4.1.10'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL=''
 
@@ -1283,7 +1283,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.7 to adapt to many kinds of systems.
+\`configure' configures NSD 4.1.10 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1344,7 +1344,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of NSD 4.1.7:";;
+     short | recursive ) echo "Configuration of NSD 4.1.10:";;
    esac
   cat <<\_ACEOF
 
@@ -1360,7 +1360,7 @@ Optional Features:
   --disable-largefile     omit support for large files
   --enable-recvmmsg       Enable recvmmsg and sendmmsg compilation, faster but
                           some kernel versions may have implementation
-                          problems
+                          problems for IPv6
   --enable-root-server    Configure NSD as a root server
   --disable-ipv6          Disables IPv6 support
   --enable-bind8-stats    Enables BIND8 like NSTATS & XSTATS and statistics in
@@ -1487,7 +1487,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-NSD configure 4.1.7
+NSD configure 4.1.10
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2196,7 +2196,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.7, which was
+It was created by NSD $as_me 4.1.10, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -5067,7 +5067,7 @@ main ()
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
 
-            if $CC $CFLAGS -o conftest conftest.c 2>&1 | grep "warning: no 
debug symbols in executable" >/dev/null; then
+            if $CC $CFLAGS -o conftest conftest.c 2>&1 | $GREP -e "warning: no 
debug symbols in executable" -e "warning: object" >/dev/null; then
                 CFLAGS="$BAKCFLAGS"
                 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -6027,7 +6027,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 stddef.h sys/param.h sys/socket.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 syslog.h 
unistd.h sys/select.h stdarg.h stdint.h netdb.h sys/bitypes.h tcpd.h glob.h 
grp.h endian.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"
@@ -7195,6 +7195,25 @@ fi
 
 fi
 
+ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimensec" 
"ac_cv_member_struct_stat_st_mtimensec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_mtimensec" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim.tv_nsec" 
"ac_cv_member_struct_stat_st_mtim_tv_nsec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_mtim_tv_nsec" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1
+_ACEOF
+
+
+fi
+
 
 # Checks for library functions.
 for ac_header in unistd.h
@@ -7921,7 +7940,7 @@ _ACEOF
 fi
 done
 
-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
+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
 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"
@@ -8803,10 +8822,74 @@ fi
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
+
+       # Check for -pthread
+       BAKLIBS="$LIBS"
+       LIBS="-lcrypto $LIBS"
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+               int HMAC_Update(void);
+               (void)HMAC_Update();
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+else
+
+                               BAKCFLAGS="$CFLAGS"
+               CFLAGS="$CFLAGS -pthread"
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libcrypto 
needs -pthread" >&5
+$as_echo_n "checking if libcrypto needs -pthread... " >&6; }
+               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 HMAC_Update ();
+int
+main ()
+{
+return HMAC_Update ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; 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; }
+                                               CFLAGS="$BAKCFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+       LIBS="$BAKLIBS"
+
        if test -n "$ssldir"; then
-            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 
HMAC_CTX_init in -lcrypto" >&5
-$as_echo_n "checking for HMAC_CTX_init in -lcrypto... " >&6; }
-if ${ac_cv_lib_crypto_HMAC_CTX_init+:} false; then :
+            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_Update 
in -lcrypto" >&5
+$as_echo_n "checking for HMAC_Update in -lcrypto... " >&6; }
+if ${ac_cv_lib_crypto_HMAC_Update+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -8820,27 +8903,27 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char HMAC_CTX_init ();
+char HMAC_Update ();
 int
 main ()
 {
-return HMAC_CTX_init ();
+return HMAC_Update ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_crypto_HMAC_CTX_init=yes
+  ac_cv_lib_crypto_HMAC_Update=yes
 else
-  ac_cv_lib_crypto_HMAC_CTX_init=no
+  ac_cv_lib_crypto_HMAC_Update=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: 
$ac_cv_lib_crypto_HMAC_CTX_init" >&5
-$as_echo "$ac_cv_lib_crypto_HMAC_CTX_init" >&6; }
-if test "x$ac_cv_lib_crypto_HMAC_CTX_init" = xyes; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: 
$ac_cv_lib_crypto_HMAC_Update" >&5
+$as_echo "$ac_cv_lib_crypto_HMAC_Update" >&6; }
+if test "x$ac_cv_lib_crypto_HMAC_Update" = xyes; then :
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBCRYPTO 1
 _ACEOF
@@ -8895,6 +8978,18 @@ fi
 
 done
 
+       for ac_func in HMAC_CTX_reset HMAC_CTX_new
+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"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
 else
        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No SSL, therefore 
remote-control is disabled" >&5
 $as_echo "$as_me: WARNING: No SSL, therefore remote-control is disabled" >&2;}
@@ -9586,7 +9681,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.7, which was
+This file was extended by NSD $as_me 4.1.10, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9648,7 +9743,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.7
+NSD config.status 4.1.10
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git configure.ac configure.ac
index c04deac..4c451bd 100644
--- configure.ac
+++ configure.ac
@@ -4,7 +4,7 @@ dnl
 
 sinclude(acx_nlnetlabs.m4)
 
-AC_INIT(NSD,4.1.7,[email protected])
+AC_INIT(NSD,4.1.10,[email protected])
 AC_CONFIG_HEADER([config.h])
 
 CFLAGS="$CFLAGS"
@@ -415,7 +415,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 stddef.h sys/param.h sys/socket.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 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_DEFUN([CHECK_VALIST_DEF],
 [
@@ -585,6 +585,7 @@ AC_CHECK_TYPE(in_addr_t, [], [AC_DEFINE([in_addr_t], 
[uint32_t], [in_addr_t])],
 # include <netinet/in.h>
 #endif])
 ACX_CHECK_SS_FAMILY
+AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec])
 
 # Checks for library functions.
 AC_FUNC_CHOWN
@@ -596,9 +597,9 @@ AC_SYS_LARGEFILE
 AC_CHECK_SIZEOF(void*)
 AC_CHECK_SIZEOF(off_t)
 AC_CHECK_FUNCS([arc4random arc4random_uniform])
-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])
+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])
 
-AC_ARG_ENABLE(recvmmsg, AC_HELP_STRING([--enable-recvmmsg], [Enable recvmmsg 
and sendmmsg compilation, faster but some kernel versions may have 
implementation problems]))
+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]))
 case "$enable_recvmmsg" in
         yes)
                AC_CHECK_FUNC([recvmmsg], [
@@ -829,8 +830,30 @@ AC_SUBST(ratelimit_default)
 CHECK_SSL
 if test x$HAVE_SSL = x"yes"; then
        ACX_LIB_SSL
+
+       # Check for -pthread
+       BAKLIBS="$LIBS"
+       LIBS="-lcrypto $LIBS"
+       AC_TRY_LINK([], [
+               int HMAC_Update(void);
+               (void)HMAC_Update();
+       ], [],[
+               dnl so link fails for HMAC_Update, try with -pthread.
+               BAKCFLAGS="$CFLAGS"
+               CFLAGS="$CFLAGS -pthread"
+               AC_MSG_CHECKING([if libcrypto needs -pthread])
+               AC_TRY_LINK_FUNC([HMAC_Update], [
+                       AC_MSG_RESULT([yes])
+               ] , [
+                       AC_MSG_RESULT([no])
+                       dnl restore the nonpthread value
+                       CFLAGS="$BAKCFLAGS"
+               ])
+       ])
+       LIBS="$BAKLIBS"
+
        if test -n "$ssldir"; then 
-            AC_CHECK_LIB(crypto, HMAC_CTX_init,, [
+            AC_CHECK_LIB(crypto, HMAC_Update,, [
                     AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 
or higher is required])
                 ])
        fi
@@ -839,6 +862,7 @@ if test x$HAVE_SSL = x"yes"; then
        AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
        AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
        AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
+       AC_CHECK_FUNCS([HMAC_CTX_reset HMAC_CTX_new])
 else
        AC_MSG_WARN([No SSL, therefore remote-control is disabled])
 fi
@@ -894,6 +918,9 @@ AH_BOTTOM([
 #  ifndef _BSD_SOURCE
 #    define _BSD_SOURCE 1
 #  endif
+#  ifndef _DEFAULT_SOURCE
+#    define _DEFAULT_SOURCE 1
+#  endif
 #  ifndef __EXTENSIONS__
 #    define __EXTENSIONS__ 1
 #  endif 
@@ -938,6 +965,10 @@ AH_BOTTOM([
 #include <netinet/in.h>
 #endif
 
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
 #ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
diff --git dbaccess.c dbaccess.c
index 86891f2..cc49a51 100644
--- dbaccess.c
+++ dbaccess.c
@@ -271,7 +271,8 @@ namedb_zone_create(namedb_type* db, const dname_type* dname,
        zone->opts = zo;
        zone->filename = NULL;
        zone->logstr = NULL;
-       zone->mtime = 0;
+       zone->mtime.tv_sec = 0;
+       zone->mtime.tv_nsec = 0;
        zone->zonestatid = 0;
        zone->is_secure = 0;
        zone->is_changed = 0;
@@ -491,17 +492,25 @@ namedb_open (const char* filename, nsd_options_t* opt)
 }
 
 /** the the file mtime stat (or nonexist or error) */
-static int
-file_get_mtime(const char* file, time_t* mtime, int* nonexist)
+int
+file_get_mtime(const char* file, struct timespec* mtime, int* nonexist)
 {
        struct stat s;
        if(stat(file, &s) != 0) {
-               *mtime = 0;
+               mtime->tv_sec = 0;
+               mtime->tv_nsec = 0;
                *nonexist = (errno == ENOENT);
                return 0;
        }
        *nonexist = 0;
-       *mtime = s.st_mtime;
+       mtime->tv_sec = s.st_mtime;
+#ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
+       mtime->tv_nsec = s.st_mtimensec;
+#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
+       mtime->tv_nsec = s.st_mtim.tv_nsec;
+#else
+       mtime->tv_nsec = 0;
+#endif
        return 1;
 }
 
@@ -509,12 +518,14 @@ void
 namedb_read_zonefile(struct nsd* nsd, struct zone* zone, udb_base* taskudb,
        udb_ptr* last_task)
 {
-       time_t mtime = 0;
+       struct timespec mtime;
        int nonexist = 0;
        unsigned int errors;
        const char* fname;
        if(!nsd->db || !zone || !zone->opts || !zone->opts->pattern->zonefile)
                return;
+       mtime.tv_sec = 0;
+       mtime.tv_nsec = 0;
        fname = config_make_zonefile(zone->opts, nsd);
        if(!file_get_mtime(fname, &mtime, &nonexist)) {
                if(nonexist) {
@@ -527,20 +538,21 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, 
udb_base* taskudb,
                return;
        } else {
                const char* zone_fname = zone->filename;
-               time_t zone_mtime = zone->mtime;
+               struct timespec zone_mtime = zone->mtime;
                if(nsd->db->udb) {
                        zone_fname = udb_zone_get_file_str(nsd->db->udb,
                                dname_name(domain_dname(zone->apex)),
                                domain_dname(zone->apex)->name_size);
-                       zone_mtime = (time_t)udb_zone_get_mtime(nsd->db->udb,
+                       udb_zone_get_mtime(nsd->db->udb,
                                dname_name(domain_dname(zone->apex)),
-                               domain_dname(zone->apex)->name_size);
+                               domain_dname(zone->apex)->name_size,
+                               &zone_mtime);
                }
                /* if no zone_fname, then it was acquired in zone transfer,
                 * see if the file is newer than the zone transfer
                 * (regardless if this is a different file), because the
                 * zone transfer is a different content source too */
-               if(!zone_fname && zone_mtime >= mtime) {
+               if(!zone_fname && timespec_compare(&zone_mtime, &mtime) >= 0) {
                        VERBOSITY(3, (LOG_INFO, "zonefile %s is older than "
                                "zone transfer in memory", fname));
                        return;
@@ -548,7 +560,8 @@ 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 && zone_mtime >= mtime) {
+                  strcmp(zone_fname, fname) == 0 &&
+                  timespec_compare(&zone_mtime, &mtime) == 0) {
                        VERBOSITY(3, (LOG_INFO, "zonefile %s is not modified",
                                fname));
                        return;
@@ -614,7 +627,8 @@ namedb_read_zonefile(struct nsd* nsd, struct zone* zone, 
udb_base* taskudb,
                zone->is_changed = 0;
                /* store zone into udb */
                if(nsd->db->udb) {
-                       if(!write_zone_to_udb(nsd->db->udb, zone, mtime, 
fname)) {
+                       if(!write_zone_to_udb(nsd->db->udb, zone, &mtime,
+                               fname)) {
                                log_msg(LOG_ERR, "failed to store zone in db");
                        } else {
                                VERBOSITY(2, (LOG_INFO, "zone %s written to db",
diff --git dbcreate.c dbcreate.c
index 24866af..ce21491 100644
--- dbcreate.c
+++ dbcreate.c
@@ -146,7 +146,7 @@ write_zone(udb_base* udb, udb_ptr* z, zone_type* zone)
 
 /** create and write a zone */
 int
-write_zone_to_udb(udb_base* udb, zone_type* zone, time_t mtime,
+write_zone_to_udb(udb_base* udb, zone_type* zone, struct timespec* mtime,
        const char* file_str)
 {
        udb_ptr z;
@@ -165,7 +165,8 @@ write_zone_to_udb(udb_base* udb, zone_type* zone, time_t 
mtime,
                }
        }
        /* set mtime */
-       ZONE(&z)->mtime = (uint64_t)mtime;
+       ZONE(&z)->mtime = (uint64_t)mtime->tv_sec;
+       ZONE(&z)->mtime_nsec = (uint64_t)mtime->tv_nsec;
        ZONE(&z)->is_changed = 0;
        udb_zone_set_log_str(udb, &z, NULL);
        udb_zone_set_file_str(udb, &z, file_str);
@@ -350,6 +351,7 @@ namedb_write_zonefile(struct nsd* nsd, zone_options_t* zopt)
        if(notexist || zone->is_changed) {
                char logs[4096];
                char bakfile[4096];
+               struct timespec mtime;
                udb_ptr zudb;
                if(nsd->db->udb) {
                        if(!udb_zone_search(nsd->db->udb, &zudb,
@@ -384,13 +386,19 @@ namedb_write_zonefile(struct nsd* nsd, zone_options_t* 
zopt)
                        return;
                }
                zone->is_changed = 0;
+               /* fetch the mtime of the just created zonefile so we
+                * do not waste effort reading it back in */
+               if(!file_get_mtime(zfile, &mtime, &notexist)) {
+                       get_time(&mtime);
+               }
                if(nsd->db->udb) {
-                       ZONE(&zudb)->mtime = (uint64_t)time(0);
+                       ZONE(&zudb)->mtime = (uint64_t)mtime.tv_sec;
+                       ZONE(&zudb)->mtime_nsec = (uint64_t)mtime.tv_nsec;
                        ZONE(&zudb)->is_changed = 0;
                        udb_zone_set_log_str(nsd->db->udb, &zudb, NULL);
                        udb_ptr_unlink(&zudb, nsd->db->udb);
                } else {
-                       zone->mtime = time(0);
+                       zone->mtime = mtime;
                        if(zone->filename)
                                region_recycle(nsd->db->region, zone->filename,
                                        strlen(zone->filename)+1);
diff --git difffile.c difffile.c
index 4196f79..b2325c5 100644
--- difffile.c
+++ difffile.c
@@ -1378,11 +1378,13 @@ apply_ixfr_for_zone(nsd_type* nsd, zone_type* zonedb, 
FILE* in,
                if(nsd->db->udb) {
                        ZONE(&z)->is_changed = 1;
                        ZONE(&z)->mtime = time_end_0;
+                       ZONE(&z)->mtime_nsec = time_end_1*1000;
                        udb_zone_set_log_str(nsd->db->udb, &z, log_buf);
                        udb_zone_set_file_str(nsd->db->udb, &z, NULL);
                        udb_ptr_unlink(&z, nsd->db->udb);
                } else {
-                       zonedb->mtime = time_end_0;
+                       zonedb->mtime.tv_sec = time_end_0;
+                       zonedb->mtime.tv_nsec = time_end_1*1000;
                        if(zonedb->logstr)
                                region_recycle(nsd->db->region, zonedb->logstr,
                                        strlen(zonedb->logstr)+1);
diff --git dns.c dns.c
index 2ba99d3..037cd4c 100644
--- dns.c
+++ dns.c
@@ -300,7 +300,8 @@ static rrtype_descriptor_type 
rrtype_descriptors[(RRTYPE_DESCRIPTORS_LENGTH+1)]
        /* 61 */
        { 61, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
        /* 62 */
-       { 62, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
+       { TYPE_CSYNC, "CSYNC", T_CSYNC, 3, 3, { RDATA_WF_LONG, RDATA_WF_SHORT,
+        RDATA_WF_BINARY }, { RDATA_ZF_LONG, RDATA_ZF_SHORT, RDATA_ZF_NSEC } },
        /* 63 */
        { 63, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
        /* 64 */
diff --git dns.h dns.h
index 3e9e88c..810cd70 100644
--- dns.h
+++ dns.h
@@ -138,6 +138,7 @@ typedef enum nsd_rc nsd_rc_type;
 #define TYPE_TLSA      52      /* RFC 6698 */
 #define TYPE_CDS       59      /* RFC 7344 */
 #define TYPE_CDNSKEY   60      /* RFC 7344 */
+#define TYPE_CSYNC     62      /* RFC 7477 */
 
 #define TYPE_SPF        99      /* RFC 4408 */
 
diff --git namedb.c namedb.c
index 96aec38..db90965 100644
--- namedb.c
+++ namedb.c
@@ -561,6 +561,18 @@ domain_find_ns_rrsets(domain_type* domain, zone_type* 
zone, rrset_type **ns)
        return NULL;
 }
 
+domain_type *
+find_dname_above(domain_type* domain, zone_type* zone)
+{
+       domain_type* d = domain->parent;
+       while(d && d != zone->apex) {
+               if(domain_find_rrset(d, zone, TYPE_DNAME))
+                       return d;
+               d = d->parent;
+       }
+       return NULL;
+}
+
 int
 domain_is_glue(domain_type* domain, zone_type* zone)
 {
diff --git namedb.h namedb.h
index d264c68..ca46477 100644
--- namedb.h
+++ namedb.h
@@ -127,7 +127,7 @@ struct zone
        struct zone_options* opts;
        char*        filename; /* set if read from file, which file */
        char*        logstr; /* set for zone xfer, the log string */
-       time_t       mtime; /* time of last modification */
+       struct timespec mtime; /* time of last modification */
        unsigned     zonestatid; /* array index for zone stats */
        unsigned     is_secure : 1; /* zone uses DNSSEC */
        unsigned     is_ok : 1; /* zone has not expired. */
@@ -235,6 +235,8 @@ zone_type* domain_find_zone(namedb_type* db, domain_type* 
domain);
 zone_type* domain_find_parent_zone(zone_type* zone);
 
 domain_type* domain_find_ns_rrsets(domain_type* domain, zone_type* zone, 
rrset_type **ns);
+/* find DNAME rrset in domain->parent or higher and return that domain */
+domain_type * find_dname_above(domain_type* domain, zone_type* zone);
 
 int domain_is_glue(domain_type* domain, zone_type* zone);
 
@@ -326,8 +328,8 @@ void domain_table_deldomain(namedb_type* db, domain_type* 
domain);
 /** dbcreate.c */
 int udb_write_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr);
 void udb_del_rr(struct udb_base* udb, struct udb_ptr* z, rr_type* rr);
-int write_zone_to_udb(struct udb_base* udb, zone_type* zone, time_t mtime,
-       const char* file_str);
+int write_zone_to_udb(struct udb_base* udb, zone_type* zone,
+       struct timespec* mtime, const char* file_str);
 /** marshal rdata into buffer, must be MAX_RDLENGTH in size */
 size_t rr_marshal_rdata(rr_type* rr, uint8_t* rdata, size_t sz);
 /* dbaccess.c */
@@ -354,6 +356,7 @@ void namedb_zone_delete(namedb_type* db, zone_type* zone);
 void namedb_write_zonefile(struct nsd* nsd, struct zone_options* zopt);
 void namedb_write_zonefiles(struct nsd* nsd, struct nsd_options* options);
 int create_dirs(const char* path);
+int file_get_mtime(const char* file, struct timespec* mtime, int* nonexist);
 void allocate_domain_nsec3(domain_table_type *table, domain_type *result);
 
 static inline int
diff --git nsd-4.1.10.tar.gz nsd-4.1.10.tar.gz
new file mode 100644
index 0000000..53f0de4
Binary files /dev/null and nsd-4.1.10.tar.gz differ
diff --git nsd-checkconf.8.in nsd-checkconf.8.in
index 9bf8306..2425e69 100644
--- nsd-checkconf.8.in
+++ nsd-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-checkconf" "8" "Dec 10, 2015" "NLnet Labs" "nsd 4.1.7"
+.TH "nsd\-checkconf" "8" "Jun 14, 2016" "NLnet Labs" "nsd 4.1.10"
 .\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
diff --git nsd-checkconf.c nsd-checkconf.c
index 6cbe71e..e5f669f 100644
--- nsd-checkconf.c
+++ nsd-checkconf.c
@@ -341,6 +341,7 @@ config_print_zone(nsd_options_t* opt, const char* k, int s, 
const char *o,
                SERV_GET_IP(ip_address, ip_addresses, o);
                /* bin */
                SERV_GET_BIN(ip_transparent, o);
+               SERV_GET_BIN(ip_freebind, o);
                SERV_GET_BIN(debug_mode, o);
                SERV_GET_BIN(do_ip4, o);
                SERV_GET_BIN(do_ip6, o);
@@ -368,6 +369,8 @@ config_print_zone(nsd_options_t* opt, const char* k, int s, 
const char *o,
                SERV_GET_INT(tcp_count, o);
                SERV_GET_INT(tcp_query_count, o);
                SERV_GET_INT(tcp_timeout, o);
+               SERV_GET_INT(tcp_mss, o);
+               SERV_GET_INT(outgoing_tcp_mss, o);
                SERV_GET_INT(ipv4_edns_size, o);
                SERV_GET_INT(ipv6_edns_size, o);
                SERV_GET_INT(statistics, o);
@@ -442,6 +445,7 @@ config_test_print_server(nsd_options_t* opt)
        printf("server:\n");
        printf("\tdebug-mode: %s\n", opt->debug_mode?"yes":"no");
        printf("\tip-transparent: %s\n", opt->ip_transparent?"yes":"no");
+       printf("\tip-freebind: %s\n", opt->ip_freebind?"yes":"no");
        printf("\treuseport: %s\n", opt->reuseport?"yes":"no");
        printf("\tdo-ip4: %s\n", opt->do_ip4?"yes":"no");
        printf("\tdo-ip6: %s\n", opt->do_ip6?"yes":"no");
@@ -451,10 +455,12 @@ config_test_print_server(nsd_options_t* opt)
        print_string_var("version:", opt->version);
        print_string_var("nsid:", opt->nsid);
        print_string_var("logfile:", opt->logfile);
-       printf("\tserver_count: %d\n", opt->server_count);
-       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);
+       printf("\tserver-count: %d\n", opt->server_count);
+       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);
+       printf("\ttcp-mss: %d\n", opt->tcp_mss);
+       printf("\toutgoing-tcp-mss: %d\n", opt->outgoing_tcp_mss);
        printf("\tipv4-edns-size: %d\n", (int) opt->ipv4_edns_size);
        printf("\tipv6-edns-size: %d\n", (int) opt->ipv6_edns_size);
        print_string_var("pidfile:", opt->pidfile);
@@ -466,7 +472,7 @@ config_test_print_server(nsd_options_t* opt)
        print_string_var("xfrdfile:", opt->xfrdfile);
        print_string_var("zonelistfile:", opt->zonelistfile);
        print_string_var("xfrdir:", opt->xfrdir);
-       printf("\txfrd_reload_timeout: %d\n", opt->xfrd_reload_timeout);
+       printf("\txfrd-reload-timeout: %d\n", opt->xfrd_reload_timeout);
        printf("\tlog-time-ascii: %s\n", opt->log_time_ascii?"yes":"no");
        printf("\tround-robin: %s\n", opt->round_robin?"yes":"no");
        printf("\tverbosity: %d\n", opt->verbosity);
diff --git nsd-checkzone.8.in nsd-checkzone.8.in
index f58e0da..2be9443 100644
--- nsd-checkzone.8.in
+++ nsd-checkzone.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-checkzone" "8" "Dec 10, 2015" "NLnet Labs" "nsd 4.1.7"
+.TH "nsd\-checkzone" "8" "Jun 14, 2016" "NLnet Labs" "nsd 4.1.10"
 .\" Copyright (c) 2014, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
diff --git nsd-control.8.in nsd-control.8.in
index 4f6a590..bf8d90d 100644
--- nsd-control.8.in
+++ nsd-control.8.in
@@ -1,4 +1,4 @@
-.TH "nsd\-control" "8" "Dec 10, 2015" "NLnet Labs" "nsd 4.1.7"
+.TH "nsd\-control" "8" "Jun 14, 2016" "NLnet Labs" "nsd 4.1.10"
 .\" Copyright (c) 2011, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
diff --git nsd.8.in nsd.8.in
index 0ef0cfa..89afd9c 100644
--- nsd.8.in
+++ nsd.8.in
@@ -1,9 +1,9 @@
-.TH "NSD" "8" "Dec 10, 2015" "NLnet Labs" "NSD 4.1.7"
+.TH "NSD" "8" "Jun 14, 2016" "NLnet Labs" "NSD 4.1.10"
 .\" 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.7.
+\- Name Server Daemon (NSD) version 4.1.10.
 .SH "SYNOPSIS"
 .B nsd
 .RB [ \-4 ] 
@@ -115,7 +115,7 @@ Do not fork, stay in the foreground.
 Use the specified
 .I database
 instead of the default of
-.IR @dbfile@ .
+.IR '@dbfile@' .
 If a 
 .B zonesdir: 
 is specified in the config file this path can be relative to that 
@@ -224,7 +224,7 @@ SIGUSR1
 Dump BIND8\-style statistics into the log. Ignored otherwise.
 .SH "FILES"
 .TP
-@dbfile@
+"@dbfile@"
 default
 .B NSD
 database
diff --git nsd.c nsd.c
index 3f35f11..f964386 100644
--- nsd.c
+++ nsd.c
@@ -681,6 +681,8 @@ main(int argc, char *argv[])
        }
        nsd.tcp_timeout = nsd.options->tcp_timeout;
        nsd.tcp_query_count = nsd.options->tcp_query_count;
+       nsd.tcp_mss = nsd.options->tcp_mss;
+       nsd.outgoing_tcp_mss = nsd.options->outgoing_tcp_mss;
        nsd.ipv4_edns_size = nsd.options->ipv4_edns_size;
        nsd.ipv6_edns_size = nsd.options->ipv6_edns_size;
 
@@ -909,6 +911,7 @@ main(int argc, char *argv[])
                        VERBOSITY(2, (LOG_WARNING, "chown %s failed: %s",
                                nsd.log_filename, strerror(errno)));
        }
+       log_msg(LOG_NOTICE, "%s starting (%s)", argv0, PACKAGE_STRING);
 
        /* Do we have a running nsd? */
        if ((oldpid = readpid(nsd.pidfile)) == -1) {
diff --git nsd.conf.5.in nsd.conf.5.in
index 2fe1bf4..44493c7 100644
--- nsd.conf.5.in
+++ nsd.conf.5.in
@@ -1,4 +1,4 @@
-.TH "nsd.conf" "5" "Dec 10, 2015" "NLnet Labs" "nsd 4.1.7"
+.TH "nsd.conf" "5" "Jun 14, 2016" "NLnet Labs" "nsd 4.1.10"
 .\" Copyright (c) 2001\-2008, NLnet Labs. All rights reserved.
 .\" See LICENSE for the license.
 .SH "NAME"
@@ -169,6 +169,10 @@ Allows NSD to bind to non local addresses. This is useful 
to have NSD
 listen to IP addresses that are not (yet) added to the network interface, so
 that it can answer immediately when the address is added. Default is no.
 .TP
+.B ip\-freebind:\fR <yes or no>
+Set the IP_FREEBIND option to bind to nonlocal addresses and interfaces
+that are down.  Similar to ip\-transparent.  Default is no.
+.TP
 .B reuseport:\fR <yes or no>
 Use the SO_REUSEPORT socket option, and create file descriptors for every
 server in the server\-count.  This improves performance of the network
@@ -193,7 +197,7 @@ If yes, NSD listens to IPv6 connections.  Default yes.
 .TP
 .B database:\fR <filename>
 By default 
-.I @dbfile@
+.I '@dbfile@'
 is used. The specified file is used to store the compiled 
 zone information. Same as commandline option 
 .BR \-f.
@@ -247,6 +251,23 @@ Default is 0, meaning there is no maximum.
 .B tcp\-timeout:\fR <number>
 Overrides the default TCP timeout. This also affects zone transfers over TCP.
 .TP
+.B tcp-mss:\fR <number>
+Maximum segment size (MSS) of TCP socket on which the server responds
+to queries. Value lower than common MSS on Ethernet 
+(1220 for example) will address path MTU problem.
+Note that not all platform supports socket option to set MSS (TCP_MAXSEG).
+Default is system default MSS determined by interface MTU and
+negotiation between server and client.
+.TP
+.B outgoing\-tcp\-mss:\fR <number>
+Maximum segment size (MSS) of TCP socket for outgoing XFR request
+to other namesevers. Value lower than
+common MSS on Ethernet (1220 for example) will
+address path MTU problem.
+Note that not all platform supports socket option to set MSS (TCP_MAXSEG).
+Default is system default MSS determined by interface MTU and
+negotiation between NSD and other servers.
+.TP
 .B ipv4\-edns\-size:\fR <number>
 Preferred EDNS buffer size for IPv4.  Default 4096.
 .TP
@@ -795,7 +816,7 @@ also function as a resolver or cache. The configuration 
options that
 BIND9 has for the resolver or caching thus have no equivalents for NSD.
 .SH "FILES"
 .TP
-@dbfile@
+"@dbfile@"
 default
 .B NSD
 database
diff --git nsd.conf.sample.in nsd.conf.sample.in
index a78548e..48eef14 100644
--- nsd.conf.sample.in
+++ nsd.conf.sample.in
@@ -27,6 +27,9 @@ server:
        # Allow binding to non local addresses. Default no.
        # ip-transparent: no
 
+       # Allow binding to addresses that are down.  Default no.
+       # ip-freebind: no
+
        # use the reuseport socket option for performance. Default no.
        # reuseport: no
 
@@ -102,6 +105,14 @@ server:
        # Override the default (120 seconds) TCP timeout.
        # tcp-timeout: 120
 
+       # Maximum segment size (MSS) of TCP socket on which the server
+       # responds to queries. Default is 0, system default MSS.
+       # tcp-mss: 0
+
+       # Maximum segment size (MSS) of TCP socket for outgoing AXFR request.
+       # Default is 0, system default MSS.
+       # outgoing-tcp-mss: 0
+
        # Preferred EDNS buffer size for IPv4.
        # ipv4-edns-size: 4096
 
diff --git nsd.h nsd.h
index 8ebf1a2..290b065 100644
--- nsd.h
+++ nsd.h
@@ -223,6 +223,8 @@ struct      nsd
        int current_tcp_count;
        int tcp_query_count;
        int tcp_timeout;
+       int tcp_mss;
+       int outgoing_tcp_mss;
        size_t ipv4_edns_size;
        size_t ipv6_edns_size;
 
diff --git nsec3.c nsec3.c
index 92802bd..d4fd1a2 100644
--- nsec3.c
+++ nsec3.c
@@ -965,9 +965,20 @@ nsec3_answer_nodata(struct query* query, struct answer* 
answer,
                                original->nsec3->nsec3_cover);
        }
        else {  /* add nsec3 to prove rrset does not exist */
-               if(original->nsec3 && original->nsec3->nsec3_is_exact) {
+               if(original->nsec3) {
+                       if(!original->nsec3->nsec3_is_exact) {
+                               /* go up to an existing parent */
+                               while(original->parent && 
original->parent->nsec3 && !original->parent->nsec3->nsec3_is_exact)
+                                       original = original->parent;
+                       }
                        nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
                                original->nsec3->nsec3_cover);
+                       if(!original->nsec3->nsec3_is_exact) {
+                               if(original->parent && original->parent->nsec3 
&& original->parent->nsec3->nsec3_is_exact)
+                                   nsec3_add_rrset(query, answer, 
AUTHORITY_SECTION,
+                                       original->parent->nsec3->nsec3_cover);
+
+                       }
                }
        }
 }
@@ -1041,7 +1052,8 @@ nsec3_answer_authoritative(struct domain** match, struct 
query *query,
 #if 0
                query->qtype != TYPE_NSEC3 &&
 #endif
-               domain_has_only_NSEC3(*match, query->zone))
+               (domain_has_only_NSEC3(*match, query->zone) ||
+               !domain_find_any_rrset(*match, query->zone)))
        {
                /* this looks like a NSEC3 domain, but is actually an empty 
non-terminal. */
                nsec3_answer_nodata(query, answer, *match);
diff --git options.c options.c
index 8896851..349e271 100644
--- options.c
+++ options.c
@@ -49,6 +49,7 @@ nsd_options_create(region_type* region)
        opt->keys = rbtree_create(region, rbtree_strcmp);
        opt->ip_addresses = NULL;
        opt->ip_transparent = 0;
+       opt->ip_freebind = 0;
        opt->debug_mode = 0;
        opt->verbosity = 0;
        opt->hide_version = 0;
@@ -65,6 +66,8 @@ nsd_options_create(region_type* region)
        opt->tcp_count = 100;
        opt->tcp_query_count = 0;
        opt->tcp_timeout = TCP_TIMEOUT;
+       opt->tcp_mss = 0;
+       opt->outgoing_tcp_mss = 0;
        opt->ipv4_edns_size = EDNS_MAX_MESSAGE_LEN;
        opt->ipv6_edns_size = EDNS_MAX_MESSAGE_LEN;
        opt->pidfile = PIDFILE;
diff --git options.h options.h
index 34ed295..ceba624 100644
--- options.h
+++ options.h
@@ -60,6 +60,7 @@ struct nsd_options {
        ip_address_option_t* ip_addresses;
 
        int ip_transparent;
+       int ip_freebind;
        int debug_mode;
        int verbosity;
        int hide_version;
@@ -73,6 +74,8 @@ struct nsd_options {
        int tcp_count;
        int tcp_query_count;
        int tcp_timeout;
+       int tcp_mss;
+       int outgoing_tcp_mss;
        size_t ipv4_edns_size;
        size_t ipv6_edns_size;
        const char* pidfile;
diff --git query.c query.c
index 4f26112..f8a429c 100644
--- query.c
+++ query.c
@@ -609,6 +609,12 @@ struct additional_rr_types default_additional_rr_types[] = 
{
        { 0, (rr_section_type) 0 }
 };
 
+struct additional_rr_types swap_aaaa_additional_rr_types[] = {
+       { TYPE_AAAA, ADDITIONAL_A_SECTION },
+       { TYPE_A, ADDITIONAL_AAAA_SECTION },
+       { 0, (rr_section_type) 0 }
+};
+
 struct additional_rr_types rt_additional_rr_types[] = {
        { TYPE_A, ADDITIONAL_A_SECTION },
        { TYPE_AAAA, ADDITIONAL_AAAA_SECTION },
@@ -698,8 +704,11 @@ add_rrset(struct query   *query,
        result = answer_add_rrset(answer, section, owner, rrset);
        switch (rrset_rrtype(rrset)) {
        case TYPE_NS:
+               /* if query over IPv6, swap A and AAAA; put AAAA first */
                add_additional_rrsets(query, answer, rrset, 0, 1,
-                                     default_additional_rr_types);
+                       (query->addr.ss_family == AF_INET6)?
+                       swap_aaaa_additional_rr_types:
+                       default_additional_rr_types);
                break;
        case TYPE_MB:
                add_additional_rrsets(query, answer, rrset, 0, 0,
@@ -960,9 +969,6 @@ answer_domain(struct nsd* nsd, struct query *q, answer_type 
*answer,
                        zone_type* origzone = q->zone;
                        ++q->cname_count;
 
-                       while (!closest_encloser->is_existing)
-                               closest_encloser = closest_encloser->parent;
-
                        answer_lookup_zone(nsd, q, answer, 
closest_match->number,
                                             closest_match == closest_encloser,
                                             closest_match, closest_encloser,
@@ -1003,6 +1009,7 @@ answer_authoritative(struct nsd   *nsd,
 {
        domain_type *match;
        domain_type *original = closest_match;
+       domain_type *dname_ce;
        rrset_type *rrset;
 
 #ifdef NSEC3
@@ -1012,6 +1019,11 @@ answer_authoritative(struct nsd   *nsd,
                        closest_encloser = closest_encloser->parent;
        }
 #endif /* NSEC3 */
+       if((dname_ce = find_dname_above(closest_encloser, q->zone)) != NULL) {
+               /* occlude the found data, the DNAME is closest_encloser */
+               closest_encloser = dname_ce;
+               exact = 0;
+       }
 
        if (exact) {
                match = closest_match;
@@ -1053,8 +1065,6 @@ answer_authoritative(struct nsd   *nsd,
                                return;
                        }
 
-                       while (closest_encloser && 
!closest_encloser->is_existing)
-                               closest_encloser = closest_encloser->parent;
                        answer_lookup_zone(nsd, q, answer, newnum,
                                closest_match == closest_encloser,
                                closest_match, closest_encloser, newname);
@@ -1176,6 +1186,14 @@ answer_lookup_zone(struct nsd *nsd, struct query *q, 
answer_type *answer,
                        RCODE_SET(q->packet, RCODE_SERVFAIL);
                return;
        }
+       /* now move up the closest encloser until it exists, previous
+        * (possibly empty) closest encloser was useful to finding the zone
+        * (for empty zones too), but now we want actual data nodes */
+       if (closest_encloser && !closest_encloser->is_existing) {
+               exact = 0;
+               while (closest_encloser != NULL && 
!closest_encloser->is_existing)
+                       closest_encloser = closest_encloser->parent;
+       }
 
        /*
         * See RFC 4035 (DNSSEC protocol) section 3.1.4.1 Responding
@@ -1214,6 +1232,9 @@ answer_lookup_zone(struct nsd *nsd, struct query *q, 
answer_type *answer,
        } else {
                q->delegation_domain = domain_find_ns_rrsets(
                        closest_encloser, q->zone, &q->delegation_rrset);
+               if(q->delegation_domain && 
find_dname_above(q->delegation_domain, q->zone)) {
+                       q->delegation_domain = NULL; /* use higher DNAME */
+               }
 
                if (!q->delegation_domain
                    || (exact && q->qtype == TYPE_DS && closest_encloser == 
q->delegation_domain))
@@ -1244,15 +1265,6 @@ answer_query(struct nsd *nsd, struct query *q)
        answer_init(&answer);
 
        exact = namedb_lookup(nsd->db, q->qname, &closest_match, 
&closest_encloser);
-       if (!closest_encloser->is_existing) {
-               exact = 0;
-               while (closest_encloser != NULL && 
!closest_encloser->is_existing)
-                       closest_encloser = closest_encloser->parent;
-       }
-       if(!closest_encloser) {
-               RCODE_SET(q->packet, RCODE_SERVFAIL);
-               return;
-       }
 
        answer_lookup_zone(nsd, q, &answer, 0, exact, closest_match,
                closest_encloser, q->qname);
diff --git rrl.c rrl.c
index 8358ea5..2a7ca4f 100644
--- rrl.c
+++ rrl.c
@@ -449,7 +449,9 @@ int rrl_process_query(query_type* query)
 query_state_type rrl_slip(query_type* query)
 {
        /* discard number the packets, randomly */
-#ifdef HAVE_ARC4RANDOM
+#ifdef HAVE_ARC4RANDOM_UNIFORM
+       if((rrl_slip_ratio > 0) && ((rrl_slip_ratio == 1) || 
((arc4random_uniform(rrl_slip_ratio)) == 0))) {
+#elif HAVE_ARC4RANDOM
        if((rrl_slip_ratio > 0) && ((rrl_slip_ratio == 1) || ((arc4random() % 
rrl_slip_ratio) == 0))) {
 #else
        if((rrl_slip_ratio > 0) && ((rrl_slip_ratio == 1) || ((random() % 
rrl_slip_ratio) == 0))) {
diff --git server.c server.c
index 2b3be10..530b443 100644
--- server.c
+++ server.c
@@ -560,7 +560,7 @@ server_init_ifs(struct nsd *nsd, size_t from, size_t to, 
int* reuseport_works)
 {
        struct addrinfo* addr;
        size_t i;
-#if defined(SO_REUSEPORT) || defined(SO_REUSEADDR) || (defined(INET6) && 
(defined(IPV6_V6ONLY) || defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU) || 
defined(IP_TRANSPARENT)))
+#if defined(SO_REUSEPORT) || defined(SO_REUSEADDR) || (defined(INET6) && 
(defined(IPV6_V6ONLY) || defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU) || 
defined(IP_TRANSPARENT)) || defined(IP_FREEBIND))
        int on = 1;
 #endif
 
@@ -734,6 +734,15 @@ server_init_ifs(struct nsd *nsd, size_t from, size_t to, 
int* reuseport_works)
                }
 
                /* Bind it... */
+               if (nsd->options->ip_freebind) {
+#ifdef IP_FREEBIND
+                       if (setsockopt(nsd->udp[i].s, IPPROTO_IP, IP_FREEBIND, 
&on, sizeof(on)) < 0) {
+                               log_msg(LOG_ERR, "setsockopt(...,IP_FREEBIND, 
...) failed for udp: %s",
+                                       strerror(errno));
+                       }
+#endif /* IP_FREEBIND */
+               }
+
                if (nsd->options->ip_transparent) {
 #ifdef IP_TRANSPARENT
                        if (setsockopt(nsd->udp[i].s, IPPROTO_IP, 
IP_TRANSPARENT, &on, sizeof(on)) < 0) {
@@ -832,6 +841,21 @@ server_init_ifs(struct nsd *nsd, size_t from, size_t to, 
int* reuseport_works)
 # endif
                }
 #endif
+               /* set maximum segment size to tcp socket */
+               if(nsd->tcp_mss > 0) {
+#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
+                       if(setsockopt(nsd->tcp[i].s, IPPROTO_TCP, TCP_MAXSEG,
+                                       (void*)&nsd->tcp_mss,
+                                       sizeof(nsd->tcp_mss)) < 0) {
+                               log_msg(LOG_ERR,
+                                       "setsockopt(...,TCP_MAXSEG,...)"
+                                       " failed for tcp: %s", strerror(errno));
+                       }
+#else
+                       log_msg(LOG_ERR, "setsockopt(TCP_MAXSEG) unsupported");
+#endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */
+               }
+
                /* set it nonblocking */
                /* (StevensUNP p463), if tcp listening socket is blocking, then
                   it may block in accept, even if select() says readable. */
@@ -840,6 +864,15 @@ server_init_ifs(struct nsd *nsd, size_t from, size_t to, 
int* reuseport_works)
                }
 
                /* Bind it... */
+               if (nsd->options->ip_freebind) {
+#ifdef IP_FREEBIND
+                       if (setsockopt(nsd->tcp[i].s, IPPROTO_IP, IP_FREEBIND, 
&on, sizeof(on)) < 0) {
+                               log_msg(LOG_ERR, "setsockopt(...,IP_FREEBIND, 
...) failed for tcp: %s",
+                                       strerror(errno));
+                       }
+#endif /* IP_FREEBIND */
+               }
+
                if (nsd->options->ip_transparent) {
 #ifdef IP_TRANSPARENT
                        if (setsockopt(nsd->tcp[i].s, IPPROTO_IP, 
IP_TRANSPARENT, &on, sizeof(on)) < 0) {
@@ -2395,7 +2428,10 @@ cleanup_tcp_handler(struct tcp_handler_data* data)
         */
        if (slowaccept || data->nsd->current_tcp_count == 
data->nsd->maximum_tcp_count) {
                configure_handler_event_types(EV_READ|EV_PERSIST);
-               slowaccept = 0;
+               if(slowaccept) {
+                       event_del(&slowaccept_event);
+                       slowaccept = 0;
+               }
        }
        --data->nsd->current_tcp_count;
        assert(data->nsd->current_tcp_count >= 0);
diff --git tsig-openssl.c tsig-openssl.c
index 1088573..62203dc 100644
--- tsig-openssl.c
+++ tsig-openssl.c
@@ -83,16 +83,28 @@ static void
 cleanup_context(void *data)
 {
        HMAC_CTX *context = (HMAC_CTX *) data;
+#ifdef HAVE_HMAC_CTX_NEW
+       HMAC_CTX_free(context);
+#else
        HMAC_CTX_cleanup(context);
+       free(context);
+#endif
 }
 
 static void *
 create_context(region_type *region)
 {
-       HMAC_CTX *context
-               = (HMAC_CTX *) region_alloc(region, sizeof(HMAC_CTX));
+#ifdef HAVE_HMAC_CTX_NEW
+       HMAC_CTX *context = HMAC_CTX_new();
+#else
+       HMAC_CTX *context = (HMAC_CTX *) malloc(sizeof(HMAC_CTX));
+#endif
        region_add_cleanup(region, cleanup_context, context);
+#ifdef HAVE_HMAC_CTX_RESET
+       HMAC_CTX_reset(context);
+#else
        HMAC_CTX_init(context);
+#endif
        return context;
 }
 
diff --git udb.h udb.h
index 049760d..4cbe403 100644
--- udb.h
+++ udb.h
@@ -342,7 +342,7 @@ struct udb_alloc {
 /** magic string that starts an UDB file, uint64_t, note first byte=0, to mark
  * header start as a chunk. */
 #define UDB_MAGIC (((uint64_t)'u'<<48)|((uint64_t)'d'<<40)|((uint64_t)'b' \
-       <<32)|((uint64_t)'v'<<24)|((uint64_t)'0'<<16)|((uint64_t)'a'<<8))
+       <<32)|((uint64_t)'v'<<24)|((uint64_t)'0'<<16)|((uint64_t)'b'<<8))
 
 /* UDB BASE */
 /**
diff --git udbzone.c udbzone.c
index 67de2db..30f1c4b 100644
--- udbzone.c
+++ udbzone.c
@@ -95,6 +95,7 @@ udb_zone_create(udb_base* udb, udb_ptr* result, const 
uint8_t* dname,
        ZONE(&z)->rr_count = 0;
        ZONE(&z)->expired = 0;
        ZONE(&z)->mtime = 0;
+       ZONE(&z)->mtime_nsec = 0;
        ZONE(&z)->namelen = dlen;
        memmove(ZONE(&z)->name, dname, dlen);
        if(!udb_radix_tree_create(udb, &dtree)) {
@@ -222,6 +223,7 @@ udb_zone_clear(udb_base* udb, udb_ptr* zone)
        ZONE(zone)->rr_count = 0;
        ZONE(zone)->expired = 0;
        ZONE(zone)->mtime = 0;
+       ZONE(zone)->mtime_nsec = 0;
        udb_ptr_unlink(&dtree, udb);
 }
 
@@ -255,15 +257,18 @@ udb_zone_search(udb_base* udb, udb_ptr* result, const 
uint8_t* dname,
        return 0;
 }
 
-uint64_t udb_zone_get_mtime(udb_base* udb, const uint8_t* dname, size_t dlen)
+void udb_zone_get_mtime(udb_base* udb, const uint8_t* dname, size_t dlen,
+       struct timespec* mtime)
 {
        udb_ptr z;
        if(udb_zone_search(udb, &z, dname, dlen)) {
-               uint64_t t = ZONE(&z)->mtime;
+               mtime->tv_sec = ZONE(&z)->mtime;
+               mtime->tv_nsec = ZONE(&z)->mtime_nsec;
                udb_ptr_unlink(&z, udb);
-               return t;
+               return;
        }
-       return 0;
+       mtime->tv_sec = 0;
+       mtime->tv_nsec = 0;
 }
 
 void udb_zone_set_log_str(udb_base* udb, udb_ptr* zone, const char* str)
diff --git udbzone.h udbzone.h
index eb81675..8169857 100644
--- udbzone.h
+++ udbzone.h
@@ -39,6 +39,8 @@ struct zone_d {
        udb_rel_ptr file_str;
        /** modification time, time when the zone data was changed */
        uint64_t mtime;
+       /** modification time, nsecs */
+       uint64_t mtime_nsec;
        /** number of RRsets in the zone */
        uint64_t rrset_count;
        /** number of RRs in the zone */
@@ -107,7 +109,8 @@ void udb_zone_delete(udb_base* udb, udb_ptr* zone);
 int udb_zone_search(udb_base* udb, udb_ptr* result, const uint8_t* dname,
        size_t dlen);
 /** get modification time for zone or 0 */
-uint64_t udb_zone_get_mtime(udb_base* udb, const uint8_t* dname, size_t dlen);
+void udb_zone_get_mtime(udb_base* udb, const uint8_t* dname, size_t dlen,
+       struct timespec* mtime);
 /** set log str in udb, or remove it */
 void udb_zone_set_log_str(udb_base* udb, udb_ptr* zone, const char* str);
 /** set file str in udb, or remove it */
diff --git util.c util.c
index ff54eda..db3d7ce 100644
--- util.c
+++ util.c
@@ -393,6 +393,28 @@ write_socket(int s, const void *buf, size_t size)
        return 1;
 }
 
+void get_time(struct timespec* t)
+{
+       struct timeval tv;
+#ifdef HAVE_CLOCK_GETTIME
+       /* first try nanosecond precision */
+       if(clock_gettime(CLOCK_REALTIME, t)>=0) {
+               return; /* success */
+       }
+       log_msg(LOG_ERR, "clock_gettime: %s", strerror(errno));
+#endif
+       /* try millisecond precision */
+       if(gettimeofday(&tv, NULL)>=0) {
+               t->tv_sec = tv.tv_sec;
+               t->tv_nsec = tv.tv_usec*1000;
+               return; /* success */
+       }
+       log_msg(LOG_ERR, "gettimeofday: %s", strerror(errno));
+       /* whole seconds precision */
+       t->tv_sec = time(0);
+       t->tv_nsec = 0;
+}
+
 int
 timespec_compare(const struct timespec *left,
                 const struct timespec *right)
diff --git util.h util.h
index 5c572e3..702674f 100644
--- util.h
+++ util.h
@@ -269,6 +269,8 @@ timeval_to_timespec(struct timespec *left,
        left->tv_nsec = 1000 * right->tv_usec;
 }
 
+/* get the time */
+void get_time(struct timespec* t);
 
 /*
  * Converts a string representation of a period of time into
diff --git xfrd-tcp.c xfrd-tcp.c
index 2949e5a..9bc01d3 100644
--- xfrd-tcp.c
+++ xfrd-tcp.c
@@ -13,6 +13,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include "nsd.h"
 #include "xfrd-tcp.h"
 #include "buffer.h"
 #include "packet.h"
@@ -524,6 +525,19 @@ xfrd_tcp_open(xfrd_tcp_set_t* set, struct 
xfrd_tcp_pipeline* tp,
                return 0;
        }
 
+       if(xfrd->nsd->outgoing_tcp_mss > 0) {
+#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
+               if(setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG,
+                       (void*)&xfrd->nsd->outgoing_tcp_mss,
+                       sizeof(xfrd->nsd->outgoing_tcp_mss)) < 0) {
+                       log_msg(LOG_ERR, "xfrd: setsockopt(TCP_MAXSEG)"
+                                       "failed: %s", strerror(errno));
+               }
+#else
+               log_msg(LOG_ERR, "setsockopt(TCP_MAXSEG) unsupported");
+#endif
+       }
+
        tp->ip_len = xfrd_acl_sockaddr_to(zone->master, &tp->ip);
 
        /* bind it */
diff --git xfrd.c xfrd.c
index 0413f4e..c2c75ed 100644
--- xfrd.c
+++ xfrd.c
@@ -724,9 +724,12 @@ xfrd_set_timer_retry(xfrd_zone_t* zone)
                /* if no information, use reasonable timeout */
                if(zone->fresh_xfr_timeout == 0)
                        zone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_START;
-#ifdef HAVE_ARC4RANDOM
+#ifdef HAVE_ARC4RANDOM_UNIFORM
                xfrd_set_timer(zone, zone->fresh_xfr_timeout
-                       + arc4random()%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);
@@ -1045,8 +1048,10 @@ xfrd_set_timer(xfrd_zone_t* zone, time_t t)
        /* only for times far in the future */
        if(t > 10) {
                time_t base = t*9/10;
-#ifdef HAVE_ARC4RANDOM
-               t = base + arc4random()%(t-base);
+#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
diff --git zparser.y zparser.y
index 6640400..d823478 100644
--- zparser.y
+++ zparser.y
@@ -68,6 +68,7 @@ nsec3_add_params(const char* hash_algo_str, const char* 
flag_str,
 %token <type> T_AXFR T_MAILB T_MAILA T_DS T_DLV T_SSHFP T_RRSIG T_NSEC T_DNSKEY
 %token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM T_TLSA T_URI
 %token <type> T_NID T_L32 T_L64 T_LP T_EUI48 T_EUI64 T_CAA T_CDS T_CDNSKEY
+%token <type> T_CSYNC
 
 /* other tokens */
 %token        DOLLAR_TTL DOLLAR_ORIGIN NL SP
@@ -632,6 +633,8 @@ type_and_rdata:
     |  T_CDS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
     |  T_CDNSKEY sp rdata_dnskey
     |  T_CDNSKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
+    |  T_CSYNC sp rdata_csync
+    |  T_CSYNC sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
     |  T_URI sp rdata_uri
     |  T_URI sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
     |  T_UTYPE sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
@@ -1050,6 +1053,17 @@ rdata_caa:       STR sp STR sp STR trail
     }
     ;
 
+/* RFC7477 */
+rdata_csync:   STR sp STR nsec_seq
+    {
+           zadd_rdata_wireformat(zparser_conv_serial(parser->region, $1.str));
+           zadd_rdata_wireformat(zparser_conv_short(parser->region, $3.str));
+           zadd_rdata_wireformat(zparser_conv_nsec(parser->region, nsecbits)); 
/* nsec bitlist */
+           memset(nsecbits, 0, sizeof(nsecbits));
+            nsec_highest_rcode = 0;
+    }
+    ;
+
 rdata_unknown: URR sp STR sp str_sp_seq trail
     {
            /* $2 is the number of octets, currently ignored */


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

Reply via email to